1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* When changing these, you must also update the assembler template
48 * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA 0x00
50 #define GPTRTAG_CODE 0x80
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
66 /* max_key keeps track of the largest label number used in
67 a function. This is then used to adjust the label offset
68 for the next function.
71 static int GpsuedoStkPtr=0;
72 static int pic14_inISR = 0;
74 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
75 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
76 const char *AopType(short type);
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
80 /* this is the down and dirty file with all kinds of
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
85 static char *zero = "#0x00";
86 static char *one = "#0x01";
87 static char *spname = "sp";
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic14;
93 //static char *accUse[] = {"a","b"};
95 //static short rbank = -1;
107 /* Resolved ifx structure. This structure stores information
108 about an iCode ifx that makes it easier to generate code.
110 typedef struct resolvedIfx {
111 symbol *lbl; /* pointer to a label */
112 int condition; /* true or false ifx */
113 int generated; /* set true when the code associated with the ifx
117 extern int pic14_ptrRegReq ;
118 extern int pic14_nRegs;
119 extern struct dbuf_s *codeOutBuf;
120 static void saverbank (int, iCode *,bool);
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
126 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
134 /*-----------------------------------------------------------------*/
135 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
136 /* exponent of 2 is returned, otherwise -1 is */
138 /* note that this is similar to the function `powof2' in SDCCsymt */
142 /*-----------------------------------------------------------------*/
143 static int my_powof2 (unsigned long num)
146 if( (num & (num-1)) == 0) {
159 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
166 ((result) ? AOP_SIZE(result) : 0),
167 ((left) ? AopType(AOP_TYPE(left)) : "-"),
168 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169 ((left) ? AOP_SIZE(left) : 0),
170 ((right) ? AopType(AOP_TYPE(right)) : "-"),
171 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
172 ((right) ? AOP_SIZE(right) : 0));
176 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
181 ((result) ? AopType(AOP_TYPE(result)) : "-"),
182 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
183 ((left) ? AopType(AOP_TYPE(left)) : "-"),
184 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
185 ((right) ? AopType(AOP_TYPE(right)) : "-"),
186 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
190 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 char lb[INITIAL_INLINEASM];
194 unsigned char *lbp = (unsigned char *)lb;
196 if(!debug_verbose && !options.debug)
203 sprintf(lb,"%s\t",inst);
205 sprintf(lb,"%s",inst);
206 vsprintf(lb+(strlen(lb)),fmt,ap);
210 while (isspace(*lbp)) lbp++;
213 lineCurr = (lineCurr ?
214 connectLine(lineCurr,newLineNode(lb)) :
215 (lineHead = newLineNode(lb)));
216 lineCurr->isInline = _G.inLine;
217 lineCurr->isDebug = _G.debugLine;
219 addpCode2pBlock(pb,newpCodeCharP(lb));
224 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
226 #if defined (HAVE_VSNPRINTF)
227 vsnprintf (buf, size, fmt, ap);
228 #elif defined (HAVE_VSPRINTF)
229 vsprintf (buf, size, fmt, ap);
230 if (strlen (buf) >= size)
232 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
234 #elif defined (HAVE_SNPRINTF)
235 snprintf (buf, size, "vs(n)printf required");
236 #elif defined (HAVE_SRINTF)
237 sprintf (buf, "vs(n)printf required");
238 if (strlen (buf) >= size)
240 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
243 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
247 void emitpComment (const char *fmt, ...)
254 Safe_vsnprintf (buffer, 4096, fmt, va);
255 //fprintf (stderr, "%s\n" ,buffer);
256 addpCode2pBlock (pb, newpCodeCharP (buffer));
259 Safe_vsnprintf (buffer, 4096, fmt, va);
260 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
266 void emitpLabel(int key)
268 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
271 /* gen.h defines a macro emitpcode that should be used to call emitpcode
272 * as this allows for easy debugging (ever asked the question: where was
273 * this instruction geenrated? Here is the answer... */
274 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
277 addpCode2pBlock(pb,newpCode(poc,pcop));
279 static int has_warned = 0;
281 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
284 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
289 void emitpcodeNULLop(PIC_OPCODE poc)
292 addpCode2pBlock(pb,newpCode(poc,NULL));
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitcode - writes the code into a file : for now it is simple */
299 /*-----------------------------------------------------------------*/
300 void pic14_emitcode (char *inst,char *fmt, ...)
303 char lb[INITIAL_INLINEASM];
310 sprintf(lb,"%s\t",inst);
312 sprintf(lb,"%s",inst);
313 vsprintf(lb+(strlen(lb)),fmt,ap);
317 while (isspace(*lbp)) lbp++;
320 lineCurr = (lineCurr ?
321 connectLine(lineCurr,newLineNode(lb)) :
322 (lineHead = newLineNode(lb)));
323 lineCurr->isInline = _G.inLine;
324 lineCurr->isDebug = _G.debugLine;
325 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
328 addpCode2pBlock(pb,newpCodeCharP(lb));
333 /*-----------------------------------------------------------------*/
334 /* pic14_emitDebuggerSymbol - associate the current code location */
335 /* with a debugger symbol */
336 /*-----------------------------------------------------------------*/
338 pic14_emitDebuggerSymbol (char * debugSym)
341 pic14_emitcode ("", ";%s ==.", debugSym);
346 /*-----------------------------------------------------------------*/
347 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
348 /*-----------------------------------------------------------------*/
349 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
351 bool r0iu = FALSE , r1iu = FALSE;
352 bool r0ou = FALSE , r1ou = FALSE;
354 /* the logic: if r0 & r1 used in the instruction
355 then we are in trouble otherwise */
357 /* first check if r0 & r1 are used by this
358 instruction, in which case we are in trouble */
359 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
360 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
365 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
366 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
368 /* if no usage of r0 then return it */
369 if (!r0iu && !r0ou) {
370 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
371 (*aopp)->type = AOP_R0;
373 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
376 /* if no usage of r1 then return it */
377 if (!r1iu && !r1ou) {
378 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
379 (*aopp)->type = AOP_R1;
381 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
384 /* now we know they both have usage */
385 /* if r0 not used in this instruction */
387 /* push it if not already pushed */
389 //pic14_emitcode ("push","%s",
390 // pic14_regWithIdx(R0_IDX)->dname);
394 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
395 (*aopp)->type = AOP_R0;
397 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
400 /* if r1 not used then */
403 /* push it if not already pushed */
405 //pic14_emitcode ("push","%s",
406 // pic14_regWithIdx(R1_IDX)->dname);
410 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
411 (*aopp)->type = AOP_R1;
412 return pic14_regWithIdx(R1_IDX);
416 /* I said end of world but not quite end of world yet */
417 /* if this is a result then we can push it on the stack*/
419 (*aopp)->type = AOP_STK;
423 /* other wise this is true end of the world */
424 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
425 "getFreePtr should never reach here");
430 /*-----------------------------------------------------------------*/
431 /* newAsmop - creates a new asmOp */
432 /*-----------------------------------------------------------------*/
433 asmop *newAsmop (short type)
437 aop = Safe_calloc(1,sizeof(asmop));
442 static void genSetDPTR(int n)
446 pic14_emitcode(";", "Select standard DPTR");
447 pic14_emitcode("mov", "dps, #0x00");
451 pic14_emitcode(";", "Select alternate DPTR");
452 pic14_emitcode("mov", "dps, #0x01");
456 /*-----------------------------------------------------------------*/
457 /* resolveIfx - converts an iCode ifx into a form more useful for */
458 /* generating code */
459 /*-----------------------------------------------------------------*/
460 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
465 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
467 resIfx->condition = 1; /* assume that the ifx is true */
468 resIfx->generated = 0; /* indicate that the ifx has not been used */
471 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
473 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
474 __FUNCTION__,__LINE__,resIfx->lbl->key);
478 resIfx->lbl = IC_TRUE(ifx);
480 resIfx->lbl = IC_FALSE(ifx);
481 resIfx->condition = 0;
485 DEBUGpic14_emitcode("; ***","ifx true is non-null");
487 DEBUGpic14_emitcode("; ***","ifx false is non-null");
491 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
494 /*-----------------------------------------------------------------*/
495 /* pointerCode - returns the code for a pointer type */
496 /*-----------------------------------------------------------------*/
498 static int pointerCode (sym_link *etype)
501 return PTR_TYPE(SPEC_OCLS(etype));
506 /*-----------------------------------------------------------------*/
507 /* aopForSym - for a true symbol */
508 /*-----------------------------------------------------------------*/
509 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
512 memmap *space= SPEC_OCLS(sym->etype);
514 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
515 /* if already has one */
520 /* assign depending on the storage class */
521 /* if it is on the stack or indirectly addressable */
522 /* space we need to assign either r0 or r1 to it */
523 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
524 sym->aop = aop = newAsmop(0);
525 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
526 aop->size = getSize(sym->type);
528 /* now assign the address of the variable to
529 the pointer register */
530 if (aop->type != AOP_STK) {
534 pic14_emitcode("push","acc");
536 pic14_emitcode("mov","a,_bp");
537 pic14_emitcode("add","a,#0x%02x",
539 ((char)(sym->stack - _G.nRegsSaved )) :
540 ((char)sym->stack)) & 0xff);
541 pic14_emitcode("mov","%s,a",
542 aop->aopu.aop_ptr->name);
545 pic14_emitcode("pop","acc");
547 pic14_emitcode("mov","%s,#%s",
548 aop->aopu.aop_ptr->name,
550 aop->paged = space->paged;
552 aop->aopu.aop_stk = sym->stack;
556 if (sym->onStack && options.stack10bit)
558 /* It's on the 10 bit stack, which is located in
562 //DEBUGpic14_emitcode(";","%d",__LINE__);
565 pic14_emitcode("push","acc");
567 pic14_emitcode("mov","a,_bp");
568 pic14_emitcode("add","a,#0x%02x",
570 ((char)(sym->stack - _G.nRegsSaved )) :
571 ((char)sym->stack)) & 0xff);
574 pic14_emitcode ("mov","dpx1,#0x40");
575 pic14_emitcode ("mov","dph1,#0x00");
576 pic14_emitcode ("mov","dpl1, a");
580 pic14_emitcode("pop","acc");
582 sym->aop = aop = newAsmop(AOP_DPTR2);
583 aop->size = getSize(sym->type);
588 //DEBUGpic14_emitcode(";","%d",__LINE__);
589 /* if in bit space */
590 if (IN_BITSPACE(space)) {
591 sym->aop = aop = newAsmop (AOP_CRY);
592 aop->aopu.aop_dir = sym->rname ;
593 aop->size = getSize(sym->type);
594 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
597 /* if it is in direct space */
598 if (IN_DIRSPACE(space)) {
599 sym->aop = aop = newAsmop (AOP_DIR);
600 aop->aopu.aop_dir = sym->rname ;
601 aop->size = getSize(sym->type);
602 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
606 /* special case for a function */
607 if (IS_FUNC(sym->type)) {
609 sym->aop = aop = newAsmop(AOP_PCODE);
610 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
611 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
612 PCOI(aop->aopu.pcop)->_function = 1;
613 PCOI(aop->aopu.pcop)->index = 0;
614 aop->size = FPTRSIZE;
616 sym->aop = aop = newAsmop(AOP_IMMD);
617 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
618 strcpy(aop->aopu.aop_immd,sym->rname);
619 aop->size = FPTRSIZE;
621 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
625 if (IS_ARRAY(sym->type)) {
626 sym->aop = aop = newAsmop(AOP_PCODE);
627 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
628 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
629 PCOI(aop->aopu.pcop)->_function = 0;
630 PCOI(aop->aopu.pcop)->index = 0;
631 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
633 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
637 /* only remaining is far space */
638 /* in which case DPTR gets the address */
639 sym->aop = aop = newAsmop(AOP_PCODE);
641 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
642 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
643 PCOI(aop->aopu.pcop)->index = 0;
645 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
646 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
648 allocDirReg (IC_LEFT(ic));
650 aop->size = FPTRSIZE;
652 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
653 sym->aop = aop = newAsmop(AOP_DPTR);
654 pic14_emitcode ("mov","dptr,#%s", sym->rname);
655 aop->size = getSize(sym->type);
657 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
660 /* if it is in code space */
661 if (IN_CODESPACE(space))
667 /*-----------------------------------------------------------------*/
668 /* aopForRemat - rematerialzes an object */
669 /*-----------------------------------------------------------------*/
670 static asmop *aopForRemat (operand *op) // x symbol *sym)
672 symbol *sym = OP_SYMBOL(op);
674 asmop *aop = newAsmop(AOP_PCODE);
678 ic = sym->rematiCode;
680 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
681 if(IS_OP_POINTER(op)) {
682 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
686 val += (int) operandLitValue(IC_RIGHT(ic));
687 } else if (ic->op == '-') {
688 val -= (int) operandLitValue(IC_RIGHT(ic));
692 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
695 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
696 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
697 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
698 PCOI(aop->aopu.pcop)->index = val;
700 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
701 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
702 val, IS_PTR_CONST(operandType(op)));
704 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
706 allocDirReg (IC_LEFT(ic));
711 int aopIdx (asmop *aop, int offset)
716 if(aop->type != AOP_REG)
719 return aop->aopu.aop_reg[offset]->rIdx;
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common */
724 /*-----------------------------------------------------------------*/
725 static bool regsInCommon (operand *op1, operand *op2)
730 /* if they have registers in common */
731 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
734 sym1 = OP_SYMBOL(op1);
735 sym2 = OP_SYMBOL(op2);
737 if (sym1->nRegs == 0 || sym2->nRegs == 0)
740 for (i = 0 ; i < sym1->nRegs ; i++) {
745 for (j = 0 ; j < sym2->nRegs ;j++ ) {
749 if (sym2->regs[j] == sym1->regs[i])
757 /*-----------------------------------------------------------------*/
758 /* operandsEqu - equivalent */
759 /*-----------------------------------------------------------------*/
760 static bool operandsEqu ( operand *op1, operand *op2)
764 /* if they not symbols */
765 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
768 sym1 = OP_SYMBOL(op1);
769 sym2 = OP_SYMBOL(op2);
771 /* if both are itemps & one is spilt
772 and the other is not then false */
773 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
774 sym1->isspilt != sym2->isspilt )
777 /* if they are the same */
781 if (sym1->rname[0] && sym2->rname[0]
782 && strcmp (sym1->rname, sym2->rname) == 0)
786 /* if left is a tmp & right is not */
790 (sym1->usl.spillLoc == sym2))
797 (sym2->usl.spillLoc == sym1))
803 /*-----------------------------------------------------------------*/
804 /* pic14_sameRegs - two asmops have the same registers */
805 /*-----------------------------------------------------------------*/
806 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
813 if (aop1->type != AOP_REG ||
814 aop2->type != AOP_REG )
817 if (aop1->size != aop2->size )
820 for (i = 0 ; i < aop1->size ; i++ )
821 if (aop1->aopu.aop_reg[i] !=
822 aop2->aopu.aop_reg[i] )
828 /*-----------------------------------------------------------------*/
829 /* aopOp - allocates an asmop for an operand : */
830 /*-----------------------------------------------------------------*/
831 void aopOp (operand *op, iCode *ic, bool result)
840 /* if this a literal */
841 if (IS_OP_LITERAL(op)) {
842 op->aop = aop = newAsmop(AOP_LIT);
843 aop->aopu.aop_lit = op->operand.valOperand;
844 aop->size = getSize(operandType(op));
849 sym_link *type = operandType(op);
850 if(IS_PTR_CONST(type))
851 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
854 /* if already has a asmop then continue */
858 /* if the underlying symbol has a aop */
859 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
860 DEBUGpic14_emitcode(";","%d",__LINE__);
861 op->aop = OP_SYMBOL(op)->aop;
865 /* if this is a true symbol */
866 if (IS_TRUE_SYMOP(op)) {
867 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
868 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
872 /* this is a temporary : this has
878 e) can be a return use only */
883 /* if the type is a conditional */
884 if (sym->regType == REG_CND) {
885 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
890 /* if it is spilt then two situations
892 b) has a spill location */
893 if (sym->isspilt || sym->nRegs == 0) {
895 DEBUGpic14_emitcode(";","%d",__LINE__);
896 /* rematerialize it NOW */
899 sym->aop = op->aop = aop = aopForRemat (op);
900 aop->size = getSize(sym->type);
901 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
906 /* WREG is not usable as an ordinary operand with PIC architecture,
907 * one might introduce a scratch register that can be used to make
908 * WREG accesible as an operand... disable WREG for now */
911 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
912 aop->size = getSize(sym->type);
913 for ( i = 0 ; i < 2 ; i++ )
914 aop->aopu.aop_str[i] = accUse[i];
915 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
921 if(sym->isptr) { // && sym->uptr
922 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
923 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
925 //PCOI(aop->aopu.pcop)->_const = 0;
926 //PCOI(aop->aopu.pcop)->index = 0;
928 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
929 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
931 //allocDirReg (IC_LEFT(ic));
933 aop->size = getSize(sym->type);
934 DEBUGpic14_emitcode(";","%d",__LINE__);
941 aop = op->aop = sym->aop = newAsmop(AOP_STR);
942 aop->size = getSize(sym->type);
943 for ( i = 0 ; i < fReturnSizePic ; i++ )
944 aop->aopu.aop_str[i] = fReturn[i];
946 DEBUGpic14_emitcode(";","%d",__LINE__);
951 /* else spill location */
952 if (sym->usl.spillLoc)
954 asmop *oldAsmOp = NULL;
956 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
958 /* force a new aop if sizes differ */
959 oldAsmOp = sym->usl.spillLoc->aop;
960 sym->usl.spillLoc->aop = NULL;
962 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
963 __FUNCTION__,__LINE__,
964 sym->usl.spillLoc->rname,
965 sym->rname, sym->usl.spillLoc->offset);
967 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
968 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
970 /* Don't reuse the new aop, go with the last one */
971 sym->usl.spillLoc->aop = oldAsmOp;
973 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
974 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
976 sym->usl.spillLoc->offset);
977 aop->size = getSize(sym->type);
984 sym_link *type = operandType(op);
985 if(IS_PTR_CONST(type))
986 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
989 /* must be in a register */
990 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
991 sym->aop = op->aop = aop = newAsmop(AOP_REG);
992 aop->size = sym->nRegs;
993 for ( i = 0 ; i < sym->nRegs ;i++)
994 aop->aopu.aop_reg[i] = sym->regs[i];
997 /*-----------------------------------------------------------------*/
998 /* freeAsmop - free up the asmop given to an operand */
999 /*----------------------------------------------------------------*/
1000 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1017 /* depending on the asmop type only three cases need work AOP_RO
1018 , AOP_R1 && AOP_STK */
1020 switch (aop->type) {
1024 pic14_emitcode ("pop","ar0");
1028 bitVectUnSetBit(ic->rUsed,R0_IDX);
1034 pic14_emitcode ("pop","ar1");
1038 bitVectUnSetBit(ic->rUsed,R1_IDX);
1044 int stk = aop->aopu.aop_stk + aop->size;
1045 bitVectUnSetBit(ic->rUsed,R0_IDX);
1046 bitVectUnSetBit(ic->rUsed,R1_IDX);
1048 getFreePtr(ic,&aop,FALSE);
1050 if (options.stack10bit)
1052 /* I'm not sure what to do here yet... */
1055 "*** Warning: probably generating bad code for "
1056 "10 bit stack mode.\n");
1060 pic14_emitcode ("mov","a,_bp");
1061 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1062 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1064 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1068 pic14_emitcode("pop","acc");
1069 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1071 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1074 freeAsmop(op,NULL,ic,TRUE);
1076 pic14_emitcode("pop","ar0");
1081 pic14_emitcode("pop","ar1");
1089 /* all other cases just dealloc */
1093 OP_SYMBOL(op)->aop = NULL;
1094 /* if the symbol has a spill */
1096 SPIL_LOC(op)->aop = NULL;
1101 /*-----------------------------------------------------------------*/
1102 /* aopGet - for fetching value of the aop */
1103 /*-----------------------------------------------------------------*/
1104 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1109 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1110 /* offset is greater than
1112 if (offset > (aop->size - 1) &&
1113 aop->type != AOP_LIT)
1116 /* depending on type */
1117 switch (aop->type) {
1121 DEBUGpic14_emitcode(";","%d",__LINE__);
1122 /* if we need to increment it */
1123 while (offset > aop->coff) {
1124 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1128 while (offset < aop->coff) {
1129 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1133 aop->coff = offset ;
1135 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1136 return (dname ? "acc" : "a");
1138 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1139 rs = Safe_calloc(1,strlen(s)+1);
1145 DEBUGpic14_emitcode(";","%d",__LINE__);
1146 if (aop->type == AOP_DPTR2)
1151 while (offset > aop->coff) {
1152 pic14_emitcode ("inc","dptr");
1156 while (offset < aop->coff) {
1157 pic14_emitcode("lcall","__decdptr");
1163 pic14_emitcode("clr","a");
1164 pic14_emitcode("movc","a,@a+dptr");
1167 pic14_emitcode("movx","a,@dptr");
1170 if (aop->type == AOP_DPTR2)
1175 return (dname ? "acc" : "a");
1180 sprintf (s,"%s",aop->aopu.aop_immd);
1183 sprintf(s,"(%s >> %d)",
1188 aop->aopu.aop_immd);
1189 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1190 rs = Safe_calloc(1,strlen(s)+1);
1196 sprintf(s,"(%s + %d)",
1199 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1201 sprintf(s,"%s",aop->aopu.aop_dir);
1202 rs = Safe_calloc(1,strlen(s)+1);
1208 // return aop->aopu.aop_reg[offset]->dname;
1210 return aop->aopu.aop_reg[offset]->name;
1213 //pic14_emitcode(";","%d",__LINE__);
1214 return aop->aopu.aop_dir;
1217 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1218 return "AOP_accumulator_bug";
1221 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1222 rs = Safe_strdup(s);
1226 aop->coff = offset ;
1227 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1230 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1232 return aop->aopu.aop_str[offset];
1236 pCodeOp *pcop = aop->aopu.pcop;
1237 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1240 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1241 sprintf(s,"(%s+%d)", pcop->name,offset);
1243 DEBUGpic14_emitcode(";","%s",pcop->name);
1244 sprintf(s,"%s", pcop->name);
1247 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1250 rs = Safe_calloc(1,strlen(s)+1);
1256 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1257 "aopget got unsupported aop->type");
1262 /*-----------------------------------------------------------------*/
1263 /* popGetTempReg - create a new temporary pCodeOp */
1264 /*-----------------------------------------------------------------*/
1265 pCodeOp *popGetTempReg(void)
1270 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1271 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1272 PCOR(pcop)->r->wasUsed=1;
1273 PCOR(pcop)->r->isFree=0;
1279 /*-----------------------------------------------------------------*/
1280 /* popReleaseTempReg - create a new temporary pCodeOp */
1281 /*-----------------------------------------------------------------*/
1282 void popReleaseTempReg(pCodeOp *pcop)
1285 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1286 PCOR(pcop)->r->isFree = 1;
1289 /*-----------------------------------------------------------------*/
1290 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1291 /*-----------------------------------------------------------------*/
1292 pCodeOp *popGetLabel(unsigned int key)
1295 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1297 if(key>(unsigned int)max_key)
1300 return newpCodeOpLabel(NULL,key+100+labelOffset);
1303 /*-------------------------------------------------------------------*/
1304 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1305 /*-------------------------------------------------------------------*/
1306 pCodeOp *popGetHighLabel(unsigned int key)
1309 pcop = popGetLabel(key);
1310 PCOLAB(pcop)->offset = 1;
1314 /*-----------------------------------------------------------------*/
1315 /* popGetLit - asm operator to pcode operator conversion */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *popGetLit(unsigned int lit)
1320 return newpCodeOpLit((unsigned char)lit);
1323 /*-----------------------------------------------------------------*/
1324 /* popGetImmd - asm operator to pcode immediate conversion */
1325 /*-----------------------------------------------------------------*/
1326 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1329 return newpCodeOpImmd(name, offset,index, 0, is_func);
1332 extern set *externs;
1334 /*-----------------------------------------------------------------*/
1335 /* popGetWithString - asm operator to pcode operator conversion */
1336 /*-----------------------------------------------------------------*/
1337 pCodeOp *popGetWithString(char *str, int isExtern)
1343 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1347 pcop = newpCodeOp(str,PO_STR);
1348 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1353 pCodeOp *popGetExternal (char *str)
1355 pCodeOp *pcop = popGetWithString (str, 1);
1361 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1363 if (!strcmp (str, sym->rname))
1369 sym = newSymbol(str, 0);
1370 strncpy(sym->rname, str, SDCC_NAME_MAX);
1371 addSet (&externs, sym);
1377 /*-----------------------------------------------------------------*/
1378 /* popRegFromString - */
1379 /*-----------------------------------------------------------------*/
1380 pCodeOp *popRegFromString(char *str, int size, int offset)
1383 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1384 pcop->type = PO_DIR;
1386 DEBUGpic14_emitcode(";","%d",__LINE__);
1391 pcop->name = Safe_calloc(1,strlen(str)+1);
1392 strcpy(pcop->name,str);
1394 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1396 PCOR(pcop)->r = dirregWithName(pcop->name);
1397 if(PCOR(pcop)->r == NULL) {
1398 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1399 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1400 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1402 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1404 PCOR(pcop)->instance = offset;
1409 /*-----------------------------------------------------------------*/
1410 /*-----------------------------------------------------------------*/
1411 pCodeOp *popRegFromIdx(int rIdx)
1415 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1416 __FUNCTION__,__LINE__,rIdx);
1418 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1420 PCOR(pcop)->rIdx = rIdx;
1421 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1422 PCOR(pcop)->r->isFree = 0;
1423 PCOR(pcop)->r->wasUsed = 1;
1425 pcop->type = PCOR(pcop)->r->pc_type;
1431 /*-----------------------------------------------------------------*/
1432 /* popGet - asm operator to pcode operator conversion */
1433 /*-----------------------------------------------------------------*/
1434 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1436 //char *s = buffer ;
1441 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1442 /* offset is greater than
1448 /* XXX: still needed for BIT operands (AOP_CRY) */
1449 if (offset > (aop->size - 1) &&
1450 aop->type != AOP_LIT &&
1451 aop->type != AOP_PCODE)
1453 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1454 return NULL; //zero;
1457 /* depending on type */
1458 switch (aop->type) {
1465 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1469 DEBUGpic14_emitcode(";","%d",__LINE__);
1470 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1473 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1475 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1476 pcop->type = PO_DIR;
1478 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1479 strcpy(pcop->name,aop->aopu.aop_dir);
1480 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1481 if(PCOR(pcop)->r == NULL) {
1482 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1483 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1484 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1486 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1488 PCOR(pcop)->instance = offset;
1496 assert (offset < aop->size);
1497 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1499 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1500 PCOR(pcop)->rIdx = rIdx;
1501 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1502 PCOR(pcop)->r->wasUsed=1;
1503 PCOR(pcop)->r->isFree=0;
1505 PCOR(pcop)->instance = offset;
1506 pcop->type = PCOR(pcop)->r->pc_type;
1507 //rs = aop->aopu.aop_reg[offset]->name;
1508 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1513 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1514 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1515 //if(PCOR(pcop)->r == NULL)
1516 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1520 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1523 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1524 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1526 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1527 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1528 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1529 pcop->type = PCOR(pcop)->r->pc_type;
1530 pcop->name = PCOR(pcop)->r->name;
1537 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1539 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1540 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1541 switch (aop->aopu.pcop->type)
1544 pcop = pCodeOpCopy (aop->aopu.pcop);
1545 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1546 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1547 PCOI(pcop)->index += offset;
1548 //PCOI(pcop)->offset = 0;
1551 pcop = pCodeOpCopy (aop->aopu.pcop);
1552 PCOR(pcop)->instance = offset;
1555 assert ( !"unhandled pCode type" );
1561 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1562 "popGet got unsupported aop->type");
1566 /*-----------------------------------------------------------------*/
1567 /* popGetAddr - access the low/high word of a symbol (immediate) */
1568 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1569 /*-----------------------------------------------------------------*/
1570 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1572 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1574 pCodeOp *pcop = aop->aopu.pcop;
1575 assert (offset <= GPTRSIZE);
1577 /* special case: index >= 2 should return GPOINTER-style values */
1580 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1584 pcop = pCodeOpCopy (pcop);
1585 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1586 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1587 PCOI(pcop)->offset += offset;
1588 PCOI(pcop)->index += index;
1589 //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);
1592 return popGet (aop, offset + index);
1596 /*-----------------------------------------------------------------*/
1597 /* aopPut - puts a string for a aop */
1598 /*-----------------------------------------------------------------*/
1599 void aopPut (asmop *aop, char *s, int offset)
1604 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1606 if (aop->size && offset > ( aop->size - 1)) {
1607 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608 "aopPut got offset > aop->size");
1612 /* will assign value to value */
1613 /* depending on where it is ofcourse */
1614 switch (aop->type) {
1617 sprintf(d,"(%s + %d)",
1618 aop->aopu.aop_dir,offset);
1619 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1622 sprintf(d,"%s",aop->aopu.aop_dir);
1625 DEBUGpic14_emitcode(";","%d",__LINE__);
1627 pic14_emitcode("movf","%s,w",s);
1628 pic14_emitcode("movwf","%s",d);
1631 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1632 if(offset >= aop->size) {
1633 emitpcode(POC_CLRF,popGet(aop,offset));
1636 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1639 emitpcode(POC_MOVWF,popGet(aop,offset));
1645 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1646 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1649 strcmp(s,"r0") == 0 ||
1650 strcmp(s,"r1") == 0 ||
1651 strcmp(s,"r2") == 0 ||
1652 strcmp(s,"r3") == 0 ||
1653 strcmp(s,"r4") == 0 ||
1654 strcmp(s,"r5") == 0 ||
1655 strcmp(s,"r6") == 0 ||
1656 strcmp(s,"r7") == 0 )
1657 pic14_emitcode("mov","%s,%s ; %d",
1658 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1662 if(strcmp(s,"W")==0 )
1663 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1665 pic14_emitcode("movwf","%s",
1666 aop->aopu.aop_reg[offset]->name);
1668 if(strcmp(s,zero)==0) {
1669 emitpcode(POC_CLRF,popGet(aop,offset));
1671 } else if(strcmp(s,"W")==0) {
1672 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1673 pcop->type = PO_GPR_REGISTER;
1675 PCOR(pcop)->rIdx = -1;
1676 PCOR(pcop)->r = NULL;
1678 DEBUGpic14_emitcode(";","%d",__LINE__);
1679 pcop->name = Safe_strdup(s);
1680 emitpcode(POC_MOVFW,pcop);
1681 emitpcode(POC_MOVWF,popGet(aop,offset));
1682 } else if(strcmp(s,one)==0) {
1683 emitpcode(POC_CLRF,popGet(aop,offset));
1684 emitpcode(POC_INCF,popGet(aop,offset));
1686 emitpcode(POC_MOVWF,popGet(aop,offset));
1694 if (aop->type == AOP_DPTR2)
1700 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1701 "aopPut writting to code space");
1705 while (offset > aop->coff) {
1707 pic14_emitcode ("inc","dptr");
1710 while (offset < aop->coff) {
1712 pic14_emitcode("lcall","__decdptr");
1717 /* if not in accumulater */
1720 pic14_emitcode ("movx","@dptr,a");
1722 if (aop->type == AOP_DPTR2)
1730 while (offset > aop->coff) {
1732 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1734 while (offset < aop->coff) {
1736 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1742 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1747 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1749 if (strcmp(s,"r0") == 0 ||
1750 strcmp(s,"r1") == 0 ||
1751 strcmp(s,"r2") == 0 ||
1752 strcmp(s,"r3") == 0 ||
1753 strcmp(s,"r4") == 0 ||
1754 strcmp(s,"r5") == 0 ||
1755 strcmp(s,"r6") == 0 ||
1756 strcmp(s,"r7") == 0 ) {
1758 sprintf(buffer,"a%s",s);
1759 pic14_emitcode("mov","@%s,%s",
1760 aop->aopu.aop_ptr->name,buffer);
1762 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1767 if (strcmp(s,"a") == 0)
1768 pic14_emitcode("push","acc");
1770 pic14_emitcode("push","%s",s);
1775 /* if bit variable */
1776 if (!aop->aopu.aop_dir) {
1777 pic14_emitcode("clr","a");
1778 pic14_emitcode("rlc","a");
1781 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1784 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1787 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1789 lbl = newiTempLabel(NULL);
1791 if (strcmp(s,"a")) {
1794 pic14_emitcode("clr","c");
1795 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1796 pic14_emitcode("cpl","c");
1797 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1798 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1805 if (strcmp(aop->aopu.aop_str[offset],s))
1806 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1811 if (!offset && (strcmp(s,"acc") == 0))
1814 if (strcmp(aop->aopu.aop_str[offset],s))
1815 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1819 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1820 "aopPut got unsupported aop->type");
1826 /*-----------------------------------------------------------------*/
1827 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1828 /*-----------------------------------------------------------------*/
1829 static void mov2w_op (operand *op, int offset)
1834 /* for PO_IMMEDIATEs: use address or value? */
1835 if (op_isLitLike (op))
1837 /* access address of op */
1838 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1839 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1841 if (offset == GPTRSIZE-1)
1842 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1844 emitpcode (POC_MOVLW, popGetLit (0));
1847 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1849 /* access value stored in op */
1850 mov2w (AOP(op), offset);
1855 /*-----------------------------------------------------------------*/
1856 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1857 /*-----------------------------------------------------------------*/
1858 void mov2w (asmop *aop, int offset)
1864 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1866 if ( aop_isLitLike (aop) )
1867 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1869 emitpcode(POC_MOVFW,popGet(aop,offset));
1873 static void movwf (asmop *op, int offset)
1875 emitpcode (POC_MOVWF, popGet(op, offset));
1878 static pCodeOp *get_argument_pcop (int idx)
1880 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1881 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1884 static pCodeOp *get_return_val_pcop (int offset)
1886 assert (offset > 0 && "the most significant byte is returned via WREG");
1887 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1890 static void pass_argument (operand *op, int offset, int idx)
1893 mov2w_op (op, offset);
1895 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1898 static void get_returnvalue (operand *op, int offset, int idx)
1901 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1902 movwf(AOP(op), offset);
1905 static void call_libraryfunc (char *name)
1907 /* library code might reside in different page... */
1908 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1909 /* call the library function */
1910 emitpcode (POC_CALL, popGetExternal (name));
1911 /* might return from different page... */
1912 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1915 /*-----------------------------------------------------------------*/
1916 /* reAdjustPreg - points a register back to where it should */
1917 /*-----------------------------------------------------------------*/
1918 static void reAdjustPreg (asmop *aop)
1922 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1924 if ((size = aop->size) <= 1)
1927 switch (aop->type) {
1931 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1935 if (aop->type == AOP_DPTR2)
1941 pic14_emitcode("lcall","__decdptr");
1944 if (aop->type == AOP_DPTR2)
1957 /*-----------------------------------------------------------------*/
1958 /* opIsGptr: returns non-zero if the passed operand is */
1959 /* a generic pointer type. */
1960 /*-----------------------------------------------------------------*/
1961 static int opIsGptr(operand *op)
1963 sym_link *type = operandType(op);
1965 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1966 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1974 /*-----------------------------------------------------------------*/
1975 /* pic14_getDataSize - get the operand data size */
1976 /*-----------------------------------------------------------------*/
1977 int pic14_getDataSize(operand *op)
1981 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1984 size = getSize(OP_SYM_ETYPE(op));
1986 //return AOP_SIZE(op);
1988 // tsd- in the pic port, the genptr size is 1, so this code here
1989 // fails. ( in the 8051 port, the size was 4).
1991 size = AOP_SIZE(op);
1992 if (IS_GENPTR(OP_SYM_TYPE(op)))
1994 sym_link *type = operandType(op);
1995 if (IS_GENPTR(type))
1997 /* generic pointer; arithmetic operations
1998 * should ignore the high byte (pointer type).
2001 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2008 /*-----------------------------------------------------------------*/
2009 /* pic14_outAcc - output Acc */
2010 /*-----------------------------------------------------------------*/
2011 void pic14_outAcc(operand *result)
2014 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2015 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2018 size = pic14_getDataSize(result);
2020 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2023 /* unsigned or positive */
2025 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2030 /*-----------------------------------------------------------------*/
2031 /* pic14_outBitC - output a bit C */
2032 /*-----------------------------------------------------------------*/
2033 void pic14_outBitC(operand *result)
2036 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2037 /* if the result is bit */
2038 if (AOP_TYPE(result) == AOP_CRY)
2039 aopPut(AOP(result),"c",0);
2041 pic14_emitcode("clr","a ; %d", __LINE__);
2042 pic14_emitcode("rlc","a");
2043 pic14_outAcc(result);
2047 /*-----------------------------------------------------------------*/
2048 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2049 /*-----------------------------------------------------------------*/
2050 void pic14_toBoolean(operand *oper)
2052 int size = AOP_SIZE(oper);
2055 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2060 /* MOVFW does not load the flags... */
2061 if (AOP_TYPE(oper) == AOP_ACC) {
2062 emitpcode(POC_IORLW, popGetLit(0));
2065 emitpcode(POC_MOVLW, popGetLit(0));
2069 if ( AOP_TYPE(oper) != AOP_ACC) {
2070 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2075 while (offset < size) {
2076 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2078 /* Z is set iff (oper == 0) */
2082 /*-----------------------------------------------------------------*/
2083 /* genNot - generate code for ! operation */
2084 /*-----------------------------------------------------------------*/
2085 static void genNot (iCode *ic)
2092 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2093 /* assign asmOps to operand & result */
2094 aopOp (IC_LEFT(ic),ic,FALSE);
2095 aopOp (IC_RESULT(ic),ic,TRUE);
2097 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2098 /* if in bit space then a special case */
2099 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2100 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2101 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2102 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2104 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2105 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2106 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2111 size = AOP_SIZE(IC_LEFT(ic));
2112 mov2w (AOP(IC_LEFT(ic)),0);
2115 if (op_isLitLike (IC_LEFT(ic)))
2116 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2118 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2120 emitpcode(POC_MOVLW, popGetLit (0));
2122 emitpcode(POC_MOVLW, popGetLit (1));
2123 movwf(AOP(IC_RESULT(ic)), 0);
2125 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2127 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2132 /* release the aops */
2133 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2134 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2138 /*-----------------------------------------------------------------*/
2139 /* genCpl - generate code for complement */
2140 /*-----------------------------------------------------------------*/
2141 static void genCpl (iCode *ic)
2143 operand *left, *result;
2148 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2149 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2150 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2152 /* if both are in bit space then
2154 if (AOP_TYPE(result) == AOP_CRY &&
2155 AOP_TYPE(left) == AOP_CRY ) {
2157 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2158 pic14_emitcode("cpl","c");
2159 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2163 size = AOP_SIZE(result);
2164 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2167 if(AOP_TYPE(left) == AOP_ACC)
2168 emitpcode(POC_XORLW, popGetLit(0xff));
2170 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2172 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2175 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2179 /* release the aops */
2180 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2181 freeAsmop(result,NULL,ic,TRUE);
2184 /*-----------------------------------------------------------------*/
2185 /* genUminusFloat - unary minus for floating points */
2186 /*-----------------------------------------------------------------*/
2187 static void genUminusFloat(operand *op,operand *result)
2189 int size ,offset =0 ;
2194 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2195 /* for this we just need to flip the
2196 first it then copy the rest in place */
2197 size = AOP_SIZE(op) - 1;
2198 l = aopGet(AOP(op),3,FALSE,FALSE);
2202 pic14_emitcode("cpl","acc.7");
2203 aopPut(AOP(result),"a",3);
2207 aopGet(AOP(op),offset,FALSE,FALSE),
2213 /*-----------------------------------------------------------------*/
2214 /* genUminus - unary minus code generation */
2215 /*-----------------------------------------------------------------*/
2216 static void genUminus (iCode *ic)
2219 sym_link *optype, *rtype;
2223 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2225 aopOp(IC_LEFT(ic),ic,FALSE);
2226 aopOp(IC_RESULT(ic),ic,TRUE);
2228 /* if both in bit space then special
2230 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2231 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2233 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2234 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2235 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2240 optype = operandType(IC_LEFT(ic));
2241 rtype = operandType(IC_RESULT(ic));
2243 /* if float then do float stuff */
2244 if (IS_FLOAT(optype)) {
2245 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2249 /* otherwise subtract from zero by taking the 2's complement */
2250 size = AOP_SIZE(IC_LEFT(ic));
2252 for(i=0; i<size; i++) {
2253 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2254 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2256 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2257 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2261 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2262 for(i=1; i<size; i++) {
2264 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2268 /* release the aops */
2269 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2270 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2273 /*-----------------------------------------------------------------*/
2274 /* saveRegisters - will look for a call and save the registers */
2275 /*-----------------------------------------------------------------*/
2276 static void saveRegisters(iCode *lic)
2285 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2287 for (ic = lic ; ic ; ic = ic->next)
2288 if (ic->op == CALL || ic->op == PCALL)
2292 fprintf(stderr,"found parameter push with no function call\n");
2296 /* if the registers have been saved already then
2298 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2301 /* find the registers in use at this time
2302 and push them away to safety */
2303 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2307 if (options.useXstack) {
2308 if (bitVectBitValue(rsave,R0_IDX))
2309 pic14_emitcode("mov","b,r0");
2310 pic14_emitcode("mov","r0,%s",spname);
2311 for (i = 0 ; i < pic14_nRegs ; i++) {
2312 if (bitVectBitValue(rsave,i)) {
2314 pic14_emitcode("mov","a,b");
2316 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2317 pic14_emitcode("movx","@r0,a");
2318 pic14_emitcode("inc","r0");
2321 pic14_emitcode("mov","%s,r0",spname);
2322 if (bitVectBitValue(rsave,R0_IDX))
2323 pic14_emitcode("mov","r0,b");
2325 //for (i = 0 ; i < pic14_nRegs ; i++) {
2326 // if (bitVectBitValue(rsave,i))
2327 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2330 dtype = operandType(IC_LEFT(ic));
2331 if (currFunc && dtype &&
2332 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2333 IFFUNC_ISISR(currFunc->type) &&
2336 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2339 /*-----------------------------------------------------------------*/
2340 /* unsaveRegisters - pop the pushed registers */
2341 /*-----------------------------------------------------------------*/
2342 static void unsaveRegisters (iCode *ic)
2349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2350 /* find the registers in use at this time
2351 and push them away to safety */
2352 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2355 if (options.useXstack) {
2356 pic14_emitcode("mov","r0,%s",spname);
2357 for (i = pic14_nRegs ; i >= 0 ; i--) {
2358 if (bitVectBitValue(rsave,i)) {
2359 pic14_emitcode("dec","r0");
2360 pic14_emitcode("movx","a,@r0");
2362 pic14_emitcode("mov","b,a");
2364 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2368 pic14_emitcode("mov","%s,r0",spname);
2369 if (bitVectBitValue(rsave,R0_IDX))
2370 pic14_emitcode("mov","r0,b");
2372 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2373 // if (bitVectBitValue(rsave,i))
2374 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2380 /*-----------------------------------------------------------------*/
2382 /*-----------------------------------------------------------------*/
2383 static void pushSide(operand * oper, int size)
2387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2389 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2390 if (AOP_TYPE(oper) != AOP_REG &&
2391 AOP_TYPE(oper) != AOP_DIR &&
2393 pic14_emitcode("mov","a,%s",l);
2394 pic14_emitcode("push","acc");
2396 pic14_emitcode("push","%s",l);
2401 /*-----------------------------------------------------------------*/
2402 /* assignResultValue - */
2403 /*-----------------------------------------------------------------*/
2404 static void assignResultValue(operand * oper)
2406 int size = AOP_SIZE(oper);
2411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2413 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2415 /* assign MSB first (passed via WREG) */
2417 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2423 /*-----------------------------------------------------------------*/
2424 /* genIpush - genrate code for pushing this gets a little complex */
2425 /*-----------------------------------------------------------------*/
2426 static void genIpush (iCode *ic)
2430 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2432 int size, offset = 0 ;
2436 /* if this is not a parm push : ie. it is spill push
2437 and spill push is always done on the local stack */
2438 if (!ic->parmPush) {
2440 /* and the item is spilt then do nothing */
2441 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2444 aopOp(IC_LEFT(ic),ic,FALSE);
2445 size = AOP_SIZE(IC_LEFT(ic));
2446 /* push it on the stack */
2448 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2453 pic14_emitcode("push","%s",l);
2458 /* this is a paramter push: in this case we call
2459 the routine to find the call and save those
2460 registers that need to be saved */
2463 /* then do the push */
2464 aopOp(IC_LEFT(ic),ic,FALSE);
2467 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2468 size = AOP_SIZE(IC_LEFT(ic));
2471 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2472 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2473 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2475 pic14_emitcode("mov","a,%s",l);
2476 pic14_emitcode("push","acc");
2478 pic14_emitcode("push","%s",l);
2481 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2485 /*-----------------------------------------------------------------*/
2486 /* genIpop - recover the registers: can happen only for spilling */
2487 /*-----------------------------------------------------------------*/
2488 static void genIpop (iCode *ic)
2492 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2493 assert (!"genIpop -- unimplemented");
2498 /* if the temp was not pushed then */
2499 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2502 aopOp(IC_LEFT(ic),ic,FALSE);
2503 size = AOP_SIZE(IC_LEFT(ic));
2506 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2509 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2513 /*-----------------------------------------------------------------*/
2514 /* unsaverbank - restores the resgister bank from stack */
2515 /*-----------------------------------------------------------------*/
2516 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2520 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2528 if (options.useXstack) {
2530 r = getFreePtr(ic,&aop,FALSE);
2533 pic14_emitcode("mov","%s,_spx",r->name);
2534 pic14_emitcode("movx","a,@%s",r->name);
2535 pic14_emitcode("mov","psw,a");
2536 pic14_emitcode("dec","%s",r->name);
2539 pic14_emitcode ("pop","psw");
2542 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2543 if (options.useXstack) {
2544 pic14_emitcode("movx","a,@%s",r->name);
2545 //pic14_emitcode("mov","(%s+%d),a",
2546 // regspic14[i].base,8*bank+regspic14[i].offset);
2547 pic14_emitcode("dec","%s",r->name);
2550 pic14_emitcode("pop",""); //"(%s+%d)",
2551 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2554 if (options.useXstack) {
2556 pic14_emitcode("mov","_spx,%s",r->name);
2557 freeAsmop(NULL,aop,ic,TRUE);
2563 /*-----------------------------------------------------------------*/
2564 /* saverbank - saves an entire register bank on the stack */
2565 /*-----------------------------------------------------------------*/
2566 static void saverbank (int bank, iCode *ic, bool pushPsw)
2570 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2576 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2577 if (options.useXstack) {
2580 r = getFreePtr(ic,&aop,FALSE);
2581 pic14_emitcode("mov","%s,_spx",r->name);
2585 for (i = 0 ; i < pic14_nRegs ;i++) {
2586 if (options.useXstack) {
2587 pic14_emitcode("inc","%s",r->name);
2588 //pic14_emitcode("mov","a,(%s+%d)",
2589 // regspic14[i].base,8*bank+regspic14[i].offset);
2590 pic14_emitcode("movx","@%s,a",r->name);
2592 pic14_emitcode("push","");// "(%s+%d)",
2593 //regspic14[i].base,8*bank+regspic14[i].offset);
2597 if (options.useXstack) {
2598 pic14_emitcode("mov","a,psw");
2599 pic14_emitcode("movx","@%s,a",r->name);
2600 pic14_emitcode("inc","%s",r->name);
2601 pic14_emitcode("mov","_spx,%s",r->name);
2602 freeAsmop (NULL,aop,ic,TRUE);
2605 pic14_emitcode("push","psw");
2607 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2613 /*-----------------------------------------------------------------*/
2614 /* genCall - generates a call statement */
2615 /*-----------------------------------------------------------------*/
2616 static void genCall (iCode *ic)
2625 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2627 /* if caller saves & we have not saved then */
2631 /* if we are calling a function that is not using
2632 the same register bank then we need to save the
2633 destination registers on the stack */
2634 dtype = operandType(IC_LEFT(ic));
2635 if (currFunc && dtype &&
2636 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2637 IFFUNC_ISISR(currFunc->type) &&
2640 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2642 /* if send set is not empty the assign */
2645 /* For the Pic port, there is no data stack.
2646 * So parameters passed to functions are stored
2647 * in registers. (The pCode optimizer will get
2648 * rid of most of these :).
2650 int psuedoStkPtr=-1;
2651 int firstTimeThruLoop = 1;
2653 _G.sendSet = reverseSet(_G.sendSet);
2655 /* First figure how many parameters are getting passed */
2656 for (sic = setFirstItem(_G.sendSet) ; sic ;
2657 sic = setNextItem(_G.sendSet)) {
2659 aopOp(IC_LEFT(sic),sic,FALSE);
2660 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2661 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2664 for (sic = setFirstItem(_G.sendSet) ; sic ;
2665 sic = setNextItem(_G.sendSet)) {
2666 int size, offset = 0;
2668 aopOp(IC_LEFT(sic),sic,FALSE);
2669 size = AOP_SIZE(IC_LEFT(sic));
2672 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2673 AopType(AOP_TYPE(IC_LEFT(sic))));
2675 if(!firstTimeThruLoop) {
2676 /* If this is not the first time we've been through the loop
2677 * then we need to save the parameter in a temporary
2678 * register. The last byte of the last parameter is
2680 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2683 firstTimeThruLoop=0;
2685 mov2w_op (IC_LEFT(sic), offset);
2688 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2693 sym = OP_SYMBOL(IC_LEFT(ic));
2694 name = sym->rname[0] ? sym->rname : sym->name;
2695 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2697 /* Extern functions and ISRs maybe on a different page;
2698 * must call pagesel */
2699 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2701 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2703 /* May have returned from a different page;
2704 * must use pagesel to restore PCLATH before next
2705 * goto or call instruction */
2706 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2709 /* if we need assign a result value */
2710 if ((IS_ITEMP(IC_RESULT(ic)) &&
2711 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2712 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2713 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2716 aopOp(IC_RESULT(ic),ic,FALSE);
2719 assignResultValue(IC_RESULT(ic));
2721 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2722 AopType(AOP_TYPE(IC_RESULT(ic))));
2724 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2727 /* if register bank was saved then pop them */
2729 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2731 /* if we hade saved some registers then unsave them */
2732 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2733 unsaveRegisters (ic);
2738 /*-----------------------------------------------------------------*/
2739 /* genPcall - generates a call by pointer statement */
2740 /*-----------------------------------------------------------------*/
2741 static void genPcall (iCode *ic)
2744 symbol *albl = newiTempLabel(NULL);
2745 symbol *blbl = newiTempLabel(NULL);
2752 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2753 /* if caller saves & we have not saved then */
2757 /* if we are calling a function that is not using
2758 the same register bank then we need to save the
2759 destination registers on the stack */
2760 dtype = operandType(IC_LEFT(ic));
2761 if (currFunc && dtype &&
2762 IFFUNC_ISISR(currFunc->type) &&
2763 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2764 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2767 aopOp(left,ic,FALSE);
2768 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2770 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2772 pushSide(IC_LEFT(ic), FPTRSIZE);
2774 /* if send set is not empty, assign parameters */
2777 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2778 /* no way to pass args - W always gets used to make the call */
2780 /* first idea - factor out a common helper function and call it.
2781 But don't know how to get it generated only once in its own block
2783 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2786 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2787 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2788 buffer = Safe_calloc(1,strlen(rname)+16);
2789 sprintf(buffer, "%s_goto_helper", rname);
2790 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2794 emitpcode(POC_CALL,popGetLabel(albl->key));
2795 pcop = popGetLabel(blbl->key);
2796 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2797 emitpcode(POC_GOTO,pcop);
2798 emitpLabel(albl->key);
2800 emitpcode(poc,popGetAddr(AOP(left),1,0));
2801 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2802 emitpcode(poc,popGetAddr(AOP(left),0,0));
2803 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2805 emitpLabel(blbl->key);
2807 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2809 /* if we need to assign a result value */
2810 if ((IS_ITEMP(IC_RESULT(ic)) &&
2811 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2812 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2813 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2816 aopOp(IC_RESULT(ic),ic,FALSE);
2821 assignResultValue(IC_RESULT(ic));
2823 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2826 /* if register bank was saved then unsave them */
2827 if (currFunc && dtype &&
2828 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2829 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2831 /* if we hade saved some registers then
2834 unsaveRegisters (ic);
2838 /*-----------------------------------------------------------------*/
2839 /* resultRemat - result is rematerializable */
2840 /*-----------------------------------------------------------------*/
2841 static int resultRemat (iCode *ic)
2843 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2846 if (SKIP_IC(ic) || ic->op == IFX)
2849 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2850 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2851 if (sym->remat && !POINTER_SET(ic))
2858 #if defined(__BORLANDC__) || defined(_MSC_VER)
2859 #define STRCASECMP stricmp
2861 #define STRCASECMP strcasecmp
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list */
2867 /*-----------------------------------------------------------------*/
2868 static bool inExcludeList(char *s)
2870 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2873 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2874 if (options.excludeRegs[i] &&
2875 STRCASECMP(options.excludeRegs[i],"none") == 0)
2878 for ( i = 0 ; options.excludeRegs[i]; i++) {
2879 if (options.excludeRegs[i] &&
2880 STRCASECMP(s,options.excludeRegs[i]) == 0)
2887 /*-----------------------------------------------------------------*/
2888 /* genFunction - generated code for function entry */
2889 /*-----------------------------------------------------------------*/
2890 static void genFunction (iCode *ic)
2897 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2899 labelOffset += (max_key+4);
2903 /* create the function header */
2904 pic14_emitcode(";","-----------------------------------------");
2905 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2906 pic14_emitcode(";","-----------------------------------------");
2908 /* prevent this symbol from being emitted as 'extern' */
2909 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2911 pic14_emitcode("","%s:",sym->rname);
2912 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2914 ftype = operandType(IC_LEFT(ic));
2916 /* if critical function then turn interrupts off */
2917 if (IFFUNC_ISCRITICAL(ftype))
2918 pic14_emitcode("clr","ea");
2920 /* here we need to generate the equates for the
2921 register bank if required */
2923 if (FUNC_REGBANK(ftype) != rbank) {
2926 rbank = FUNC_REGBANK(ftype);
2927 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2928 if (strcmp(regspic14[i].base,"0") == 0)
2929 pic14_emitcode("","%s = 0x%02x",
2931 8*rbank+regspic14[i].offset);
2933 pic14_emitcode ("","%s = %s + 0x%02x",
2936 8*rbank+regspic14[i].offset);
2941 /* if this is an interrupt service routine */
2943 if (IFFUNC_ISISR(sym->type)) {
2945 /* already done in pic14createInterruptVect() - delete me
2946 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2947 emitpcodeNULLop(POC_NOP);
2948 emitpcodeNULLop(POC_NOP);
2949 emitpcodeNULLop(POC_NOP);
2951 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2952 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2953 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2954 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2955 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2956 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2957 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2959 pBlockConvert2ISR(pb);
2960 pic14_hasInterrupt = 1;
2962 if (!inExcludeList("acc"))
2963 pic14_emitcode ("push","acc");
2964 if (!inExcludeList("b"))
2965 pic14_emitcode ("push","b");
2966 if (!inExcludeList("dpl"))
2967 pic14_emitcode ("push","dpl");
2968 if (!inExcludeList("dph"))
2969 pic14_emitcode ("push","dph");
2970 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2972 pic14_emitcode ("push", "dpx");
2973 /* Make sure we're using standard DPTR */
2974 pic14_emitcode ("push", "dps");
2975 pic14_emitcode ("mov", "dps, #0x00");
2976 if (options.stack10bit)
2978 /* This ISR could conceivably use DPTR2. Better save it. */
2979 pic14_emitcode ("push", "dpl1");
2980 pic14_emitcode ("push", "dph1");
2981 pic14_emitcode ("push", "dpx1");
2984 /* if this isr has no bank i.e. is going to
2985 run with bank 0 , then we need to save more
2987 if (!FUNC_REGBANK(sym->type)) {
2989 /* if this function does not call any other
2990 function then we can be economical and
2991 save only those registers that are used */
2992 if (! IFFUNC_HASFCALL(sym->type)) {
2995 /* if any registers used */
2996 if (sym->regsUsed) {
2997 /* save the registers used */
2998 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2999 if (bitVectBitValue(sym->regsUsed,i) ||
3000 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3001 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
3006 /* this function has a function call cannot
3007 determines register usage so we will have the
3009 saverbank(0,ic,FALSE);
3014 /* if callee-save to be used for this function
3015 then save the registers being used in this function */
3016 if (IFFUNC_CALLEESAVES(sym->type)) {
3019 /* if any registers used */
3020 if (sym->regsUsed) {
3021 /* save the registers used */
3022 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3023 if (bitVectBitValue(sym->regsUsed,i) ||
3024 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3025 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3033 /* set the register bank to the desired value */
3034 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3035 pic14_emitcode("push","psw");
3036 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3039 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3041 if (options.useXstack) {
3042 pic14_emitcode("mov","r0,%s",spname);
3043 pic14_emitcode("mov","a,_bp");
3044 pic14_emitcode("movx","@r0,a");
3045 pic14_emitcode("inc","%s",spname);
3049 /* set up the stack */
3050 pic14_emitcode ("push","_bp"); /* save the callers stack */
3052 pic14_emitcode ("mov","_bp,%s",spname);
3055 /* adjust the stack for the function */
3060 werror(W_STACK_OVERFLOW,sym->name);
3062 if (i > 3 && sym->recvSize < 4) {
3064 pic14_emitcode ("mov","a,sp");
3065 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3066 pic14_emitcode ("mov","sp,a");
3071 pic14_emitcode("inc","sp");
3076 pic14_emitcode ("mov","a,_spx");
3077 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3078 pic14_emitcode ("mov","_spx,a");
3083 /*-----------------------------------------------------------------*/
3084 /* genEndFunction - generates epilogue for functions */
3085 /*-----------------------------------------------------------------*/
3086 static void genEndFunction (iCode *ic)
3088 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3092 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3094 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3096 pic14_emitcode ("mov","%s,_bp",spname);
3099 /* if use external stack but some variables were
3100 added to the local stack then decrement the
3102 if (options.useXstack && sym->stack) {
3103 pic14_emitcode("mov","a,sp");
3104 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3105 pic14_emitcode("mov","sp,a");
3109 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3110 if (options.useXstack) {
3111 pic14_emitcode("mov","r0,%s",spname);
3112 pic14_emitcode("movx","a,@r0");
3113 pic14_emitcode("mov","_bp,a");
3114 pic14_emitcode("dec","%s",spname);
3118 pic14_emitcode ("pop","_bp");
3122 /* restore the register bank */
3123 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3124 pic14_emitcode ("pop","psw");
3126 if (IFFUNC_ISISR(sym->type)) {
3128 /* now we need to restore the registers */
3129 /* if this isr has no bank i.e. is going to
3130 run with bank 0 , then we need to save more
3132 if (!FUNC_REGBANK(sym->type)) {
3134 /* if this function does not call any other
3135 function then we can be economical and
3136 save only those registers that are used */
3137 if (! IFFUNC_HASFCALL(sym->type)) {
3140 /* if any registers used */
3141 if (sym->regsUsed) {
3142 /* save the registers used */
3143 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3144 if (bitVectBitValue(sym->regsUsed,i) ||
3145 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3146 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3151 /* this function has a function call cannot
3152 determines register usage so we will have the
3154 unsaverbank(0,ic,FALSE);
3158 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3160 if (options.stack10bit)
3162 pic14_emitcode ("pop", "dpx1");
3163 pic14_emitcode ("pop", "dph1");
3164 pic14_emitcode ("pop", "dpl1");
3166 pic14_emitcode ("pop", "dps");
3167 pic14_emitcode ("pop", "dpx");
3169 if (!inExcludeList("dph"))
3170 pic14_emitcode ("pop","dph");
3171 if (!inExcludeList("dpl"))
3172 pic14_emitcode ("pop","dpl");
3173 if (!inExcludeList("b"))
3174 pic14_emitcode ("pop","b");
3175 if (!inExcludeList("acc"))
3176 pic14_emitcode ("pop","acc");
3178 if (IFFUNC_ISCRITICAL(sym->type))
3179 pic14_emitcode("setb","ea");
3182 /* if debug then send end of function */
3183 /* if (options.debug && currFunc) { */
3185 debugFile->writeEndFunction (currFunc, ic, 1);
3188 pic14_emitcode ("reti","");
3189 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3190 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3191 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3192 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3193 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3194 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3195 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3196 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3197 emitpcodeNULLop(POC_RETFIE);
3200 if (IFFUNC_ISCRITICAL(sym->type))
3201 pic14_emitcode("setb","ea");
3203 if (IFFUNC_CALLEESAVES(sym->type)) {
3206 /* if any registers used */
3207 if (sym->regsUsed) {
3208 /* save the registers used */
3209 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3210 if (bitVectBitValue(sym->regsUsed,i) ||
3211 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3212 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3218 /* if debug then send end of function */
3220 debugFile->writeEndFunction (currFunc, ic, 1);
3223 pic14_emitcode ("return","");
3224 emitpcodeNULLop(POC_RETURN);
3226 /* Mark the end of a function */
3227 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3232 /*-----------------------------------------------------------------*/
3233 /* genRet - generate code for return statement */
3234 /*-----------------------------------------------------------------*/
3235 static void genRet (iCode *ic)
3237 int size,offset = 0;
3241 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3242 /* if we have no return value then
3243 just generate the "ret" */
3247 /* we have something to return then
3248 move the return value into place */
3249 aopOp(IC_LEFT(ic),ic,FALSE);
3250 size = AOP_SIZE(IC_LEFT(ic));
3252 for (offset = 0; offset < size; offset++)
3254 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3257 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3260 /* generate a jump to the return label
3261 if the next is not the return statement */
3262 if (!(ic->next && ic->next->op == LABEL &&
3263 IC_LABEL(ic->next) == returnLabel)) {
3265 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label */
3272 /*-----------------------------------------------------------------*/
3273 static void genLabel (iCode *ic)
3277 /* special case never generate */
3278 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3279 if (IC_LABEL(ic) == entryLabel)
3282 emitpLabel(IC_LABEL(ic)->key);
3283 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a goto */
3288 /*-----------------------------------------------------------------*/
3290 static void genGoto (iCode *ic)
3294 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3295 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3299 /*-----------------------------------------------------------------*/
3300 /* genMultbits :- multiplication of bits */
3301 /*-----------------------------------------------------------------*/
3302 static void genMultbits (operand *left,
3307 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3309 if(!pic14_sameRegs(AOP(result),AOP(right)))
3310 emitpcode(POC_BSF, popGet(AOP(result),0));
3312 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3313 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3314 emitpcode(POC_BCF, popGet(AOP(result),0));
3319 /*-----------------------------------------------------------------*/
3320 /* genMultOneByte : 8 bit multiplication & division */
3321 /*-----------------------------------------------------------------*/
3322 static void genMultOneByte (operand *left,
3326 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3334 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3335 DEBUGpic14_AopType(__LINE__,left,right,result);
3336 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3338 /* (if two literals, the value is computed before) */
3339 /* if one literal, literal on the right */
3340 if (AOP_TYPE(left) == AOP_LIT){
3346 assert (AOP_SIZE(left) == AOP_SIZE(right));
3348 size = min(AOP_SIZE(result),AOP_SIZE(left));
3349 offset = Gstack_base_addr - (2*size - 1);
3351 /* pass right operand as argument */
3352 for (i=0; i < size; i++)
3354 mov2w (AOP(right), i);
3355 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3358 /* pass left operand as argument */
3359 for (i=0; i < size; i++)
3361 mov2w (AOP(left), i);
3362 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3364 assert (offset == Gstack_base_addr);
3366 /* call library routine */
3367 assert (size > 0 && size <= 4);
3368 call_libraryfunc (func[size]);
3371 movwf (AOP(result), size-1);
3372 for (i=0; i < size - 1; i++)
3374 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3375 movwf (AOP(result), size - 2 - i);
3378 /* now (zero-/sign) extend the result to its size */
3379 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3382 /*-----------------------------------------------------------------*/
3383 /* genMult - generates code for multiplication */
3384 /*-----------------------------------------------------------------*/
3385 static void genMult (iCode *ic)
3387 operand *left = IC_LEFT(ic);
3388 operand *right = IC_RIGHT(ic);
3389 operand *result= IC_RESULT(ic);
3393 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3394 /* assign the amsops */
3395 aopOp (left,ic,FALSE);
3396 aopOp (right,ic,FALSE);
3397 aopOp (result,ic,TRUE);
3399 DEBUGpic14_AopType(__LINE__,left,right,result);
3401 /* special cases first */
3403 if (AOP_TYPE(left) == AOP_CRY &&
3404 AOP_TYPE(right)== AOP_CRY) {
3405 genMultbits(left,right,result);
3409 /* if both are of size == 1 */
3410 if (AOP_SIZE(left) == 1 &&
3411 AOP_SIZE(right) == 1 ) {
3412 genMultOneByte(left,right,result);
3416 /* should have been converted to function call */
3420 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3421 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3422 freeAsmop(result,NULL,ic,TRUE);
3425 /*-----------------------------------------------------------------*/
3426 /* genDivbits :- division of bits */
3427 /*-----------------------------------------------------------------*/
3428 static void genDivbits (operand *left,
3437 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3438 /* the result must be bit */
3439 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3440 l = aopGet(AOP(left),0,FALSE,FALSE);
3444 pic14_emitcode("div","ab");
3445 pic14_emitcode("rrc","a");
3446 aopPut(AOP(result),"c",0);
3449 /*-----------------------------------------------------------------*/
3450 /* genDivOneByte : 8 bit division */
3451 /*-----------------------------------------------------------------*/
3452 static void genDivOneByte (operand *left,
3460 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3462 assert (AOP_SIZE(right) == 1);
3463 assert (AOP_SIZE(left) == 1);
3465 size = min(AOP_SIZE(result),AOP_SIZE(left));
3466 sign = !(SPEC_USIGN(operandType(left))
3467 && SPEC_USIGN(operandType(right)));
3469 if (AOP_TYPE(right) == AOP_LIT)
3471 /* XXX: might add specialized code */
3476 /* unsigned division */
3478 mov2w(AOP(right),0);
3479 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3481 call_libraryfunc("__divuchar");
3482 movwf(AOP(result),0);
3487 temp = popGetTempReg();
3488 lbl = newiTempLabel(NULL);
3490 /* XXX: improve this naive approach:
3491 [result] = [a] / [b]
3492 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3496 movwf temp // temp <-- left
3497 movf right,W // W <-- right
3501 subwf temp,F // temp <-- temp - W
3502 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3504 decf result // we just subtract once too often
3507 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3508 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3511 emitpcode(POC_MOVWF, temp);
3512 mov2w(AOP(right),0);
3513 emitpcode(POC_CLRF, popGet(AOP(result),0));
3515 emitpLabel(lbl->key);
3516 emitpcode(POC_INCF, popGet(AOP(result),0));
3517 emitpcode(POC_SUBWF, temp);
3519 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3520 emitpcode(POC_DECF, popGet(AOP(result),0));
3525 /* signed division */
3526 mov2w(AOP(right),0);
3527 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3529 call_libraryfunc("__divschar");
3530 movwf(AOP(result),0);
3533 /* now performed the signed/unsigned division -- extend result */
3534 addSign(result, 1, sign);
3537 /*-----------------------------------------------------------------*/
3538 /* genDiv - generates code for division */
3539 /*-----------------------------------------------------------------*/
3540 static void genDiv (iCode *ic)
3542 operand *left = IC_LEFT(ic);
3543 operand *right = IC_RIGHT(ic);
3544 operand *result= IC_RESULT(ic);
3547 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3548 /* assign the amsops */
3549 aopOp (left,ic,FALSE);
3550 aopOp (right,ic,FALSE);
3551 aopOp (result,ic,TRUE);
3553 /* special cases first */
3555 if (AOP_TYPE(left) == AOP_CRY &&
3556 AOP_TYPE(right)== AOP_CRY) {
3557 genDivbits(left,right,result);
3561 /* if both are of size == 1 */
3562 if (AOP_SIZE(left) == 1 &&
3563 AOP_SIZE(right) == 1 ) {
3564 genDivOneByte(left,right,result);
3568 /* should have been converted to function call */
3571 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3572 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3573 freeAsmop(result,NULL,ic,TRUE);
3576 /*-----------------------------------------------------------------*/
3577 /* genModOneByte : 8 bit modulus */
3578 /*-----------------------------------------------------------------*/
3579 static void genModOneByte (operand *left,
3587 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3589 assert (AOP_SIZE(right) == 1);
3590 assert (AOP_SIZE(left) == 1);
3592 size = min(AOP_SIZE(result),AOP_SIZE(left));
3593 sign = !(SPEC_USIGN(operandType(left))
3594 && SPEC_USIGN(operandType(right)));
3596 if (AOP_TYPE(right) == AOP_LIT)
3598 /* XXX: might add specialized code */
3603 /* unsigned division */
3605 mov2w(AOP(right),0);
3606 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3608 call_libraryfunc("__moduchar");
3609 movwf(AOP(result),0);
3614 lbl = newiTempLabel(NULL);
3616 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3618 /* XXX: improve this naive approach:
3619 [result] = [a] % [b]
3620 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3624 movwf result // result <-- left
3625 movf right,W // W <-- right
3627 subwf result,F // result <-- result - W
3628 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3630 addwf result, F // we just subtract once too often
3633 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3634 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3636 if (!pic14_sameRegs(AOP(left), AOP(result)))
3639 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3641 mov2w(AOP(right),0);
3643 emitpLabel(lbl->key);
3644 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3646 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3647 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3652 /* signed division */
3653 mov2w(AOP(right),0);
3654 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3656 call_libraryfunc("__modschar");
3657 movwf(AOP(result),0);
3660 /* now we performed the signed/unsigned modulus -- extend result */
3661 addSign(result, 1, sign);
3664 /*-----------------------------------------------------------------*/
3665 /* genMod - generates code for division */
3666 /*-----------------------------------------------------------------*/
3667 static void genMod (iCode *ic)
3669 operand *left = IC_LEFT(ic);
3670 operand *right = IC_RIGHT(ic);
3671 operand *result= IC_RESULT(ic);
3674 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3675 /* assign the amsops */
3676 aopOp (left,ic,FALSE);
3677 aopOp (right,ic,FALSE);
3678 aopOp (result,ic,TRUE);
3680 /* if both are of size == 1 */
3681 if (AOP_SIZE(left) == 1 &&
3682 AOP_SIZE(right) == 1 ) {
3683 genModOneByte(left,right,result);
3687 /* should have been converted to function call */
3691 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3692 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3693 freeAsmop(result,NULL,ic,TRUE);
3696 /*-----------------------------------------------------------------*/
3697 /* genIfxJump :- will create a jump depending on the ifx */
3698 /*-----------------------------------------------------------------*/
3700 note: May need to add parameter to indicate when a variable is in bit space.
3702 static void genIfxJump (iCode *ic, char *jval)
3706 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3707 /* if true label then we jump if condition
3709 if ( IC_TRUE(ic) ) {
3711 if(strcmp(jval,"a") == 0)
3713 else if (strcmp(jval,"c") == 0)
3716 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3717 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3720 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3721 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3725 /* false label is present */
3726 if(strcmp(jval,"a") == 0)
3728 else if (strcmp(jval,"c") == 0)
3731 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3732 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3735 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3736 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3741 /* mark the icode as generated */
3746 /*-----------------------------------------------------------------*/
3748 /*-----------------------------------------------------------------*/
3749 static void genSkip(iCode *ifx,int status_bit)
3755 if ( IC_TRUE(ifx) ) {
3756 switch(status_bit) {
3771 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3772 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3776 switch(status_bit) {
3790 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3791 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3798 /*-----------------------------------------------------------------*/
3800 /*-----------------------------------------------------------------*/
3801 static void genSkipc(resolvedIfx *rifx)
3812 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3813 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3814 rifx->generated = 1;
3818 /*-----------------------------------------------------------------*/
3820 /*-----------------------------------------------------------------*/
3821 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3827 if( (rifx->condition ^ invert_condition) & 1)
3832 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3833 rifx->generated = 1;
3838 /*-----------------------------------------------------------------*/
3840 /*-----------------------------------------------------------------*/
3841 static void genSkipz(iCode *ifx, int condition)
3844 assert (ifx != NULL);
3852 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3854 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3857 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3859 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3865 /*-----------------------------------------------------------------*/
3867 /*-----------------------------------------------------------------*/
3868 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3875 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3877 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3880 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3881 rifx->generated = 1;
3886 /*-----------------------------------------------------------------*/
3887 /* genChkZeroes :- greater or less than comparison */
3888 /* For each byte in a literal that is zero, inclusive or the */
3889 /* the corresponding byte in the operand with W */
3890 /* returns true if any of the bytes are zero */
3891 /*-----------------------------------------------------------------*/
3892 static int genChkZeroes(operand *op, int lit, int size)
3899 i = (lit >> (size*8)) & 0xff;
3903 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3905 emitpcode(POC_IORFW, popGet(AOP(op),size));
3915 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3916 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3917 #define DEBUGpc emitpComment
3919 /*-----------------------------------------------------------------*/
3920 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3921 /* aop (if it's NOT a literal) or from lit (if */
3922 /* aop is a literal) */
3923 /*-----------------------------------------------------------------*/
3924 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3925 if (aop->type == AOP_LIT) {
3926 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3928 emitpcode (POC_MOVFW, popGet (aop, offset));
3932 /* genCmp performs a left < right comparison, stores
3933 * the outcome in result (if != NULL) and generates
3934 * control flow code for the ifx (if != NULL).
3936 * This version leaves in sequences like
3937 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3938 * which should be optmized by the peephole
3939 * optimizer - RN 2005-01-01 */
3940 static void genCmp (operand *left,operand *right,
3941 operand *result, iCode *ifx, int sign)
3951 int invert_result = 0;
3955 assert (AOP_SIZE(left) == AOP_SIZE(right));
3956 assert (left && right);
3958 size = AOP_SIZE(right) - 1;
3959 mask = (0x100UL << (size*8)) - 1;
3960 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3965 resolveIfx (&rIfx, ifx);
3967 /**********************************************************************
3968 * handle bits - bit compares are promoted to int compares seemingly! *
3969 **********************************************************************/
3971 // THIS IS COMPLETELY UNTESTED!
3972 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3973 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3974 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3975 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3978 // 1 < {0,1} is false --> clear C by skipping the next instruction
3979 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3980 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3981 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3982 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3983 emitCLRC; // only skipped for left=0 && right=1
3985 goto correct_result_in_carry;
3989 /*************************************************
3990 * make sure that left is register (or the like) *
3991 *************************************************/
3992 if (!isAOP_REGlike(left)) {
3993 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3994 assert (isAOP_LIT(left));
3995 assert (isAOP_REGlike(right));
3996 // swap left and right
3997 // left < right <==> right > left <==> (right >= left + 1)
3998 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4000 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4001 // MAXVALUE < right? always false
4002 if (performedLt) emitCLRC; else emitSETC;
4003 goto correct_result_in_carry;
4006 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4007 // that's why we handled it above.
4014 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4015 } else if (isAOP_LIT(right)) {
4016 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4019 assert (isAOP_REGlike(left)); // left must be register or the like
4020 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4022 /*************************************************
4023 * special cases go here *
4024 *************************************************/
4026 if (isAOP_LIT(right)) {
4028 // unsigned comparison to a literal
4029 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4031 // unsigned left < 0? always false
4032 if (performedLt) emitCLRC; else emitSETC;
4033 goto correct_result_in_carry;
4036 // signed comparison to a literal
4037 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4038 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4039 // signed left < 0x80000000? always false
4040 if (performedLt) emitCLRC; else emitSETC;
4041 goto correct_result_in_carry;
4042 } else if (lit == 0) {
4043 // compare left < 0; set CARRY if SIGNBIT(left) is set
4044 if (performedLt) emitSETC; else emitCLRC;
4045 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4046 if (performedLt) emitCLRC; else emitSETC;
4047 goto correct_result_in_carry;
4050 } // right is literal
4052 /*************************************************
4053 * perform a general case comparison *
4054 * make sure we get CARRY==1 <==> left >= right *
4055 *************************************************/
4056 // compare most significant bytes
4057 //DEBUGpc ("comparing bytes at offset %d", size);
4059 // unsigned comparison
4060 pic14_mov2w_regOrLit (AOP(right), lit, size);
4061 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4063 // signed comparison
4064 // (add 2^n to both operands then perform an unsigned comparison)
4065 if (isAOP_LIT(right)) {
4066 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4067 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4069 if (litbyte == 0x80) {
4070 // left >= 0x80 -- always true, but more bytes to come
4071 mov2w (AOP(left), size);
4072 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4075 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4076 mov2w (AOP(left), size);
4077 emitpcode (POC_ADDLW, popGetLit (0x80));
4078 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4081 pCodeOp *pctemp = popGetTempReg();
4082 mov2w (AOP(left), size);
4083 emitpcode (POC_ADDLW, popGetLit (0x80));
4084 emitpcode (POC_MOVWF, pctemp);
4085 mov2w (AOP(right), size);
4086 emitpcode (POC_ADDLW, popGetLit (0x80));
4087 emitpcode (POC_SUBFW, pctemp);
4088 popReleaseTempReg(pctemp);
4092 // compare remaining bytes (treat as unsigned case from above)
4093 templbl = newiTempLabel ( NULL );
4096 //DEBUGpc ("comparing bytes at offset %d", offs);
4098 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4099 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4100 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4102 emitpLabel (templbl->key);
4103 goto result_in_carry;
4107 /****************************************************
4108 * now CARRY contains the result of the comparison: *
4109 * SUBWF sets CARRY iff *
4110 * F-W >= 0 <==> F >= W <==> !(F < W) *
4111 * (F=left, W=right) *
4112 ****************************************************/
4116 // value will be used in the following genSkipc()
4117 rIfx.condition ^= 1;
4120 correct_result_in_carry:
4122 // assign result to variable (if neccessary)
4123 if (result && AOP_TYPE(result) != AOP_CRY) {
4124 //DEBUGpc ("assign result");
4125 size = AOP_SIZE(result);
4127 emitpcode (POC_CLRF, popGet (AOP(result), size));
4129 if (invert_result) {
4131 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4133 emitpcode (POC_RLF, popGet (AOP(result), 0));
4137 // perform conditional jump
4139 //DEBUGpc ("generate control flow");
4147 /* OLD VERSION -- BUGGY, DO NOT USE */
4149 /*-----------------------------------------------------------------*/
4150 /* genCmp :- greater or less than comparison */
4151 /*-----------------------------------------------------------------*/
4152 static void genCmp (operand *left,operand *right,
4153 operand *result, iCode *ifx, int sign)
4155 int size; //, offset = 0 ;
4156 unsigned long lit = 0L,i = 0;
4157 resolvedIfx rFalseIfx;
4158 // resolvedIfx rTrueIfx;
4162 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4165 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4166 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4170 resolveIfx(&rFalseIfx,ifx);
4171 truelbl = newiTempLabel(NULL);
4172 size = max(AOP_SIZE(left),AOP_SIZE(right));
4174 DEBUGpic14_AopType(__LINE__,left,right,result);
4178 /* if literal is on the right then swap with left */
4179 if ((AOP_TYPE(right) == AOP_LIT)) {
4180 operand *tmp = right ;
4181 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4182 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4185 lit = (lit - 1) & mask;
4188 rFalseIfx.condition ^= 1;
4191 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4192 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4196 //if(IC_TRUE(ifx) == NULL)
4197 /* if left & right are bit variables */
4198 if (AOP_TYPE(left) == AOP_CRY &&
4199 AOP_TYPE(right) == AOP_CRY ) {
4200 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4201 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4203 /* subtract right from left if at the
4204 end the carry flag is set then we know that
4205 left is greater than right */
4207 symbol *lbl = newiTempLabel(NULL);
4210 if(AOP_TYPE(right) == AOP_LIT) {
4212 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4214 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4221 genSkipCond(&rFalseIfx,left,size-1,7);
4223 /* no need to compare to 0...*/
4224 /* NOTE: this is a de-generate compare that most certainly
4225 * creates some dead code. */
4226 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4228 if(ifx) ifx->generated = 1;
4235 //i = (lit >> (size*8)) & 0xff;
4236 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4238 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4240 i = ((0-lit) & 0xff);
4243 /* lit is 0x7f, all signed chars are less than
4244 * this except for 0x7f itself */
4245 emitpcode(POC_XORLW, popGetLit(0x7f));
4246 genSkipz2(&rFalseIfx,0);
4248 emitpcode(POC_ADDLW, popGetLit(0x80));
4249 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4250 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4255 genSkipz2(&rFalseIfx,1);
4257 emitpcode(POC_ADDLW, popGetLit(i));
4258 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4262 if(ifx) ifx->generated = 1;
4266 /* chars are out of the way. now do ints and longs */
4269 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4276 genSkipCond(&rFalseIfx,left,size,7);
4277 if(ifx) ifx->generated = 1;
4282 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4284 //rFalseIfx.condition ^= 1;
4285 //genSkipCond(&rFalseIfx,left,size,7);
4286 //rFalseIfx.condition ^= 1;
4288 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4289 if(rFalseIfx.condition)
4290 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4292 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4294 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4295 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4296 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4299 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4301 if(rFalseIfx.condition) {
4303 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4309 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4310 emitpLabel(truelbl->key);
4311 if(ifx) ifx->generated = 1;
4318 if( (lit & 0xff) == 0) {
4319 /* lower byte is zero */
4320 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4321 i = ((lit >> 8) & 0xff) ^0x80;
4322 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4323 emitpcode(POC_ADDLW, popGetLit( 0x80));
4324 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4325 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4328 if(ifx) ifx->generated = 1;
4333 /* Special cases for signed longs */
4334 if( (lit & 0xffffff) == 0) {
4335 /* lower byte is zero */
4336 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4337 i = ((lit >> 8*3) & 0xff) ^0x80;
4338 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4339 emitpcode(POC_ADDLW, popGetLit( 0x80));
4340 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4341 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4344 if(ifx) ifx->generated = 1;
4352 if(lit & (0x80 << (size*8))) {
4353 /* lit is negative */
4354 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4356 //genSkipCond(&rFalseIfx,left,size,7);
4358 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4360 if(rFalseIfx.condition)
4361 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4363 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4367 /* lit is positive */
4368 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4369 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4370 if(rFalseIfx.condition)
4371 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4373 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4377 /* There are no more special cases, so perform a general compare */
4379 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4380 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4384 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4386 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4388 //rFalseIfx.condition ^= 1;
4389 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4391 emitpLabel(truelbl->key);
4393 if(ifx) ifx->generated = 1;
4400 /* sign is out of the way. So now do an unsigned compare */
4401 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4404 /* General case - compare to an unsigned literal on the right.*/
4406 i = (lit >> (size*8)) & 0xff;
4407 emitpcode(POC_MOVLW, popGetLit(i));
4408 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4410 i = (lit >> (size*8)) & 0xff;
4413 emitpcode(POC_MOVLW, popGetLit(i));
4415 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4417 /* this byte of the lit is zero,
4418 *if it's not the last then OR in the variable */
4420 emitpcode(POC_IORFW, popGet(AOP(left),size));
4425 emitpLabel(lbl->key);
4426 //if(emitFinalCheck)
4427 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4429 emitpLabel(truelbl->key);
4431 if(ifx) ifx->generated = 1;
4438 if(AOP_TYPE(left) == AOP_LIT) {
4439 //symbol *lbl = newiTempLabel(NULL);
4441 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4444 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4447 if((lit == 0) && (sign == 0)){
4450 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4452 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4454 genSkipz2(&rFalseIfx,0);
4455 if(ifx) ifx->generated = 1;
4462 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4463 /* degenerate compare can never be true */
4464 if(rFalseIfx.condition == 0)
4465 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4467 if(ifx) ifx->generated = 1;
4472 /* signed comparisons to a literal byte */
4474 int lp1 = (lit+1) & 0xff;
4476 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4479 rFalseIfx.condition ^= 1;
4480 genSkipCond(&rFalseIfx,right,0,7);
4483 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4484 emitpcode(POC_XORLW, popGetLit(0x7f));
4485 genSkipz2(&rFalseIfx,1);
4488 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4489 emitpcode(POC_ADDLW, popGetLit(0x80));
4490 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4491 rFalseIfx.condition ^= 1;
4492 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4495 if(ifx) ifx->generated = 1;
4497 /* unsigned comparisons to a literal byte */
4499 switch(lit & 0xff ) {
4501 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4502 genSkipz2(&rFalseIfx,0);
4503 if(ifx) ifx->generated = 1;
4506 genSkipCond(&rFalseIfx,right,0,7);
4507 if(ifx) ifx->generated = 1;
4511 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4512 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4513 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4514 rFalseIfx.condition ^= 1;
4515 if (AOP_TYPE(result) == AOP_CRY) {
4516 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4517 if(ifx) ifx->generated = 1;
4519 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4520 emitpcode(POC_CLRF, popGet(AOP(result),0));
4521 emitpcode(POC_RLF, popGet(AOP(result),0));
4522 emitpcode(POC_MOVLW, popGetLit(0x01));
4523 emitpcode(POC_XORWF, popGet(AOP(result),0));
4534 /* Size is greater than 1 */
4542 /* this means lit = 0xffffffff, or -1 */
4545 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4546 rFalseIfx.condition ^= 1;
4547 genSkipCond(&rFalseIfx,right,size,7);
4548 if(ifx) ifx->generated = 1;
4555 if(rFalseIfx.condition) {
4556 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4557 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4560 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4562 emitpcode(POC_IORFW, popGet(AOP(right),size));
4566 if(rFalseIfx.condition) {
4567 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4568 emitpLabel(truelbl->key);
4570 rFalseIfx.condition ^= 1;
4571 genSkipCond(&rFalseIfx,right,s,7);
4574 if(ifx) ifx->generated = 1;
4578 if((size == 1) && (0 == (lp1&0xff))) {
4579 /* lower byte of signed word is zero */
4580 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4581 i = ((lp1 >> 8) & 0xff) ^0x80;
4582 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4583 emitpcode(POC_ADDLW, popGetLit( 0x80));
4584 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4585 rFalseIfx.condition ^= 1;
4586 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4589 if(ifx) ifx->generated = 1;
4593 if(lit & (0x80 << (size*8))) {
4594 /* Lit is less than zero */
4595 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4596 //rFalseIfx.condition ^= 1;
4597 //genSkipCond(&rFalseIfx,left,size,7);
4598 //rFalseIfx.condition ^= 1;
4599 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4600 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4602 if(rFalseIfx.condition)
4603 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4605 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4609 /* Lit is greater than or equal to zero */
4610 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4611 //rFalseIfx.condition ^= 1;
4612 //genSkipCond(&rFalseIfx,right,size,7);
4613 //rFalseIfx.condition ^= 1;
4615 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4616 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4618 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4619 if(rFalseIfx.condition)
4620 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4622 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4627 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4628 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4632 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4634 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4636 rFalseIfx.condition ^= 1;
4637 //rFalseIfx.condition = 1;
4638 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4640 emitpLabel(truelbl->key);
4642 if(ifx) ifx->generated = 1;
4647 /* compare word or long to an unsigned literal on the right.*/
4652 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4655 break; /* handled above */
4658 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4660 emitpcode(POC_IORFW, popGet(AOP(right),size));
4661 genSkipz2(&rFalseIfx,0);
4665 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4667 emitpcode(POC_IORFW, popGet(AOP(right),size));
4670 if(rFalseIfx.condition)
4671 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4673 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4676 emitpcode(POC_MOVLW, popGetLit(lit+1));
4677 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4679 rFalseIfx.condition ^= 1;
4680 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4683 emitpLabel(truelbl->key);
4685 if(ifx) ifx->generated = 1;
4691 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4692 i = (lit >> (size*8)) & 0xff;
4694 emitpcode(POC_MOVLW, popGetLit(i));
4695 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4698 i = (lit >> (size*8)) & 0xff;
4701 emitpcode(POC_MOVLW, popGetLit(i));
4703 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4705 /* this byte of the lit is zero,
4706 *if it's not the last then OR in the variable */
4708 emitpcode(POC_IORFW, popGet(AOP(right),size));
4713 emitpLabel(lbl->key);
4715 rFalseIfx.condition ^= 1;
4716 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4720 emitpLabel(truelbl->key);
4721 if(ifx) ifx->generated = 1;
4725 /* Compare two variables */
4727 DEBUGpic14_emitcode(";sign","%d",sign);
4731 /* Sigh. thus sucks... */
4733 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4734 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4735 emitpcode(POC_MOVLW, popGetLit(0x80));
4736 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4737 emitpcode(POC_XORFW, popGet(AOP(right),size));
4738 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4740 /* Signed char comparison */
4741 /* Special thanks to Nikolai Golovchenko for this snippet */
4742 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4743 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4744 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4745 emitpcode(POC_XORFW, popGet(AOP(left),0));
4746 emitpcode(POC_XORFW, popGet(AOP(right),0));
4747 emitpcode(POC_ADDLW, popGetLit(0x80));
4749 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4750 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4752 if(ifx) ifx->generated = 1;
4758 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4759 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4763 /* The rest of the bytes of a multi-byte compare */
4767 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4770 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4771 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4776 emitpLabel(lbl->key);
4778 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4779 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4780 (AOP_TYPE(result) == AOP_REG)) {
4781 emitpcode(POC_CLRF, popGet(AOP(result),0));
4782 emitpcode(POC_RLF, popGet(AOP(result),0));
4784 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4786 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4787 if(ifx) ifx->generated = 1;
4794 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4796 pic14_outBitC(result);
4798 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4799 /* if the result is used in the next
4800 ifx conditional branch then generate
4801 code a little differently */
4803 genIfxJump (ifx,"c");
4805 pic14_outBitC(result);
4806 /* leave the result in acc */
4812 /*-----------------------------------------------------------------*/
4813 /* genCmpGt :- greater than comparison */
4814 /*-----------------------------------------------------------------*/
4815 static void genCmpGt (iCode *ic, iCode *ifx)
4817 operand *left, *right, *result;
4818 sym_link *letype , *retype;
4822 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4824 right= IC_RIGHT(ic);
4825 result = IC_RESULT(ic);
4827 letype = getSpec(operandType(left));
4828 retype =getSpec(operandType(right));
4829 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4830 /* assign the amsops */
4831 aopOp (left,ic,FALSE);
4832 aopOp (right,ic,FALSE);
4833 aopOp (result,ic,TRUE);
4835 genCmp(right, left, result, ifx, sign);
4837 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4838 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4839 freeAsmop(result,NULL,ic,TRUE);
4842 /*-----------------------------------------------------------------*/
4843 /* genCmpLt - less than comparisons */
4844 /*-----------------------------------------------------------------*/
4845 static void genCmpLt (iCode *ic, iCode *ifx)
4847 operand *left, *right, *result;
4848 sym_link *letype , *retype;
4852 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4854 right= IC_RIGHT(ic);
4855 result = IC_RESULT(ic);
4857 letype = getSpec(operandType(left));
4858 retype =getSpec(operandType(right));
4859 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4861 /* assign the amsops */
4862 aopOp (left,ic,FALSE);
4863 aopOp (right,ic,FALSE);
4864 aopOp (result,ic,TRUE);
4866 genCmp(left, right, result, ifx, sign);
4868 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4869 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4870 freeAsmop(result,NULL,ic,TRUE);
4874 /*-----------------------------------------------------------------*/
4875 /* genc16bit2lit - compare a 16 bit value to a literal */
4876 /*-----------------------------------------------------------------*/
4877 static void genc16bit2lit(operand *op, int lit, int offset)
4882 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4883 if( (lit&0xff) == 0)
4888 switch( BYTEofLONG(lit,i)) {
4890 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4893 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4896 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4899 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4900 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4905 switch( BYTEofLONG(lit,i)) {
4907 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4911 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4915 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4918 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4920 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4928 /*-----------------------------------------------------------------*/
4929 /* gencjneshort - compare and jump if not equal */
4930 /*-----------------------------------------------------------------*/
4931 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4933 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4938 //unsigned long lit = 0L;
4940 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4941 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4944 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4945 DEBUGpic14_AopType(__LINE__,left,right,result);
4947 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4948 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4949 if (AOP_SIZE(result)) {
4950 for (offset = 0; offset < AOP_SIZE(result); offset++)
4951 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4954 assert (AOP_SIZE(left) == AOP_SIZE(right));
4955 //resolveIfx(&rIfx,ifx);
4956 lbl = newiTempLabel (NULL);
4959 mov2w (AOP(right),size);
4960 emitpcode (POC_XORFW, popGet (AOP(left), size));
4964 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4967 emitpLabel (lbl->key);
4968 if (AOP_SIZE(result)) {
4970 emitpcode (POC_INCF, popGet (AOP(result), 0));
4973 genSkipz (ifx, NULL != IC_TRUE(ifx));
4980 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4981 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4982 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4983 for (offset=0; offset < AOP_SIZE(result); offset++)
4985 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4990 /* if the left side is a literal or
4991 if the right is in a pointer register and left
4993 if ((AOP_TYPE(left) == AOP_LIT) ||
4994 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4999 if(AOP_TYPE(right) == AOP_LIT)
5000 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5002 /* if the right side is a literal then anything goes */
5003 if (AOP_TYPE(right) == AOP_LIT &&
5004 AOP_TYPE(left) != AOP_DIR ) {
5007 genc16bit2lit(left, lit, 0);
5009 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5015 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5016 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5018 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5022 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5030 /* if the right side is in a register or in direct space or
5031 if the left is a pointer register & right is not */
5032 else if (AOP_TYPE(right) == AOP_REG ||
5033 AOP_TYPE(right) == AOP_DIR ||
5034 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5035 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5036 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5037 int lbl_key = lbl->key;
5040 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5041 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5042 __FUNCTION__,__LINE__);
5046 /* switch(size) { */
5048 /* genc16bit2lit(left, lit, 0); */
5050 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5056 if((AOP_TYPE(left) == AOP_DIR) &&
5057 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5059 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5060 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5062 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5064 switch (lit & 0xff) {
5066 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5069 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5070 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5071 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5075 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5076 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5077 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5078 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5082 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5083 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5088 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5091 if(AOP_TYPE(result) == AOP_CRY) {
5092 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5097 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5099 /* fix me. probably need to check result size too */
5100 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5105 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5115 } else if(AOP_TYPE(right) == AOP_REG &&
5116 AOP_TYPE(left) != AOP_DIR){
5120 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5121 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5122 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5127 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5132 /* right is a pointer reg need both a & b */
5135 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5137 pic14_emitcode("mov","b,%s",l);
5138 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5139 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5144 emitpcode(POC_INCF,popGet(AOP(result),0));
5146 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5148 emitpLabel(lbl->key);
5150 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5159 /*-----------------------------------------------------------------*/
5160 /* gencjne - compare and jump if not equal */
5161 /*-----------------------------------------------------------------*/
5162 static void gencjne(operand *left, operand *right, iCode *ifx)
5164 symbol *tlbl = newiTempLabel(NULL);
5166 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5167 gencjneshort(left, right, lbl);
5169 pic14_emitcode("mov","a,%s",one);
5170 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5171 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5172 pic14_emitcode("clr","a");
5173 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5175 emitpLabel(lbl->key);
5176 emitpLabel(tlbl->key);
5181 /*-----------------------------------------------------------------*/
5182 /* genCmpEq - generates code for equal to */
5183 /*-----------------------------------------------------------------*/
5184 static void genCmpEq (iCode *ic, iCode *ifx)
5186 operand *left, *right, *result;
5188 symbol *false_label;
5191 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5194 DEBUGpic14_emitcode ("; ifx is non-null","");
5196 DEBUGpic14_emitcode ("; ifx is null","");
5198 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5199 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5200 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5202 DEBUGpic14_AopType(__LINE__,left,right,result);
5204 /* if literal, move literal to right */
5205 if (op_isLitLike (IC_LEFT(ic))) {
5206 operand *tmp = right ;
5212 if (ifx && !IC_TRUE(ifx))
5214 assert (IC_FALSE(ifx));
5215 false_label = IC_FALSE(ifx);
5218 size = min(AOP_SIZE(left),AOP_SIZE(right));
5219 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5220 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5222 /* assume left != right */
5225 for (i=0; i < AOP_SIZE(result); i++)
5227 emitpcode(POC_CLRF, popGet(AOP(result),i));
5231 if (AOP_TYPE(right) == AOP_LIT)
5233 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5235 size = AOP_SIZE(left);
5236 assert(!op_isLitLike(left));
5241 mov2w(AOP(left), 0);
5242 for (i=1; i < size; i++)
5243 emitpcode(POC_IORFW,popGet(AOP(left),i));
5244 /* now Z is set iff `left == right' */
5246 if (!false_label) false_label = newiTempLabel(NULL);
5247 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5251 for (i=0; i < size; i++)
5254 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5255 /* now Z is cleared if `left != right' */
5257 if (!false_label) false_label = newiTempLabel(NULL);
5258 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5265 /* right is no literal */
5268 for (i=0; i < size; i++)
5270 mov2w(AOP(right),i);
5271 emitpcode(POC_XORFW,popGet(AOP(left),i));
5272 /* now Z is cleared if `left != right' */
5274 if (!false_label) false_label = newiTempLabel(NULL);
5275 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5279 /* if we reach here, left == right */
5281 if (AOP_SIZE(result) > 0)
5283 emitpcode(POC_INCF, popGet(AOP(result),0));
5286 if (ifx && IC_TRUE(ifx))
5288 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5291 if (false_label && (!ifx || IC_TRUE(ifx)))
5292 emitpLabel(false_label->key);
5294 if (ifx) ifx->generated = 1;
5296 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5297 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5298 freeAsmop(result,NULL,ic,TRUE);
5301 /*-----------------------------------------------------------------*/
5302 /* ifxForOp - returns the icode containing the ifx for operand */
5303 /*-----------------------------------------------------------------*/
5304 static iCode *ifxForOp ( operand *op, iCode *ic )
5307 /* if true symbol then needs to be assigned */
5308 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5309 if (IS_TRUE_SYMOP(op))
5312 /* if this has register type condition and
5313 the next instruction is ifx with the same operand
5314 and live to of the operand is upto the ifx only then */
5316 ic->next->op == IFX &&
5317 IC_COND(ic->next)->key == op->key &&
5318 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5322 ic->next->op == IFX &&
5323 IC_COND(ic->next)->key == op->key) {
5324 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5328 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5330 ic->next->op == IFX)
5331 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5334 ic->next->op == IFX &&
5335 IC_COND(ic->next)->key == op->key) {
5336 DEBUGpic14_emitcode ("; "," key is okay");
5337 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5338 OP_SYMBOL(op)->liveTo,
5345 /*-----------------------------------------------------------------*/
5346 /* genAndOp - for && operation */
5347 /*-----------------------------------------------------------------*/
5348 static void genAndOp (iCode *ic)
5350 operand *left,*right, *result;
5354 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5355 /* note here that && operations that are in an
5356 if statement are taken away by backPatchLabels
5357 only those used in arthmetic operations remain */
5358 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5359 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5360 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5362 DEBUGpic14_AopType(__LINE__,left,right,result);
5364 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5365 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5366 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5368 /* if both are bit variables */
5369 /* if (AOP_TYPE(left) == AOP_CRY && */
5370 /* AOP_TYPE(right) == AOP_CRY ) { */
5371 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5372 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5373 /* pic14_outBitC(result); */
5375 /* tlbl = newiTempLabel(NULL); */
5376 /* pic14_toBoolean(left); */
5377 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5378 /* pic14_toBoolean(right); */
5379 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5380 /* pic14_outBitAcc(result); */
5383 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5384 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5385 freeAsmop(result,NULL,ic,TRUE);
5389 /*-----------------------------------------------------------------*/
5390 /* genOrOp - for || operation */
5391 /*-----------------------------------------------------------------*/
5394 modified this code, but it doesn't appear to ever get called
5397 static void genOrOp (iCode *ic)
5399 operand *left,*right, *result;
5403 /* note here that || operations that are in an
5404 if statement are taken away by backPatchLabels
5405 only those used in arthmetic operations remain */
5407 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5408 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5409 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5410 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5412 DEBUGpic14_AopType(__LINE__,left,right,result);
5414 for (i=0; i < AOP_SIZE(result); i++)
5416 emitpcode(POC_CLRF, popGet(AOP(result), i));
5419 tlbl = newiTempLabel(NULL);
5420 pic14_toBoolean(left);
5422 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5423 pic14_toBoolean(right);
5424 emitpLabel(tlbl->key);
5425 /* here Z is clear IFF `left || right' */
5427 emitpcode(POC_INCF, popGet(AOP(result), 0));
5429 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5430 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5431 freeAsmop(result,NULL,ic,TRUE);
5434 /*-----------------------------------------------------------------*/
5435 /* isLiteralBit - test if lit == 2^n */
5436 /*-----------------------------------------------------------------*/
5437 static int isLiteralBit(unsigned long lit)
5439 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5440 0x100L,0x200L,0x400L,0x800L,
5441 0x1000L,0x2000L,0x4000L,0x8000L,
5442 0x10000L,0x20000L,0x40000L,0x80000L,
5443 0x100000L,0x200000L,0x400000L,0x800000L,
5444 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5445 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5449 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5450 for(idx = 0; idx < 32; idx++)
5456 /*-----------------------------------------------------------------*/
5457 /* continueIfTrue - */
5458 /*-----------------------------------------------------------------*/
5459 static void continueIfTrue (iCode *ic)
5462 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5466 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5467 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5472 /*-----------------------------------------------------------------*/
5474 /*-----------------------------------------------------------------*/
5475 static void jumpIfTrue (iCode *ic)
5478 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5482 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5483 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5488 /*-----------------------------------------------------------------*/
5489 /* jmpTrueOrFalse - */
5490 /*-----------------------------------------------------------------*/
5491 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5494 // ugly but optimized by peephole
5495 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5497 symbol *nlbl = newiTempLabel(NULL);
5498 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5499 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5500 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5501 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5504 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5505 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5510 /*-----------------------------------------------------------------*/
5511 /* genAnd - code for and */
5512 /*-----------------------------------------------------------------*/
5513 static void genAnd (iCode *ic, iCode *ifx)
5515 operand *left, *right, *result;
5517 unsigned long lit = 0L;
5522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5523 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5524 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5525 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5527 resolveIfx(&rIfx,ifx);
5529 /* if left is a literal & right is not then exchange them */
5530 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5531 AOP_NEEDSACC(left)) {
5532 operand *tmp = right ;
5537 /* if result = right then exchange them */
5538 if(pic14_sameRegs(AOP(result),AOP(right))){
5539 operand *tmp = right ;
5544 /* if right is bit then exchange them */
5545 if (AOP_TYPE(right) == AOP_CRY &&
5546 AOP_TYPE(left) != AOP_CRY){
5547 operand *tmp = right ;
5551 if(AOP_TYPE(right) == AOP_LIT)
5552 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5554 size = AOP_SIZE(result);
5556 DEBUGpic14_AopType(__LINE__,left,right,result);
5559 // result = bit & yy;
5560 if (AOP_TYPE(left) == AOP_CRY){
5561 // c = bit & literal;
5562 if(AOP_TYPE(right) == AOP_LIT){
5564 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5567 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5570 if(size && (AOP_TYPE(result) == AOP_CRY)){
5571 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5574 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5578 pic14_emitcode("clr","c");
5581 if (AOP_TYPE(right) == AOP_CRY){
5583 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5584 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5587 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5589 pic14_emitcode("rrc","a");
5590 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5596 pic14_outBitC(result);
5598 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5599 genIfxJump(ifx, "c");
5603 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5604 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5605 if((AOP_TYPE(right) == AOP_LIT) &&
5606 (AOP_TYPE(result) == AOP_CRY) &&
5607 (AOP_TYPE(left) != AOP_CRY)){
5608 int posbit = isLiteralBit(lit);
5612 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5615 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5620 while (posbit > 7) {
5624 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5625 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5626 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5633 symbol *tlbl = newiTempLabel(NULL);
5634 int sizel = AOP_SIZE(left);
5636 pic14_emitcode("setb","c");
5638 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5639 mov2w( AOP(left), offset);
5641 if((posbit = isLiteralBit(bytelit)) != 0) {
5642 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5643 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5644 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5647 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5648 if (rIfx.condition) emitSKPZ;
5651 if(bytelit != 0x0FFL)
5653 pic14_emitcode("anl","a,%s",
5654 aopGet(AOP(right),offset,FALSE,TRUE));
5656 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5659 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5665 // bit = left & literal
5667 pic14_emitcode("clr","c");
5668 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5670 // if(left & literal)
5673 jmpTrueOrFalse(ifx, tlbl);
5677 pic14_outBitC(result);
5681 /* if left is same as result */
5682 if(pic14_sameRegs(AOP(result),AOP(left))){
5684 for(;size--; offset++,lit>>=8) {
5685 if(AOP_TYPE(right) == AOP_LIT){
5686 switch(lit & 0xff) {
5688 /* and'ing with 0 has clears the result */
5689 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5692 /* and'ing with 0xff is a nop when the result and left are the same */
5697 int p = my_powof2( (~lit) & 0xff );
5699 /* only one bit is set in the literal, so use a bcf instruction */
5700 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5703 if(know_W != (int)(lit&0xff))
5704 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5706 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5711 if (AOP_TYPE(left) == AOP_ACC) {
5712 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5714 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5715 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5722 // left & result in different registers
5723 if(AOP_TYPE(result) == AOP_CRY){
5725 // if(size), result in bit
5726 // if(!size && ifx), conditional oper: if(left & right)
5727 symbol *tlbl = newiTempLabel(NULL);
5728 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5730 pic14_emitcode("setb","c");
5732 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5733 pic14_emitcode("anl","a,%s",
5734 aopGet(AOP(left),offset,FALSE,FALSE));
5735 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5740 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5741 pic14_outBitC(result);
5743 jmpTrueOrFalse(ifx, tlbl);
5745 for(;(size--);offset++) {
5747 // result = left & right
5748 if(AOP_TYPE(right) == AOP_LIT){
5749 int t = (lit >> (offset*8)) & 0x0FFL;
5752 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5755 if(AOP_TYPE(left) != AOP_ACC) {
5756 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5758 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5761 if(AOP_TYPE(left) == AOP_ACC) {
5762 emitpcode(POC_ANDLW, popGetLit(t));
5764 emitpcode(POC_MOVLW, popGetLit(t));
5765 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5767 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5772 if (AOP_TYPE(left) == AOP_ACC) {
5773 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5775 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5776 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5778 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5784 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5785 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5786 freeAsmop(result,NULL,ic,TRUE);
5789 /*-----------------------------------------------------------------*/
5790 /* genOr - code for or */
5791 /*-----------------------------------------------------------------*/
5792 static void genOr (iCode *ic, iCode *ifx)
5794 operand *left, *right, *result;
5796 unsigned long lit = 0L;
5799 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5801 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5802 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5803 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5805 DEBUGpic14_AopType(__LINE__,left,right,result);
5807 /* if left is a literal & right is not then exchange them */
5808 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5809 AOP_NEEDSACC(left)) {
5810 operand *tmp = right ;
5815 /* if result = right then exchange them */
5816 if(pic14_sameRegs(AOP(result),AOP(right))){
5817 operand *tmp = right ;
5822 /* if right is bit then exchange them */
5823 if (AOP_TYPE(right) == AOP_CRY &&
5824 AOP_TYPE(left) != AOP_CRY){
5825 operand *tmp = right ;
5830 DEBUGpic14_AopType(__LINE__,left,right,result);
5832 if(AOP_TYPE(right) == AOP_LIT)
5833 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5835 size = AOP_SIZE(result);
5839 if (AOP_TYPE(left) == AOP_CRY){
5840 if(AOP_TYPE(right) == AOP_LIT){
5841 // c = bit & literal;
5843 // lit != 0 => result = 1
5844 if(AOP_TYPE(result) == AOP_CRY){
5846 emitpcode(POC_BSF, popGet(AOP(result),0));
5847 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5848 // AOP(result)->aopu.aop_dir,
5849 // AOP(result)->aopu.aop_dir);
5851 continueIfTrue(ifx);
5855 // lit == 0 => result = left
5856 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5858 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5861 if (AOP_TYPE(right) == AOP_CRY){
5862 if(pic14_sameRegs(AOP(result),AOP(left))){
5864 emitpcode(POC_BCF, popGet(AOP(result),0));
5865 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5866 emitpcode(POC_BSF, popGet(AOP(result),0));
5868 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5869 AOP(result)->aopu.aop_dir,
5870 AOP(result)->aopu.aop_dir);
5871 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5872 AOP(right)->aopu.aop_dir,
5873 AOP(right)->aopu.aop_dir);
5874 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5875 AOP(result)->aopu.aop_dir,
5876 AOP(result)->aopu.aop_dir);
5878 if( AOP_TYPE(result) == AOP_ACC) {
5879 emitpcode(POC_MOVLW, popGetLit(0));
5880 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5881 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5882 emitpcode(POC_MOVLW, popGetLit(1));
5886 emitpcode(POC_BCF, popGet(AOP(result),0));
5887 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5888 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5889 emitpcode(POC_BSF, popGet(AOP(result),0));
5891 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5892 AOP(result)->aopu.aop_dir,
5893 AOP(result)->aopu.aop_dir);
5894 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5895 AOP(right)->aopu.aop_dir,
5896 AOP(right)->aopu.aop_dir);
5897 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5898 AOP(left)->aopu.aop_dir,
5899 AOP(left)->aopu.aop_dir);
5900 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5901 AOP(result)->aopu.aop_dir,
5902 AOP(result)->aopu.aop_dir);
5907 symbol *tlbl = newiTempLabel(NULL);
5908 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5911 emitpcode(POC_BCF, popGet(AOP(result),0));
5912 if( AOP_TYPE(right) == AOP_ACC) {
5913 emitpcode(POC_IORLW, popGetLit(0));
5915 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5916 emitpcode(POC_BSF, popGet(AOP(result),0));
5921 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5922 pic14_emitcode(";XXX setb","c");
5923 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5924 AOP(left)->aopu.aop_dir,tlbl->key+100);
5925 pic14_toBoolean(right);
5926 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5927 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5928 jmpTrueOrFalse(ifx, tlbl);
5932 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5939 pic14_outBitC(result);
5941 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5942 genIfxJump(ifx, "c");
5946 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5947 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5948 if((AOP_TYPE(right) == AOP_LIT) &&
5949 (AOP_TYPE(result) == AOP_CRY) &&
5950 (AOP_TYPE(left) != AOP_CRY)){
5952 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5955 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5957 continueIfTrue(ifx);
5960 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5961 // lit = 0, result = boolean(left)
5963 pic14_emitcode(";XXX setb","c");
5964 pic14_toBoolean(right);
5966 symbol *tlbl = newiTempLabel(NULL);
5967 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5969 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5971 genIfxJump (ifx,"a");
5975 pic14_outBitC(result);
5979 /* if left is same as result */
5980 if(pic14_sameRegs(AOP(result),AOP(left))){
5982 for(;size--; offset++,lit>>=8) {
5983 if(AOP_TYPE(right) == AOP_LIT){
5984 if((lit & 0xff) == 0)
5985 /* or'ing with 0 has no effect */
5988 int p = my_powof2(lit & 0xff);
5990 /* only one bit is set in the literal, so use a bsf instruction */
5992 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5994 if(know_W != (int)(lit & 0xff))
5995 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5996 know_W = lit & 0xff;
5997 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6002 if (AOP_TYPE(left) == AOP_ACC) {
6003 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6004 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6006 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6007 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6009 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6010 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6016 // left & result in different registers
6017 if(AOP_TYPE(result) == AOP_CRY){
6019 // if(size), result in bit
6020 // if(!size && ifx), conditional oper: if(left | right)
6021 symbol *tlbl = newiTempLabel(NULL);
6022 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6023 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6027 pic14_emitcode(";XXX setb","c");
6029 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6030 pic14_emitcode(";XXX orl","a,%s",
6031 aopGet(AOP(left),offset,FALSE,FALSE));
6032 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6037 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6038 pic14_outBitC(result);
6040 jmpTrueOrFalse(ifx, tlbl);
6041 } else for(;(size--);offset++){
6043 // result = left | right
6044 if(AOP_TYPE(right) == AOP_LIT){
6045 int t = (lit >> (offset*8)) & 0x0FFL;
6048 if (AOP_TYPE(left) != AOP_ACC) {
6049 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6051 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6055 if (AOP_TYPE(left) == AOP_ACC) {
6056 emitpcode(POC_IORLW, popGetLit(t));
6058 emitpcode(POC_MOVLW, popGetLit(t));
6059 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6061 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6066 // faster than result <- left, anl result,right
6067 // and better if result is SFR
6068 if (AOP_TYPE(left) == AOP_ACC) {
6069 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6071 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6072 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6074 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6079 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6080 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6081 freeAsmop(result,NULL,ic,TRUE);
6084 /*-----------------------------------------------------------------*/
6085 /* genXor - code for xclusive or */
6086 /*-----------------------------------------------------------------*/
6087 static void genXor (iCode *ic, iCode *ifx)
6089 operand *left, *right, *result;
6091 unsigned long lit = 0L;
6094 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6096 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6097 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6098 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6100 /* if left is a literal & right is not ||
6101 if left needs acc & right does not */
6102 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6103 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6104 operand *tmp = right ;
6109 /* if result = right then exchange them */
6110 if(pic14_sameRegs(AOP(result),AOP(right))){
6111 operand *tmp = right ;
6116 /* if right is bit then exchange them */
6117 if (AOP_TYPE(right) == AOP_CRY &&
6118 AOP_TYPE(left) != AOP_CRY){
6119 operand *tmp = right ;
6123 if(AOP_TYPE(right) == AOP_LIT)
6124 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6126 size = AOP_SIZE(result);
6130 if (AOP_TYPE(left) == AOP_CRY){
6131 if(AOP_TYPE(right) == AOP_LIT){
6132 // c = bit & literal;
6134 // lit>>1 != 0 => result = 1
6135 if(AOP_TYPE(result) == AOP_CRY){
6137 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6138 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6140 continueIfTrue(ifx);
6143 pic14_emitcode("setb","c");
6147 // lit == 0, result = left
6148 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6150 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6152 // lit == 1, result = not(left)
6153 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6154 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6155 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6156 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6159 assert ( !"incomplete genXor" );
6160 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6161 pic14_emitcode("cpl","c");
6168 symbol *tlbl = newiTempLabel(NULL);
6169 if (AOP_TYPE(right) == AOP_CRY){
6171 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6174 int sizer = AOP_SIZE(right);
6176 // if val>>1 != 0, result = 1
6177 pic14_emitcode("setb","c");
6179 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6181 // test the msb of the lsb
6182 pic14_emitcode("anl","a,#0xfe");
6183 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6187 pic14_emitcode("rrc","a");
6189 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6190 pic14_emitcode("cpl","c");
6191 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6196 pic14_outBitC(result);
6198 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6199 genIfxJump(ifx, "c");
6203 if(pic14_sameRegs(AOP(result),AOP(left))){
6204 /* if left is same as result */
6205 for(;size--; offset++) {
6206 if(AOP_TYPE(right) == AOP_LIT){
6207 int t = (lit >> (offset*8)) & 0x0FFL;
6211 if (IS_AOP_PREG(left)) {
6212 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6213 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6214 aopPut(AOP(result),"a",offset);
6216 emitpcode(POC_MOVLW, popGetLit(t));
6217 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6218 pic14_emitcode("xrl","%s,%s",
6219 aopGet(AOP(left),offset,FALSE,TRUE),
6220 aopGet(AOP(right),offset,FALSE,FALSE));
6223 if (AOP_TYPE(left) == AOP_ACC)
6224 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6226 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6227 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6229 if (IS_AOP_PREG(left)) {
6230 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6231 aopPut(AOP(result),"a",offset);
6233 pic14_emitcode("xrl","%s,a",
6234 aopGet(AOP(left),offset,FALSE,TRUE));
6240 // left & result in different registers
6241 if(AOP_TYPE(result) == AOP_CRY){
6243 // if(size), result in bit
6244 // if(!size && ifx), conditional oper: if(left ^ right)
6245 symbol *tlbl = newiTempLabel(NULL);
6246 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6248 pic14_emitcode("setb","c");
6250 if((AOP_TYPE(right) == AOP_LIT) &&
6251 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6252 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6254 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6255 pic14_emitcode("xrl","a,%s",
6256 aopGet(AOP(left),offset,FALSE,FALSE));
6258 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6263 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6264 pic14_outBitC(result);
6266 jmpTrueOrFalse(ifx, tlbl);
6267 } else for(;(size--);offset++){
6269 // result = left & right
6270 if(AOP_TYPE(right) == AOP_LIT){
6271 int t = (lit >> (offset*8)) & 0x0FFL;
6274 if (AOP_TYPE(left) != AOP_ACC) {
6275 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6277 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6278 pic14_emitcode("movf","%s,w",
6279 aopGet(AOP(left),offset,FALSE,FALSE));
6280 pic14_emitcode("movwf","%s",
6281 aopGet(AOP(result),offset,FALSE,FALSE));
6284 if (AOP_TYPE(left) == AOP_ACC) {
6285 emitpcode(POC_XORLW, popGetLit(t));
6287 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6289 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6292 if (AOP_TYPE(left) == AOP_ACC) {
6293 emitpcode(POC_XORLW, popGetLit(t));
6295 emitpcode(POC_MOVLW, popGetLit(t));
6296 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6298 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6299 pic14_emitcode("movlw","0x%x",t);
6300 pic14_emitcode("xorwf","%s,w",
6301 aopGet(AOP(left),offset,FALSE,FALSE));
6302 pic14_emitcode("movwf","%s",
6303 aopGet(AOP(result),offset,FALSE,FALSE));
6309 // faster than result <- left, anl result,right
6310 // and better if result is SFR
6311 if (AOP_TYPE(left) == AOP_ACC) {
6312 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6314 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6315 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6317 if ( AOP_TYPE(result) != AOP_ACC){
6318 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6324 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6325 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326 freeAsmop(result,NULL,ic,TRUE);
6329 /*-----------------------------------------------------------------*/
6330 /* genInline - write the inline code out */
6331 /*-----------------------------------------------------------------*/
6332 static void genInline (iCode *ic)
6334 char *buffer, *bp, *bp1;
6337 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6339 _G.inLine += (!options.asmpeep);
6341 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6342 strcpy(buffer,IC_INLINE(ic));
6344 /* emit each line as a code */
6350 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6358 /* print label, use this special format with NULL directive
6359 * to denote that the argument should not be indented with tab */
6360 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6367 if ((bp1 != bp) && *bp1)
6368 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6372 _G.inLine -= (!options.asmpeep);
6375 /*-----------------------------------------------------------------*/
6376 /* genRRC - rotate right with carry */
6377 /*-----------------------------------------------------------------*/
6378 static void genRRC (iCode *ic)
6380 operand *left , *result ;
6381 int size, offset = 0, same;
6384 /* rotate right with carry */
6386 result=IC_RESULT(ic);
6387 aopOp (left,ic,FALSE);
6388 aopOp (result,ic,FALSE);
6390 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6392 same = pic14_sameRegs(AOP(result),AOP(left));
6394 size = AOP_SIZE(result);
6396 /* get the lsb and put it into the carry */
6397 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6404 emitpcode(POC_RRF, popGet(AOP(left),offset));
6406 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6407 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6413 freeAsmop(left,NULL,ic,TRUE);
6414 freeAsmop(result,NULL,ic,TRUE);
6417 /*-----------------------------------------------------------------*/
6418 /* genRLC - generate code for rotate left with carry */
6419 /*-----------------------------------------------------------------*/
6420 static void genRLC (iCode *ic)
6422 operand *left , *result ;
6423 int size, offset = 0;
6427 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6428 /* rotate right with carry */
6430 result=IC_RESULT(ic);
6431 aopOp (left,ic,FALSE);
6432 aopOp (result,ic,FALSE);
6434 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6436 same = pic14_sameRegs(AOP(result),AOP(left));
6438 /* move it to the result */
6439 size = AOP_SIZE(result);
6441 /* get the msb and put it into the carry */
6442 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6449 emitpcode(POC_RLF, popGet(AOP(left),offset));
6451 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6452 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6459 freeAsmop(left,NULL,ic,TRUE);
6460 freeAsmop(result,NULL,ic,TRUE);
6463 /*-----------------------------------------------------------------*/
6464 /* genGetHbit - generates code get highest order bit */
6465 /*-----------------------------------------------------------------*/
6466 static void genGetHbit (iCode *ic)
6468 operand *left, *result;
6470 result=IC_RESULT(ic);
6471 aopOp (left,ic,FALSE);
6472 aopOp (result,ic,FALSE);
6475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6476 /* get the highest order byte into a */
6477 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6478 if(AOP_TYPE(result) == AOP_CRY){
6479 pic14_emitcode("rlc","a");
6480 pic14_outBitC(result);
6483 pic14_emitcode("rl","a");
6484 pic14_emitcode("anl","a,#0x01");
6485 pic14_outAcc(result);
6489 freeAsmop(left,NULL,ic,TRUE);
6490 freeAsmop(result,NULL,ic,TRUE);
6493 /*-----------------------------------------------------------------*/
6494 /* AccLsh - shift left accumulator by known count */
6495 /* MARK: pic14 always rotates through CARRY! */
6496 /*-----------------------------------------------------------------*/
6497 static void AccLsh (pCodeOp *pcop,int shCount)
6500 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6501 shCount &= 0x0007; // shCount : 0..7
6508 emitpcode(POC_RLF,pcop);
6512 emitpcode(POC_RLF,pcop);
6513 emitpcode(POC_RLF,pcop);
6516 emitpcode(POC_RLF,pcop);
6517 emitpcode(POC_RLF,pcop);
6518 emitpcode(POC_RLF,pcop);
6521 emitpcode(POC_SWAPF,pcop);
6524 emitpcode(POC_SWAPF,pcop);
6525 emitpcode(POC_RLF,pcop);
6528 emitpcode(POC_SWAPF,pcop);
6529 emitpcode(POC_RLF,pcop);
6530 emitpcode(POC_RLF,pcop);
6533 emitpcode(POC_RRFW,pcop);
6534 emitpcode(POC_RRF,pcop);
6537 /* clear invalid bits */
6538 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6539 emitpcode(POC_ANDWF, pcop);
6542 /*-----------------------------------------------------------------*/
6543 /* AccRsh - shift right accumulator by known count */
6544 /* MARK: pic14 always rotates through CARRY! */
6545 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6546 /* 1: mask out invalid bits (zero-extend) */
6547 /* 2: sign-extend result (pretty slow) */
6548 /*-----------------------------------------------------------------*/
6549 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6552 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6553 shCount &= 0x0007; // shCount : 0..7
6559 /* load sign if needed */
6560 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6561 else if (mask_mode == 1) emitCLRC;
6562 emitpcode(POC_RRF,pcop);
6566 /* load sign if needed */
6567 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568 emitpcode(POC_RRF,pcop);
6569 /* load sign if needed */
6570 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6571 emitpcode(POC_RRF,pcop);
6572 if (mask_mode == 2) return;
6575 /* load sign if needed */
6576 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6577 emitpcode(POC_RRF,pcop);
6578 /* load sign if needed */
6579 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6580 emitpcode(POC_RRF,pcop);
6581 /* load sign if needed */
6582 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6583 emitpcode(POC_RRF,pcop);
6584 if (mask_mode == 2) return;
6587 emitpcode(POC_SWAPF,pcop);
6590 emitpcode(POC_SWAPF,pcop);
6591 emitpcode(POC_RRF,pcop);
6594 emitpcode(POC_SWAPF,pcop);
6595 emitpcode(POC_RRF,pcop);
6596 emitpcode(POC_RRF,pcop);
6602 emitpcode(POC_RLFW,pcop);
6603 emitpcode(POC_CLRF,pcop);
6605 emitpcode(POC_COMF,pcop);
6608 emitpcode(POC_RLFW,pcop);
6609 emitpcode(POC_RLF,pcop);
6616 /* leave invalid bits undefined */
6620 /* clear invalid bits -- zero-extend */
6621 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6622 emitpcode(POC_ANDWF, pcop);
6624 if (mask_mode == 2) {
6626 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6627 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6628 emitpcode(POC_IORWF, pcop);
6633 /*-----------------------------------------------------------------*/
6634 /* AccSRsh - signed right shift accumulator by known count */
6635 /*-----------------------------------------------------------------*/
6636 static void AccSRsh (int shCount)
6639 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6642 pic14_emitcode("mov","c,acc.7");
6643 pic14_emitcode("rrc","a");
6644 } else if(shCount == 2){
6645 pic14_emitcode("mov","c,acc.7");
6646 pic14_emitcode("rrc","a");
6647 pic14_emitcode("mov","c,acc.7");
6648 pic14_emitcode("rrc","a");
6650 tlbl = newiTempLabel(NULL);
6651 /* rotate right accumulator */
6652 AccRol(8 - shCount);
6653 /* and kill the higher order bits */
6654 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6655 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6656 pic14_emitcode("orl","a,#0x%02x",
6657 (unsigned char)~SRMask[shCount]);
6658 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6663 /*-----------------------------------------------------------------*/
6664 /* shiftR1Left2Result - shift right one byte from left to result */
6665 /*-----------------------------------------------------------------*/
6666 static void shiftR1Left2ResultSigned (operand *left, int offl,
6667 operand *result, int offr,
6673 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6675 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6679 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6681 emitpcode(POC_RRF, popGet(AOP(result),offr));
6683 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6684 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6690 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6692 emitpcode(POC_RRF, popGet(AOP(result),offr));
6694 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6695 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6697 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6698 emitpcode(POC_RRF, popGet(AOP(result),offr));
6704 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6706 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6707 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6710 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6711 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6712 emitpcode(POC_ANDLW, popGetLit(0x1f));
6714 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6715 emitpcode(POC_IORLW, popGetLit(0xe0));
6717 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6721 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6722 emitpcode(POC_ANDLW, popGetLit(0x0f));
6723 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6724 emitpcode(POC_IORLW, popGetLit(0xf0));
6725 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6729 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6731 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6732 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6734 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6735 emitpcode(POC_ANDLW, popGetLit(0x07));
6736 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6737 emitpcode(POC_IORLW, popGetLit(0xf8));
6738 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6743 emitpcode(POC_MOVLW, popGetLit(0x00));
6744 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6745 emitpcode(POC_MOVLW, popGetLit(0xfe));
6746 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6747 emitpcode(POC_IORLW, popGetLit(0x01));
6748 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6750 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6751 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6752 emitpcode(POC_DECF, popGet(AOP(result),offr));
6753 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6754 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6760 emitpcode(POC_MOVLW, popGetLit(0x00));
6761 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6762 emitpcode(POC_MOVLW, popGetLit(0xff));
6763 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6765 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6766 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6767 emitpcode(POC_DECF, popGet(AOP(result),offr));
6775 /*-----------------------------------------------------------------*/
6776 /* shiftR1Left2Result - shift right one byte from left to result */
6777 /*-----------------------------------------------------------------*/
6778 static void shiftR1Left2Result (operand *left, int offl,
6779 operand *result, int offr,
6780 int shCount, int sign)
6785 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6787 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6789 /* Copy the msb into the carry if signed. */
6791 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6801 emitpcode(POC_RRF, popGet(AOP(result),offr));
6803 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6804 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6810 emitpcode(POC_RRF, popGet(AOP(result),offr));
6812 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6813 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6816 emitpcode(POC_RRF, popGet(AOP(result),offr));
6821 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6823 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6824 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6827 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6828 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6829 emitpcode(POC_ANDLW, popGetLit(0x1f));
6830 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6834 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6835 emitpcode(POC_ANDLW, popGetLit(0x0f));
6836 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6841 emitpcode(POC_ANDLW, popGetLit(0x0f));
6842 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6844 emitpcode(POC_RRF, popGet(AOP(result),offr));
6849 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6850 emitpcode(POC_ANDLW, popGetLit(0x80));
6851 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6852 emitpcode(POC_RLF, popGet(AOP(result),offr));
6853 emitpcode(POC_RLF, popGet(AOP(result),offr));
6858 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6859 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6860 emitpcode(POC_RLF, popGet(AOP(result),offr));
6869 /*-----------------------------------------------------------------*/
6870 /* shiftL1Left2Result - shift left one byte from left to result */
6871 /*-----------------------------------------------------------------*/
6872 static void shiftL1Left2Result (operand *left, int offl,
6873 operand *result, int offr, int shCount)
6879 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6881 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6882 DEBUGpic14_emitcode ("; ***","same = %d",same);
6883 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6885 /* shift left accumulator */
6886 //AccLsh(shCount); // don't comment out just yet...
6887 // aopPut(AOP(result),"a",offr);
6891 /* Shift left 1 bit position */
6892 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6894 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6896 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6897 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6901 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6902 emitpcode(POC_ANDLW,popGetLit(0x7e));
6903 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6904 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6907 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6908 emitpcode(POC_ANDLW,popGetLit(0x3e));
6909 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6910 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911 emitpcode(POC_RLF, popGet(AOP(result),offr));
6914 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6915 emitpcode(POC_ANDLW, popGetLit(0xf0));
6916 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6919 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6920 emitpcode(POC_ANDLW, popGetLit(0xf0));
6921 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6922 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6925 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6926 emitpcode(POC_ANDLW, popGetLit(0x30));
6927 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6928 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6929 emitpcode(POC_RLF, popGet(AOP(result),offr));
6932 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6933 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6934 emitpcode(POC_RRF, popGet(AOP(result),offr));
6938 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6944 /*-----------------------------------------------------------------*/
6945 /* movLeft2Result - move byte from left to result */
6946 /*-----------------------------------------------------------------*/
6947 static void movLeft2Result (operand *left, int offl,
6948 operand *result, int offr)
6952 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6953 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6954 l = aopGet(AOP(left),offl,FALSE,FALSE);
6956 if (*l == '@' && (IS_AOP_PREG(result))) {
6957 pic14_emitcode("mov","a,%s",l);
6958 aopPut(AOP(result),"a",offr);
6960 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6961 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6966 /*-----------------------------------------------------------------*/
6967 /* shiftLeft_Left2ResultLit - shift left by known count */
6968 /*-----------------------------------------------------------------*/
6970 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6972 int size, same, offr, i;
6974 size = AOP_SIZE(left);
6975 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6977 same = pic14_sameRegs (AOP(left), AOP(result));
6980 shCount = shCount & 0x07;
6986 case 0: /* takes 0 or 2N cycles (for offr==0) */
6987 if (!same || offr) {
6988 for (i=size-1; i >= 0; i--)
6989 movLeft2Result (left, i, result, offr + i);
6993 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6995 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6996 shiftLeft_Left2ResultLit (result, result, shCount);
6997 return; /* prevent clearing result again */
7000 for (i=0; i < size; i++) {
7001 if (same && !offr) {
7002 emitpcode (POC_RLF, popGet (AOP(left), i));
7004 emitpcode (POC_RLFW, popGet (AOP(left), i));
7005 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7011 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7012 /* works in-place/with offr as well */
7013 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7014 emitpcode (POC_ANDLW, popGetLit (0xF0));
7015 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7017 for (i = size - 2; i >= 0; i--)
7019 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7020 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7021 emitpcode (POC_ANDLW, popGetLit (0x0F));
7022 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7023 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7027 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7028 /* works in-place/with offr as well */
7029 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7030 for (i = size-2; i >= 0; i--) {
7031 emitpcode (POC_RRFW, popGet (AOP(left), i));
7032 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7034 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7035 emitpcode (POC_RRF, popGet (AOP(result), offr));
7039 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7040 shiftLeft_Left2ResultLit (result, result, 1);
7041 return; /* prevent clearing result again */
7047 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7051 /*-----------------------------------------------------------------*/
7052 /* shiftRight_Left2ResultLit - shift right by known count */
7053 /*-----------------------------------------------------------------*/
7055 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7057 int size, same, offr, i;
7059 size = AOP_SIZE(left);
7060 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7062 same = pic14_sameRegs (AOP(left), AOP(result));
7065 shCount = shCount & 0x07;
7073 case 0: /* takes 0 or 2N cycles (for offr==0) */
7074 if (!same || offr) {
7075 for (i=0; i < size; i++)
7076 movLeft2Result (left, i + offr, result, i);
7080 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7081 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7083 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7084 shiftRight_Left2ResultLit (result, result, shCount, sign);
7085 return; /* prevent sign-extending result again */
7089 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7092 for (i = size-1; i >= 0; i--) {
7093 if (same && !offr) {
7094 emitpcode (POC_RRF, popGet (AOP(left), i));
7096 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7097 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7103 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7104 /* works in-place/with offr as well */
7105 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7106 emitpcode (POC_ANDLW, popGetLit (0x0F));
7107 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7109 for (i = 1; i < size; i++)
7111 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7112 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7113 emitpcode (POC_ANDLW, popGetLit (0xF0));
7114 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7115 emitpcode (POC_XORWF, popGet (AOP(result), i));
7120 emitpcode (POC_MOVLW, popGetLit (0xF0));
7121 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7122 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7126 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7127 /* works in-place/with offr as well */
7128 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7129 for (i = 0; i < size-1; i++) {
7130 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7131 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7133 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7135 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7138 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7143 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7144 shiftRight_Left2ResultLit (result, result, 1, sign);
7145 return; /* prevent sign extending result again */
7150 addSign (result, size, sign);
7154 /*-----------------------------------------------------------------*/
7155 /* shiftL2Left2Result - shift left two bytes from left to result */
7156 /*-----------------------------------------------------------------*/
7157 static void shiftL2Left2Result (operand *left, int offl,
7158 operand *result, int offr, int shCount)
7162 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7164 if(pic14_sameRegs(AOP(result), AOP(left))) {
7172 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7173 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7174 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7178 emitpcode(POC_RLF, popGet(AOP(result),offr));
7179 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7185 emitpcode(POC_MOVLW, popGetLit(0x0f));
7186 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7187 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7188 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7189 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7190 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7191 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_RLF, popGet(AOP(result),offr));
7194 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7198 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7199 emitpcode(POC_RRF, popGet(AOP(result),offr));
7200 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7201 emitpcode(POC_RRF, popGet(AOP(result),offr));
7202 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7203 emitpcode(POC_ANDLW,popGetLit(0xc0));
7204 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7205 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7206 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7207 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7210 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7211 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7212 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7213 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7214 emitpcode(POC_RRF, popGet(AOP(result),offr));
7224 /* note, use a mov/add for the shift since the mov has a
7225 chance of getting optimized out */
7226 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7227 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7228 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7229 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7230 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7234 emitpcode(POC_RLF, popGet(AOP(result),offr));
7235 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7241 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7242 emitpcode(POC_ANDLW, popGetLit(0xF0));
7243 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7244 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7245 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7246 emitpcode(POC_ANDLW, popGetLit(0xF0));
7247 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7248 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7252 emitpcode(POC_RLF, popGet(AOP(result),offr));
7253 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7257 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7258 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7259 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7260 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7262 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7263 emitpcode(POC_RRF, popGet(AOP(result),offr));
7264 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7265 emitpcode(POC_ANDLW,popGetLit(0xc0));
7266 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7267 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7268 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7269 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7272 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7273 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7274 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7275 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7276 emitpcode(POC_RRF, popGet(AOP(result),offr));
7282 /*-----------------------------------------------------------------*/
7283 /* shiftR2Left2Result - shift right two bytes from left to result */
7284 /*-----------------------------------------------------------------*/
7285 static void shiftR2Left2Result (operand *left, int offl,
7286 operand *result, int offr,
7287 int shCount, int sign)
7292 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7293 same = pic14_sameRegs(AOP(result), AOP(left));
7295 if(same && ((offl + MSB16) == offr)){
7297 /* don't crash result[offr] */
7298 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7299 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7302 movLeft2Result(left,offl, result, offr);
7303 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7306 /* a:x >> shCount (x = lsb(result))*/
7309 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7311 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7320 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7325 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7326 emitpcode(POC_RRF,popGet(AOP(result),offr));
7328 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7329 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7330 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7331 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7336 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7339 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7340 emitpcode(POC_RRF,popGet(AOP(result),offr));
7347 emitpcode(POC_MOVLW, popGetLit(0xf0));
7348 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7349 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7351 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7352 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7353 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7354 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7356 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7357 emitpcode(POC_ANDLW, popGetLit(0x0f));
7358 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7360 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7361 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7362 emitpcode(POC_ANDLW, popGetLit(0xf0));
7363 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7364 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7368 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7369 emitpcode(POC_RRF, popGet(AOP(result),offr));
7373 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7374 emitpcode(POC_BTFSC,
7375 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7376 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7384 emitpcode(POC_RLF, popGet(AOP(result),offr));
7385 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7387 emitpcode(POC_RLF, popGet(AOP(result),offr));
7388 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7389 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7390 emitpcode(POC_ANDLW,popGetLit(0x03));
7392 emitpcode(POC_BTFSC,
7393 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7394 emitpcode(POC_IORLW,popGetLit(0xfc));
7396 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7397 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7398 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7399 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7401 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7402 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7403 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7404 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7405 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7406 emitpcode(POC_RLF, popGet(AOP(result),offr));
7407 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7408 emitpcode(POC_ANDLW,popGetLit(0x03));
7410 emitpcode(POC_BTFSC,
7411 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7412 emitpcode(POC_IORLW,popGetLit(0xfc));
7414 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7415 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7422 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7423 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7424 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7425 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7428 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7430 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7434 /*-----------------------------------------------------------------*/
7435 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7436 /*-----------------------------------------------------------------*/
7437 static void shiftLLeftOrResult (operand *left, int offl,
7438 operand *result, int offr, int shCount)
7441 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7443 /* shift left accumulator */
7444 AccLsh(left,offl,shCount);
7445 /* or with result */
7446 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7447 assert ( !"broken (modifies left, fails for left==result))" );
7450 /*-----------------------------------------------------------------*/
7451 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7452 /*-----------------------------------------------------------------*/
7453 static void shiftRLeftOrResult (operand *left, int offl,
7454 operand *result, int offr, int shCount)
7457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7459 /* shift right accumulator */
7460 AccRsh(left,offl,shCount);
7461 /* or with result */
7462 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7463 assert ( !"broken (modifies left, fails for left==result))" );
7466 /*-----------------------------------------------------------------*/
7467 /* genlshOne - left shift a one byte quantity by known count */
7468 /*-----------------------------------------------------------------*/
7469 static void genlshOne (operand *result, operand *left, int shCount)
7472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7473 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7476 /*-----------------------------------------------------------------*/
7477 /* genlshTwo - left shift two bytes by known amount != 0 */
7478 /*-----------------------------------------------------------------*/
7479 static void genlshTwo (operand *result,operand *left, int shCount)
7484 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7485 size = pic14_getDataSize(result);
7487 /* if shCount >= 8 */
7493 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7495 movLeft2Result(left, LSB, result, MSB16);
7497 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7500 /* 1 <= shCount <= 7 */
7503 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7505 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7509 /*-----------------------------------------------------------------*/
7510 /* shiftLLong - shift left one long from left to result */
7511 /* offl = LSB or MSB16 */
7512 /*-----------------------------------------------------------------*/
7513 static void shiftLLong (operand *left, operand *result, int offr )
7516 int size = AOP_SIZE(result);
7519 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7520 if(size >= LSB+offr){
7521 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7523 pic14_emitcode("add","a,acc");
7524 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7525 size >= MSB16+offr && offr != LSB )
7526 pic14_emitcode("xch","a,%s",
7527 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7529 aopPut(AOP(result),"a",LSB+offr);
7532 if(size >= MSB16+offr){
7533 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7534 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7537 pic14_emitcode("rlc","a");
7538 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7539 size >= MSB24+offr && offr != LSB)
7540 pic14_emitcode("xch","a,%s",
7541 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7543 aopPut(AOP(result),"a",MSB16+offr);
7546 if(size >= MSB24+offr){
7547 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7548 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7551 pic14_emitcode("rlc","a");
7552 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7553 size >= MSB32+offr && offr != LSB )
7554 pic14_emitcode("xch","a,%s",
7555 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7557 aopPut(AOP(result),"a",MSB24+offr);
7560 if(size > MSB32+offr){
7561 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7562 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7565 pic14_emitcode("rlc","a");
7566 aopPut(AOP(result),"a",MSB32+offr);
7569 aopPut(AOP(result),zero,LSB);
7572 /*-----------------------------------------------------------------*/
7573 /* genlshFour - shift four byte by a known amount != 0 */
7574 /*-----------------------------------------------------------------*/
7575 static void genlshFour (operand *result, operand *left, int shCount)
7580 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7581 size = AOP_SIZE(result);
7583 /* if shifting more that 3 bytes */
7584 if (shCount >= 24 ) {
7587 /* lowest order of left goes to the highest
7588 order of the destination */
7589 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7591 movLeft2Result(left, LSB, result, MSB32);
7592 aopPut(AOP(result),zero,LSB);
7593 aopPut(AOP(result),zero,MSB16);
7594 aopPut(AOP(result),zero,MSB32);
7598 /* more than two bytes */
7599 else if ( shCount >= 16 ) {
7600 /* lower order two bytes goes to higher order two bytes */
7602 /* if some more remaining */
7604 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7606 movLeft2Result(left, MSB16, result, MSB32);
7607 movLeft2Result(left, LSB, result, MSB24);
7609 aopPut(AOP(result),zero,MSB16);
7610 aopPut(AOP(result),zero,LSB);
7614 /* if more than 1 byte */
7615 else if ( shCount >= 8 ) {
7616 /* lower order three bytes goes to higher order three bytes */
7620 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7622 movLeft2Result(left, LSB, result, MSB16);
7624 else{ /* size = 4 */
7626 movLeft2Result(left, MSB24, result, MSB32);
7627 movLeft2Result(left, MSB16, result, MSB24);
7628 movLeft2Result(left, LSB, result, MSB16);
7629 aopPut(AOP(result),zero,LSB);
7631 else if(shCount == 1)
7632 shiftLLong(left, result, MSB16);
7634 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7635 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7636 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7637 aopPut(AOP(result),zero,LSB);
7642 /* 1 <= shCount <= 7 */
7643 else if(shCount <= 2){
7644 shiftLLong(left, result, LSB);
7646 shiftLLong(result, result, LSB);
7648 /* 3 <= shCount <= 7, optimize */
7650 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7651 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7652 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7658 /*-----------------------------------------------------------------*/
7659 /* genLeftShiftLiteral - left shifting by known count */
7660 /*-----------------------------------------------------------------*/
7661 static void genLeftShiftLiteral (operand *left,
7666 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7671 freeAsmop(right,NULL,ic,TRUE);
7673 aopOp(left,ic,FALSE);
7674 aopOp(result,ic,FALSE);
7676 size = getSize(operandType(result));
7679 pic14_emitcode("; shift left ","result %d, left %d",size,
7683 /* I suppose that the left size >= result size */
7686 movLeft2Result(left, size, result, size);
7690 else if(shCount >= (size * 8))
7692 aopPut(AOP(result),zero,size);
7696 genlshOne (result,left,shCount);
7701 genlshTwo (result,left,shCount);
7705 genlshFour (result,left,shCount);
7709 freeAsmop(left,NULL,ic,TRUE);
7710 freeAsmop(result,NULL,ic,TRUE);
7714 /*-----------------------------------------------------------------*
7715 * genMultiAsm - repeat assembly instruction for size of register.
7716 * if endian == 1, then the high byte (i.e base address + size of
7717 * register) is used first else the low byte is used first;
7718 *-----------------------------------------------------------------*/
7719 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7725 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7738 emitpcode(poc, popGet(AOP(reg),offset));
7745 /*-----------------------------------------------------------------*/
7746 /* genLeftShift - generates code for left shifting */
7747 /*-----------------------------------------------------------------*/
7748 static void genLeftShift (iCode *ic)
7750 operand *left,*right, *result;
7752 unsigned long lit = 0L;
7754 symbol *tlbl , *tlbl1;
7758 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7760 right = IC_RIGHT(ic);
7762 result = IC_RESULT(ic);
7764 aopOp(right,ic,FALSE);
7765 aopOp(left,ic,FALSE);
7766 aopOp(result,ic,FALSE);
7769 /* if the shift count is known then do it
7770 as efficiently as possible */
7771 if (AOP_TYPE(right) == AOP_LIT) {
7772 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7776 /* shift count is unknown then we have to form
7777 a loop get the loop count in B : Note: we take
7778 only the lower order byte since shifting
7779 more that 32 bits make no sense anyway, ( the
7780 largest size of an object can be only 32 bits ) */
7782 /* this code fails for RIGHT == RESULT */
7783 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7785 /* now move the left to the result if they are not the
7787 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7788 AOP_SIZE(result) > 1) {
7790 size = AOP_SIZE(result);
7793 l = aopGet(AOP(left),offset,FALSE,TRUE);
7794 if (*l == '@' && (IS_AOP_PREG(result))) {
7796 pic14_emitcode("mov","a,%s",l);
7797 aopPut(AOP(result),"a",offset);
7799 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7800 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7801 //aopPut(AOP(result),l,offset);
7807 if(AOP_TYPE(left) == AOP_LIT)
7808 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7810 size = AOP_SIZE(result);
7812 /* if it is only one byte then */
7814 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7815 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7816 emitpcode(POC_ANDLW, popGetLit(0xf0));
7817 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7818 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7819 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7820 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7821 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7822 emitpcode(POC_RLFW, popGet(AOP(result),0));
7823 emitpcode(POC_ANDLW, popGetLit(0xfe));
7824 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7825 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7826 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7829 tlbl = newiTempLabel(NULL);
7830 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7831 mov2w (AOP(left), 0);
7832 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7835 emitpcode(POC_COMFW, popGet(AOP(right),0));
7836 emitpcode(POC_RRF, popGet(AOP(result),0));
7837 emitpLabel(tlbl->key);
7838 emitpcode(POC_RLF, popGet(AOP(result),0));
7839 emitpcode(POC_ADDLW, popGetLit(1));
7841 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7846 if (pic14_sameRegs(AOP(left),AOP(result))) {
7848 tlbl = newiTempLabel(NULL);
7849 emitpcode(POC_COMFW, popGet(AOP(right),0));
7850 genMultiAsm(POC_RRF, result, size,1);
7851 emitpLabel(tlbl->key);
7852 genMultiAsm(POC_RLF, result, size,0);
7853 emitpcode(POC_ADDLW, popGetLit(1));
7855 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7859 //tlbl = newiTempLabel(NULL);
7861 //tlbl1 = newiTempLabel(NULL);
7863 //reAdjustPreg(AOP(result));
7865 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7866 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7867 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7869 //pic14_emitcode("add","a,acc");
7870 //aopPut(AOP(result),"a",offset++);
7872 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7874 // pic14_emitcode("rlc","a");
7875 // aopPut(AOP(result),"a",offset++);
7877 //reAdjustPreg(AOP(result));
7879 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7880 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7883 tlbl = newiTempLabel(NULL);
7884 tlbl1= newiTempLabel(NULL);
7886 size = AOP_SIZE(result);
7889 pctemp = popGetTempReg(); /* grab a temporary working register. */
7891 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7893 /* offset should be 0, 1 or 3 */
7894 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7896 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7898 emitpcode(POC_MOVWF, pctemp);
7901 emitpLabel(tlbl->key);
7904 emitpcode(POC_RLF, popGet(AOP(result),0));
7906 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7908 emitpcode(POC_DECFSZ, pctemp);
7909 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7910 emitpLabel(tlbl1->key);
7912 popReleaseTempReg(pctemp);
7916 freeAsmop (right,NULL,ic,TRUE);
7917 freeAsmop(left,NULL,ic,TRUE);
7918 freeAsmop(result,NULL,ic,TRUE);
7923 /*-----------------------------------------------------------------*/
7924 /* genrshOne - right shift a one byte quantity by known count */
7925 /*-----------------------------------------------------------------*/
7926 static void genrshOne (operand *result, operand *left,
7927 int shCount, int sign)
7930 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7931 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7934 /*-----------------------------------------------------------------*/
7935 /* genrshTwo - right shift two bytes by known amount != 0 */
7936 /*-----------------------------------------------------------------*/
7937 static void genrshTwo (operand *result,operand *left,
7938 int shCount, int sign)
7941 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7942 /* if shCount >= 8 */
7946 shiftR1Left2Result(left, MSB16, result, LSB,
7949 movLeft2Result(left, MSB16, result, LSB);
7951 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7954 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7955 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7959 /* 1 <= shCount <= 7 */
7961 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7964 /*-----------------------------------------------------------------*/
7965 /* shiftRLong - shift right one long from left to result */
7966 /* offl = LSB or MSB16 */
7967 /*-----------------------------------------------------------------*/
7968 static void shiftRLong (operand *left, int offl,
7969 operand *result, int sign)
7974 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7976 size = AOP_SIZE(left);
7977 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7980 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7984 assert (offl >= 0 && offl < size);
7986 same = pic14_sameRegs (AOP(left), AOP(result));
7988 /* perform the shift */
7991 if (same && !offl) {
7992 emitpcode (POC_RRF, popGet (AOP(result), size));
7994 emitpcode (POC_RRFW, popGet (AOP(left), size));
7995 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7999 addSign (result, AOP_SIZE(left) - offl, sign);
8002 /*-----------------------------------------------------------------*/
8003 /* genrshFour - shift four byte by a known amount != 0 */
8004 /*-----------------------------------------------------------------*/
8005 static void genrshFour (operand *result, operand *left,
8006 int shCount, int sign)
8009 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8010 /* if shifting more that 3 bytes */
8011 if(shCount >= 24 ) {
8014 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8016 movLeft2Result(left, MSB32, result, LSB);
8018 addSign(result, MSB16, sign);
8020 else if(shCount >= 16){
8023 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8025 movLeft2Result(left, MSB24, result, LSB);
8026 movLeft2Result(left, MSB32, result, MSB16);
8028 addSign(result, MSB24, sign);
8030 else if(shCount >= 8){
8033 shiftRLong(left, MSB16, result, sign);
8034 else if(shCount == 0){
8035 movLeft2Result(left, MSB16, result, LSB);
8036 movLeft2Result(left, MSB24, result, MSB16);
8037 movLeft2Result(left, MSB32, result, MSB24);
8038 addSign(result, MSB32, sign);
8041 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8042 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8043 /* the last shift is signed */
8044 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8045 addSign(result, MSB32, sign);
8048 else{ /* 1 <= shCount <= 7 */
8050 shiftRLong(left, LSB, result, sign);
8052 shiftRLong(result, LSB, result, sign);
8055 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8056 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8057 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8062 /*-----------------------------------------------------------------*/
8063 /* genRightShiftLiteral - right shifting by known count */
8064 /*-----------------------------------------------------------------*/
8065 static void genRightShiftLiteral (operand *left,
8071 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8075 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8076 freeAsmop(right,NULL,ic,TRUE);
8078 aopOp(left,ic,FALSE);
8079 aopOp(result,ic,FALSE);
8082 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8086 lsize = pic14_getDataSize(left);
8087 res_size = pic14_getDataSize(result);
8088 /* test the LEFT size !!! */
8090 /* I suppose that the left size >= result size */
8093 movLeft2Result(left, res_size, result, res_size);
8096 else if(shCount >= (lsize * 8)){
8099 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8101 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8102 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8107 emitpcode(POC_MOVLW, popGetLit(0));
8108 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8109 emitpcode(POC_MOVLW, popGetLit(0xff));
8111 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8116 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8123 genrshOne (result,left,shCount,sign);
8127 genrshTwo (result,left,shCount,sign);
8131 genrshFour (result,left,shCount,sign);
8139 freeAsmop(left,NULL,ic,TRUE);
8140 freeAsmop(result,NULL,ic,TRUE);
8145 /*-----------------------------------------------------------------*/
8146 /* genSignedRightShift - right shift of signed number */
8147 /*-----------------------------------------------------------------*/
8148 static void genSignedRightShift (iCode *ic)
8150 operand *right, *left, *result;
8153 symbol *tlbl, *tlbl1 ;
8156 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8158 /* we do it the hard way put the shift count in b
8159 and loop thru preserving the sign */
8161 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8163 right = IC_RIGHT(ic);
8165 result = IC_RESULT(ic);
8167 aopOp(right,ic,FALSE);
8168 aopOp(left,ic,FALSE);
8169 aopOp(result,ic,FALSE);
8172 if ( AOP_TYPE(right) == AOP_LIT) {
8173 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8174 //genRightShiftLiteral (left,right,result,ic,1);
8177 /* shift count is unknown then we have to form
8178 a loop get the loop count in B : Note: we take
8179 only the lower order byte since shifting
8180 more that 32 bits make no sense anyway, ( the
8181 largest size of an object can be only 32 bits ) */
8183 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8184 //pic14_emitcode("inc","b");
8185 //freeAsmop (right,NULL,ic,TRUE);
8186 //aopOp(left,ic,FALSE);
8187 //aopOp(result,ic,FALSE);
8189 /* now move the left to the result if they are not the
8191 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8192 AOP_SIZE(result) > 1) {
8194 size = AOP_SIZE(result);
8198 l = aopGet(AOP(left),offset,FALSE,TRUE);
8199 if (*l == '@' && IS_AOP_PREG(result)) {
8200 pic14_emitcode("mov","a,%s",l);
8201 aopPut(AOP(result),"a",offset);
8203 aopPut(AOP(result),l,offset);
8205 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8206 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8212 /* mov the highest order bit to OVR */
8213 tlbl = newiTempLabel(NULL);
8214 tlbl1= newiTempLabel(NULL);
8216 size = AOP_SIZE(result);
8219 pctemp = popGetTempReg(); /* grab a temporary working register. */
8221 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8223 /* offset should be 0, 1 or 3 */
8224 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8226 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8228 emitpcode(POC_MOVWF, pctemp);
8231 emitpLabel(tlbl->key);
8233 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8234 emitpcode(POC_RRF, popGet(AOP(result),offset));
8237 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8240 emitpcode(POC_DECFSZ, pctemp);
8241 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8242 emitpLabel(tlbl1->key);
8244 popReleaseTempReg(pctemp);
8246 size = AOP_SIZE(result);
8248 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8249 pic14_emitcode("rlc","a");
8250 pic14_emitcode("mov","ov,c");
8251 /* if it is only one byte then */
8253 l = aopGet(AOP(left),0,FALSE,FALSE);
8255 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8256 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8257 pic14_emitcode("mov","c,ov");
8258 pic14_emitcode("rrc","a");
8259 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8260 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8261 aopPut(AOP(result),"a",0);
8265 reAdjustPreg(AOP(result));
8266 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8267 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8268 pic14_emitcode("mov","c,ov");
8270 l = aopGet(AOP(result),offset,FALSE,FALSE);
8272 pic14_emitcode("rrc","a");
8273 aopPut(AOP(result),"a",offset--);
8275 reAdjustPreg(AOP(result));
8276 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8277 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8282 freeAsmop(left,NULL,ic,TRUE);
8283 freeAsmop(result,NULL,ic,TRUE);
8284 freeAsmop(right,NULL,ic,TRUE);
8288 /*-----------------------------------------------------------------*/
8289 /* loadSignToC - load the operand's sign bit into CARRY */
8290 /*-----------------------------------------------------------------*/
8292 static void loadSignToC (operand *op)
8295 assert (op && AOP(op) && AOP_SIZE(op));
8298 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8302 /*-----------------------------------------------------------------*/
8303 /* genRightShift - generate code for right shifting */
8304 /*-----------------------------------------------------------------*/
8305 static void genGenericShift (iCode *ic, int shiftRight)
8307 operand *right, *left, *result;
8310 symbol *tlbl, *tlbl1, *inverselbl;
8313 /* if signed then we do it the hard way preserve the
8314 sign bit moving it inwards */
8315 retype = getSpec(operandType(IC_RESULT(ic)));
8316 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8318 /* signed & unsigned types are treated the same : i.e. the
8319 signed is NOT propagated inwards : quoting from the
8320 ANSI - standard : "for E1 >> E2, is equivalent to division
8321 by 2**E2 if unsigned or if it has a non-negative value,
8322 otherwise the result is implementation defined ", MY definition
8323 is that the sign does not get propagated */
8325 right = IC_RIGHT(ic);
8327 result = IC_RESULT(ic);
8329 aopOp(right,ic,FALSE);
8330 aopOp(left,ic,FALSE);
8331 aopOp(result,ic,FALSE);
8333 /* if the shift count is known then do it
8334 as efficiently as possible */
8335 if (AOP_TYPE(right) == AOP_LIT) {
8336 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8340 shiftRight = !shiftRight;
8344 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8346 shiftLeft_Left2ResultLit (left, result, lit);
8347 //genRightShiftLiteral (left,right,result,ic, 0);
8351 /* shift count is unknown then we have to form
8352 a loop get the loop count in B : Note: we take
8353 only the lower order byte since shifting
8354 more that 32 bits make no sense anyway, ( the
8355 largest size of an object can be only 32 bits ) */
8357 /* we must not overwrite the shift counter */
8358 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8360 /* now move the left to the result if they are not the
8362 if (!pic14_sameRegs(AOP(left),AOP(result)))
8364 size = min(AOP_SIZE(result), AOP_SIZE(left));
8366 mov2w(AOP(left), size);
8367 movwf(AOP(result), size);
8369 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8372 tlbl = newiTempLabel(NULL);
8373 tlbl1= newiTempLabel(NULL);
8375 size = AOP_SIZE(result);
8377 mov2w(AOP(right),0);
8378 if (!SPEC_USIGN(operandType(right)))
8380 inverselbl = newiTempLabel(NULL);
8381 /* signed shift count -- invert shift direction for c<0 */
8382 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8383 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8385 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8386 /* check for `a = b >> c' with `-c == 0' */
8388 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8389 emitpLabel(tlbl->key);
8390 /* propagate the sign bit inwards for SIGNED result */
8391 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8392 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8393 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8395 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8397 if (!SPEC_USIGN(operandType(right)))
8399 symbol *inv_loop = newiTempLabel(NULL);
8401 shiftRight = !shiftRight; /* invert shift direction */
8403 /* we came here from the code above -- we are done */
8404 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8406 /* emit code for shifting N<0 steps, count is already in W */
8407 emitpLabel(inverselbl->key);
8408 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8409 emitpLabel(inv_loop->key);
8410 /* propagate the sign bit inwards for SIGNED result */
8411 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8412 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8413 emitpcode(POC_ADDLW, popGetLit(1));
8415 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8418 emitpLabel(tlbl1->key);
8420 freeAsmop(left,NULL,ic,TRUE);
8421 freeAsmop (right,NULL,ic,TRUE);
8422 freeAsmop(result,NULL,ic,TRUE);
8425 static void genRightShift (iCode *ic)
8427 genGenericShift(ic, 1);
8430 static void genLeftShift (iCode *ic)
8432 genGenericShift(ic, 0);
8435 /*-----------------------------------------------------------------*/
8436 /* SetIrp - Set IRP bit */
8437 /*-----------------------------------------------------------------*/
8438 void SetIrp(operand *result) {
8440 if (AOP_TYPE(result) == AOP_LIT) {
8441 unsigned lit = (unsigned)operandLitValue(result);
8447 if (PCOP(AOP(result))->type == PO_LITERAL) {
8448 int addrs = PCOL(AOP(result))->lit;
8454 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8455 if(AOP_SIZE(result) > 1) {
8456 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8464 setup_fsr (operand *ptr)
8467 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8469 /* also setup-up IRP */
8473 /*-----------------------------------------------------------------*/
8474 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8475 /* arbitrary pointer (__code, __data, generic) */
8476 /*-----------------------------------------------------------------*/
8478 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8485 if (!alreadyAddressed) setup_fsr (src);
8486 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8490 assert( AOP_SIZE(src) == 2 );
8492 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8494 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8495 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8496 call_libraryfunc ("__gptrget1");
8500 assert( AOP_SIZE(src) == 3 );
8502 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8504 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8506 call_libraryfunc ("__gptrget1");
8510 assert( !"unhandled pointer type" );
8515 /*-----------------------------------------------------------------*/
8516 /* emitPtrByteSet - emits code to set a byte from src through a */
8517 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8518 /*-----------------------------------------------------------------*/
8520 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8527 if (!alreadyAddressed) setup_fsr (dst);
8528 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8532 assert( !"trying to assign to __code pointer" );
8536 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8538 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8540 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8542 call_libraryfunc ("__gptrput1");
8546 assert( !"unhandled pointer type" );
8551 /*-----------------------------------------------------------------*/
8552 /* genUnpackBits - generates code for unpacking bits */
8553 /*-----------------------------------------------------------------*/
8554 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8556 int rsize; /* result size */
8557 sym_link *etype; /* bitfield type information */
8558 int blen; /* bitfield length */
8559 int bstr; /* bitfield starting bit within byte */
8562 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8563 etype = getSpec(operandType(result));
8564 rsize = getSize (operandType (result));
8565 blen = SPEC_BLEN (etype);
8566 bstr = SPEC_BSTR (etype);
8568 /* single bit field case */
8570 if (ifx) { /* that is for an if statement */
8573 resolveIfx(&rIfx,ifx);
8574 if (ptype == -1) /* direct */
8575 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8577 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8578 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8579 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8583 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8584 for (i=0; i < AOP_SIZE(result); i++)
8585 emitpcode (POC_CLRF, popGet (AOP(result), i));
8590 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8591 /* adjust result below */
8598 emitPtrByteGet (left, ptype, FALSE);
8599 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8601 /* adjust result below */
8605 assert( !"unhandled pointer type" );
8608 /* move sign-/zero extended bit to result */
8609 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8610 emitpcode (POC_INCF, popGet (AOP(result), 0));
8612 emitpcode (POC_DECF, popGet (AOP(result), 0));
8614 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8618 else if (blen <= 8 && ((blen + bstr) <= 8))
8623 for (i=0; i < AOP_SIZE(result); i++)
8624 emitpcode (POC_CLRF, popGet (AOP(result), i));
8629 mov2w(AOP(left), 0);
8636 emitPtrByteGet (left, ptype, FALSE);
8640 assert( !"unhandled pointer type" );
8644 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8645 movwf(AOP(result), 0);
8646 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8648 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8650 /* signed bitfield */
8651 assert (bstr + blen > 0);
8652 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8653 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8654 emitpcode(POC_IORWF, popGet(AOP(result),0));
8656 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8660 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8664 /*-----------------------------------------------------------------*/
8665 /* genDataPointerGet - generates code when ptr offset is known */
8666 /*-----------------------------------------------------------------*/
8667 static void genDataPointerGet (operand *left,
8671 int size , offset = 0;
8674 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8677 /* optimization - most of the time, left and result are the same
8678 * address, but different types. for the pic code, we could omit
8681 aopOp(result,ic,TRUE);
8683 if (pic14_sameRegs (AOP(left), AOP(result)))
8686 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8688 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8690 size = AOP_SIZE(result);
8691 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8695 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8696 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8700 freeAsmop(left,NULL,ic,TRUE);
8701 freeAsmop(result,NULL,ic,TRUE);
8705 /*-----------------------------------------------------------------*/
8706 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8707 /*-----------------------------------------------------------------*/
8708 static void genNearPointerGet (operand *left,
8713 sym_link *ltype = operandType(left);
8714 sym_link *rtype = operandType(result);
8715 sym_link *retype= getSpec(rtype); /* bitfield type information */
8719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8722 aopOp(left,ic,FALSE);
8724 /* if left is rematerialisable and
8725 result is not bit variable type and
8726 the left is pointer to data space i.e
8727 lower 128 bytes of space */
8728 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8729 !IS_BITVAR(retype) &&
8730 PIC_IS_DATA_PTR(ltype)) {
8731 genDataPointerGet (left,result,ic);
8735 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8736 aopOp (result,ic,FALSE);
8738 /* Check if can access directly instead of via a pointer */
8739 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8740 && AOP_SIZE(result) == 1)
8745 if (IS_BITFIELD(getSpec(operandType(result))))
8747 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8751 /* If the pointer value is not in a the FSR then need to put it in */
8752 /* Must set/reset IRP bit for use with FSR. */
8757 /* if bitfield then unpack the bits */
8759 /* we have can just get the values */
8760 int size = AOP_SIZE(result);
8763 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8767 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8769 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8770 if (AOP_TYPE(result) == AOP_LIT) {
8771 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8773 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8775 if (size && !direct)
8776 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8781 /* now some housekeeping stuff */
8783 /* we had to allocate for this iCode */
8784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8785 freeAsmop(NULL,aop,ic,TRUE);
8787 /* we did not allocate which means left
8788 already in a pointer register, then
8789 if size > 0 && this could be used again
8790 we have to point it back to where it
8792 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8793 if (AOP_SIZE(result) > 1 &&
8794 !OP_SYMBOL(left)->remat &&
8795 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8797 int size = AOP_SIZE(result) - 1;
8799 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8805 freeAsmop(left,NULL,ic,TRUE);
8806 freeAsmop(result,NULL,ic,TRUE);
8811 /*-----------------------------------------------------------------*/
8812 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8813 /*-----------------------------------------------------------------*/
8814 static void genPagedPointerGet (operand *left,
8821 sym_link *rtype, *retype;
8824 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8826 rtype = operandType(result);
8827 retype= getSpec(rtype);
8829 aopOp(left,ic,FALSE);
8831 /* if the value is already in a pointer register
8832 then don't need anything more */
8833 if (!AOP_INPREG(AOP(left))) {
8834 /* otherwise get a free pointer register */
8836 preg = getFreePtr(ic,&aop,FALSE);
8837 pic14_emitcode("mov","%s,%s",
8839 aopGet(AOP(left),0,FALSE,TRUE));
8840 rname = preg->name ;
8842 rname = aopGet(AOP(left),0,FALSE,FALSE);
8844 freeAsmop(left,NULL,ic,TRUE);
8845 aopOp (result,ic,FALSE);
8847 /* if bitfield then unpack the bits */
8848 if (IS_BITFIELD(retype))
8849 genUnpackBits (result,left,rname,PPOINTER,0);
8851 /* we have can just get the values */
8852 int size = AOP_SIZE(result);
8857 pic14_emitcode("movx","a,@%s",rname);
8858 aopPut(AOP(result),"a",offset);
8863 pic14_emitcode("inc","%s",rname);
8867 /* now some housekeeping stuff */
8869 /* we had to allocate for this iCode */
8870 freeAsmop(NULL,aop,ic,TRUE);
8872 /* we did not allocate which means left
8873 already in a pointer register, then
8874 if size > 0 && this could be used again
8875 we have to point it back to where it
8877 if (AOP_SIZE(result) > 1 &&
8878 !OP_SYMBOL(left)->remat &&
8879 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8881 int size = AOP_SIZE(result) - 1;
8883 pic14_emitcode("dec","%s",rname);
8888 freeAsmop(result,NULL,ic,TRUE);
8893 /*-----------------------------------------------------------------*/
8894 /* genFarPointerGet - gget value from far space */
8895 /*-----------------------------------------------------------------*/
8896 static void genFarPointerGet (operand *left,
8897 operand *result, iCode *ic)
8900 sym_link *retype = getSpec(operandType(result));
8903 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8905 aopOp(left,ic,FALSE);
8907 /* if the operand is already in dptr
8908 then we do nothing else we move the value to dptr */
8909 if (AOP_TYPE(left) != AOP_STR) {
8910 /* if this is remateriazable */
8911 if (AOP_TYPE(left) == AOP_IMMD)
8912 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8913 else { /* we need to get it byte by byte */
8914 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8915 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8916 if (options.model == MODEL_FLAT24)
8918 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8922 /* so dptr know contains the address */
8923 freeAsmop(left,NULL,ic,TRUE);
8924 aopOp(result,ic,FALSE);
8926 /* if bit then unpack */
8927 if (IS_BITFIELD(retype))
8928 genUnpackBits(result,left,"dptr",FPOINTER,0);
8930 size = AOP_SIZE(result);
8934 pic14_emitcode("movx","a,@dptr");
8935 aopPut(AOP(result),"a",offset++);
8937 pic14_emitcode("inc","dptr");
8941 freeAsmop(result,NULL,ic,TRUE);
8946 /*-----------------------------------------------------------------*/
8947 /* genCodePointerGet - get value from code space */
8948 /*-----------------------------------------------------------------*/
8949 static void genCodePointerGet (operand *left,
8950 operand *result, iCode *ic)
8953 sym_link *retype = getSpec(operandType(result));
8955 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8957 aopOp(left,ic,FALSE);
8959 /* if the operand is already in dptr
8960 then we do nothing else we move the value to dptr */
8961 if (AOP_TYPE(left) != AOP_STR) {
8962 /* if this is remateriazable */
8963 if (AOP_TYPE(left) == AOP_IMMD)
8964 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8965 else { /* we need to get it byte by byte */
8966 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8967 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8968 if (options.model == MODEL_FLAT24)
8970 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8974 /* so dptr know contains the address */
8975 freeAsmop(left,NULL,ic,TRUE);
8976 aopOp(result,ic,FALSE);
8978 /* if bit then unpack */
8979 if (IS_BITFIELD(retype))
8980 genUnpackBits(result,left,"dptr",CPOINTER,0);
8982 size = AOP_SIZE(result);
8986 pic14_emitcode("clr","a");
8987 pic14_emitcode("movc","a,@a+dptr");
8988 aopPut(AOP(result),"a",offset++);
8990 pic14_emitcode("inc","dptr");
8994 freeAsmop(result,NULL,ic,TRUE);
8997 /*-----------------------------------------------------------------*/
8998 /* genGenPointerGet - gget value from generic pointer space */
8999 /*-----------------------------------------------------------------*/
9000 static void genGenPointerGet (operand *left,
9001 operand *result, iCode *ic)
9004 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9005 aopOp(left,ic,FALSE);
9006 aopOp(result,ic,FALSE);
9009 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9011 if (IS_BITFIELD(getSpec(operandType(result))))
9013 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9018 /* emit call to __gptrget */
9019 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9020 int size = AOP_SIZE(result);
9023 assert (size > 0 && size <= 4);
9025 /* pass arguments */
9026 assert (AOP_SIZE(left) == 3);
9027 mov2w(AOP(left), 0);
9028 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9029 mov2w(AOP(left), 1);
9030 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9031 mov2w(AOP(left), 2);
9032 call_libraryfunc (func[size]);
9035 movwf (AOP(result), --size);
9037 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9038 movwf (AOP(result), size);
9042 freeAsmop(left,NULL,ic,TRUE);
9043 freeAsmop(result,NULL,ic,TRUE);
9047 /*-----------------------------------------------------------------*/
9048 /* genConstPointerGet - get value from const generic pointer space */
9049 /*-----------------------------------------------------------------*/
9050 static void genConstPointerGet (operand *left,
9051 operand *result, iCode *ic)
9053 //sym_link *retype = getSpec(operandType(result));
9055 symbol *albl, *blbl;//, *clbl;
9062 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9063 aopOp(left,ic,FALSE);
9064 aopOp(result,ic,FALSE);
9066 size = AOP_SIZE(result);
9068 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9070 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9072 lit = op_isLitLike (left);
9073 poc = lit ? POC_MOVLW : POC_MOVFW;
9075 if (IS_BITFIELD(getSpec(operandType(result))))
9077 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9082 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9083 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9084 assert (size > 0 && size <= 4);
9087 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9089 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9090 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9091 call_libraryfunc (func[size]);
9093 movwf(AOP(result),size-1);
9094 for (i = 1; i < size; i++)
9096 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9097 movwf(AOP(result),size - 1 - i);
9102 freeAsmop(left,NULL,ic,TRUE);
9103 freeAsmop(result,NULL,ic,TRUE);
9106 /*-----------------------------------------------------------------*/
9107 /* genPointerGet - generate code for pointer get */
9108 /*-----------------------------------------------------------------*/
9109 static void genPointerGet (iCode *ic)
9111 operand *left, *result ;
9112 sym_link *type, *etype;
9116 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9119 result = IC_RESULT(ic) ;
9121 /* depending on the type of pointer we need to
9122 move it to the correct pointer register */
9123 type = operandType(left);
9124 etype = getSpec(type);
9126 if (IS_PTR_CONST(type))
9127 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9129 /* if left is of type of pointer then it is simple */
9130 if (IS_PTR(type) && !IS_FUNC(type->next))
9131 p_type = DCL_TYPE(type);
9133 /* we have to go by the storage class */
9134 p_type = PTR_TYPE(SPEC_OCLS(etype));
9136 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9138 if (SPEC_OCLS(etype)->codesp ) {
9139 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9140 //p_type = CPOINTER ;
9143 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9144 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9145 /*p_type = FPOINTER ;*/
9147 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9148 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9149 /* p_type = PPOINTER; */
9151 if (SPEC_OCLS(etype) == idata )
9152 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9153 /* p_type = IPOINTER; */
9155 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9156 /* p_type = POINTER ; */
9159 /* now that we have the pointer type we assign
9160 the pointer values */
9166 genNearPointerGet (left,result,ic);
9170 genPagedPointerGet(left,result,ic);
9174 genFarPointerGet (left,result,ic);
9178 genConstPointerGet (left,result,ic);
9182 genGenPointerGet (left,result,ic);
9185 assert ( !"unhandled pointer type" );
9191 /*-----------------------------------------------------------------*/
9192 /* genPackBits - generates code for packed bit storage */
9193 /*-----------------------------------------------------------------*/
9194 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9196 int blen; /* bitfield length */
9197 int bstr; /* bitfield starting bit within byte */
9198 int litval; /* source literal value (if AOP_LIT) */
9199 unsigned char mask; /* bitmask within current byte */
9202 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9204 blen = SPEC_BLEN (etype);
9205 bstr = SPEC_BSTR (etype);
9207 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9208 if ((blen <= 8) && ((bstr + blen) <= 8))
9210 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9211 (unsigned char) (0xFF >> (8 - bstr)));
9213 if (AOP_TYPE (right) == AOP_LIT)
9215 /* Case with a bitfield length <8 and literal source */
9216 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9223 if (AOP(result)->type == AOP_PCODE)
9224 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9226 pcop = popGet(AOP(result),0);
9227 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9233 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9237 assert( !"trying to assign to bitfield via pointer to __code space" );
9241 emitPtrByteGet(result, p_type, FALSE);
9243 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9245 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9247 emitPtrByteSet(result, p_type, TRUE);
9251 assert( !"unhandled pointer type" );
9253 } // switch (p_type)
9256 litval = lit << bstr;
9257 litval &= (~mask) & 0x00ff;
9262 mov2w (AOP(result), 0);
9263 if ((litval|mask) != 0x00ff)
9264 emitpcode(POC_ANDLW, popGetLit (mask));
9266 emitpcode(POC_IORLW, popGetLit (litval));
9267 movwf (AOP(result), 0);
9273 emitPtrByteGet(result, p_type, FALSE);
9274 if ((litval|mask) != 0x00ff)
9275 emitpcode(POC_ANDLW, popGetLit (mask));
9277 emitpcode(POC_IORLW, popGetLit (litval));
9278 emitPtrByteSet(result, p_type, TRUE);
9282 assert( !"trying to assign to bitfield via pointer to __code space" );
9286 assert( !"unhandled pointer type" );
9293 /* right is no literal */
9298 /* Note more efficient code, of pre clearing bit then only setting it if required,
9299 * can only be done if it is known that the result is not a SFR */
9300 emitpcode(POC_RRFW,popGet(AOP(right),0));
9302 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9304 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9310 emitPtrByteGet (result, p_type, FALSE);
9311 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9312 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9313 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9314 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9315 emitPtrByteSet (result, p_type, TRUE);
9319 assert( !"trying to assign to bitfield via pointer to __code space" );
9323 assert( !"unhandled pointer type" );
9328 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9329 pCodeOp *temp = popGetTempReg ();
9331 mov2w (AOP(right), 0);
9333 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9335 emitpcode(POC_MOVWF, temp);
9337 AccLsh (temp, bstr);
9343 mov2w (AOP(result), 0);
9344 emitpcode(POC_ANDLW, popGetLit (mask));
9345 emitpcode(POC_IORFW, temp);
9346 movwf (AOP(result), 0);
9352 emitPtrByteGet (result, p_type, FALSE);
9353 emitpcode(POC_ANDLW, popGetLit (mask));
9354 emitpcode(POC_IORFW, temp);
9355 emitPtrByteSet (result, p_type, TRUE);
9359 assert( !"trying to assign to bitfield via pointer to __code space" );
9363 assert( !"unhandled pointer type" );
9367 popReleaseTempReg (temp);
9369 } // if (AOP(right)->type != AOP_LIT)
9371 } // if (blen <= 8 && ((blen + bstr) <= 8))
9373 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9376 /*-----------------------------------------------------------------*/
9377 /* genDataPointerSet - remat pointer to data space */
9378 /*-----------------------------------------------------------------*/
9379 static void genDataPointerSet(operand *right,
9383 int size, offset = 0 ;
9387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9388 aopOp(right,ic,FALSE);
9389 aopOp(result,ic,FALSE);
9391 assert (IS_SYMOP(result));
9392 assert (IS_PTR(OP_SYM_TYPE(result)));
9394 if (AOP_TYPE(right) == AOP_LIT)
9397 size = AOP_SIZE(right);
9398 ressize = getSize(OP_SYM_ETYPE(result));
9399 if (size > ressize) size = ressize;
9400 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9402 //assert( !"what's going on here?" );
9405 if ( AOP_TYPE(result) == AOP_PCODE) {
9406 fprintf(stderr,"genDataPointerSet %s, %d\n",
9407 AOP(result)->aopu.pcop->name,
9408 PCOI(AOP(result)->aopu.pcop)->offset);
9412 // tsd, was l+1 - the underline `_' prefix was being stripped
9414 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9416 if (AOP_TYPE(right) == AOP_LIT) {
9417 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9418 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9420 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9421 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9423 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9426 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9427 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9428 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9434 freeAsmop(right,NULL,ic,TRUE);
9435 freeAsmop(result,NULL,ic,TRUE);
9438 /*-----------------------------------------------------------------*/
9439 /* genNearPointerSet - pic14_emitcode for near pointer put */
9440 /*-----------------------------------------------------------------*/
9441 static void genNearPointerSet (operand *right,
9446 sym_link *ptype = operandType(result);
9447 sym_link *retype = getSpec(operandType(right));
9448 sym_link *letype = getSpec(ptype);
9453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9454 aopOp(result,ic,FALSE);
9457 /* if the result is rematerializable &
9458 in data space & not a bit variable */
9459 //if (AOP_TYPE(result) == AOP_IMMD &&
9460 if (AOP_TYPE(result) == AOP_PCODE &&
9461 PIC_IS_DATA_PTR(ptype) &&
9462 !IS_BITVAR (retype) &&
9463 !IS_BITVAR (letype)) {
9464 genDataPointerSet (right,result,ic);
9465 freeAsmop(result,NULL,ic,TRUE);
9470 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9471 aopOp(right,ic,FALSE);
9472 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9474 /* Check if can access directly instead of via a pointer */
9475 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9479 if (IS_BITFIELD (letype))
9481 genPackBits (letype, result, right, direct?-1:POINTER);
9485 /* If the pointer value is not in a the FSR then need to put it in */
9486 /* Must set/reset IRP bit for use with FSR. */
9487 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9492 /* we have can just get the values */
9493 int size = AOP_SIZE(right);
9496 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9500 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9502 if (AOP_TYPE(right) == AOP_LIT) {
9503 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9505 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9508 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9510 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9512 if (size && !direct)
9513 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9518 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9519 /* now some housekeeping stuff */
9521 /* we had to allocate for this iCode */
9522 freeAsmop(NULL,aop,ic,TRUE);
9524 /* we did not allocate which means left
9525 already in a pointer register, then
9526 if size > 0 && this could be used again
9527 we have to point it back to where it
9529 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9530 if (AOP_SIZE(right) > 1 &&
9531 !OP_SYMBOL(result)->remat &&
9532 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9534 int size = AOP_SIZE(right) - 1;
9536 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9540 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9543 freeAsmop(right,NULL,ic,TRUE);
9544 freeAsmop(result,NULL,ic,TRUE);
9548 /*-----------------------------------------------------------------*/
9549 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9550 /*-----------------------------------------------------------------*/
9551 static void genPagedPointerSet (operand *right,
9561 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9563 retype= getSpec(operandType(right));
9565 aopOp(result,ic,FALSE);
9567 /* if the value is already in a pointer register
9568 then don't need anything more */
9569 if (!AOP_INPREG(AOP(result))) {
9570 /* otherwise get a free pointer register */
9572 preg = getFreePtr(ic,&aop,FALSE);
9573 pic14_emitcode("mov","%s,%s",
9575 aopGet(AOP(result),0,FALSE,TRUE));
9576 rname = preg->name ;
9578 rname = aopGet(AOP(result),0,FALSE,FALSE);
9580 freeAsmop(result,NULL,ic,TRUE);
9581 aopOp (right,ic,FALSE);
9583 /* if bitfield then unpack the bits */
9584 if (IS_BITFIELD(retype))
9585 genPackBits (retype,result,right,rname,PPOINTER);
9587 /* we have can just get the values */
9588 int size = AOP_SIZE(right);
9592 l = aopGet(AOP(right),offset,FALSE,TRUE);
9595 pic14_emitcode("movx","@%s,a",rname);
9598 pic14_emitcode("inc","%s",rname);
9604 /* now some housekeeping stuff */
9606 /* we had to allocate for this iCode */
9607 freeAsmop(NULL,aop,ic,TRUE);
9609 /* we did not allocate which means left
9610 already in a pointer register, then
9611 if size > 0 && this could be used again
9612 we have to point it back to where it
9614 if (AOP_SIZE(right) > 1 &&
9615 !OP_SYMBOL(result)->remat &&
9616 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9618 int size = AOP_SIZE(right) - 1;
9620 pic14_emitcode("dec","%s",rname);
9625 freeAsmop(right,NULL,ic,TRUE);
9630 /*-----------------------------------------------------------------*/
9631 /* genFarPointerSet - set value from far space */
9632 /*-----------------------------------------------------------------*/
9633 static void genFarPointerSet (operand *right,
9634 operand *result, iCode *ic)
9637 sym_link *retype = getSpec(operandType(right));
9640 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9641 aopOp(result,ic,FALSE);
9643 /* if the operand is already in dptr
9644 then we do nothing else we move the value to dptr */
9645 if (AOP_TYPE(result) != AOP_STR) {
9646 /* if this is remateriazable */
9647 if (AOP_TYPE(result) == AOP_IMMD)
9648 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9649 else { /* we need to get it byte by byte */
9650 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9651 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9652 if (options.model == MODEL_FLAT24)
9654 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9658 /* so dptr know contains the address */
9659 freeAsmop(result,NULL,ic,TRUE);
9660 aopOp(right,ic,FALSE);
9662 /* if bit then unpack */
9663 if (IS_BITFIELD(retype))
9664 genPackBits(retype,result,right,"dptr",FPOINTER);
9666 size = AOP_SIZE(right);
9670 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9672 pic14_emitcode("movx","@dptr,a");
9674 pic14_emitcode("inc","dptr");
9678 freeAsmop(right,NULL,ic,TRUE);
9682 /*-----------------------------------------------------------------*/
9683 /* genGenPointerSet - set value from generic pointer space */
9684 /*-----------------------------------------------------------------*/
9685 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9687 sym_link *retype = getSpec(operandType(result));
9690 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9691 aopOp(right,ic,FALSE);
9692 aopOp(result,ic,FALSE);
9695 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9697 if (IS_BITFIELD(retype))
9699 genPackBits (retype, result, right, GPOINTER);
9704 /* emit call to __gptrput */
9705 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9706 int size = AOP_SIZE(right);
9709 assert (size == getSize(OP_SYM_ETYPE(result)));
9710 assert (size > 0 && size <= 4);
9712 /* pass arguments */
9713 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9719 mov2w_op (right, off);
9720 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9725 assert (AOP_SIZE(result) == 3);
9726 mov2w(AOP(result), 0);
9727 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9728 mov2w(AOP(result), 1);
9729 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9730 mov2w(AOP(result), 2);
9731 call_libraryfunc (func[size]);
9734 freeAsmop(right,NULL,ic,TRUE);
9735 freeAsmop(result,NULL,ic,TRUE);
9738 /*-----------------------------------------------------------------*/
9739 /* genPointerSet - stores the value into a pointer location */
9740 /*-----------------------------------------------------------------*/
9741 static void genPointerSet (iCode *ic)
9743 operand *right, *result ;
9744 sym_link *type, *etype;
9748 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9750 right = IC_RIGHT(ic);
9751 result = IC_RESULT(ic) ;
9753 /* depending on the type of pointer we need to
9754 move it to the correct pointer register */
9755 type = operandType(result);
9756 etype = getSpec(type);
9757 /* if left is of type of pointer then it is simple */
9758 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9759 p_type = DCL_TYPE(type);
9762 /* we have to go by the storage class */
9763 p_type = PTR_TYPE(SPEC_OCLS(etype));
9765 /* if (SPEC_OCLS(etype)->codesp ) { */
9766 /* p_type = CPOINTER ; */
9769 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9770 /* p_type = FPOINTER ; */
9772 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9773 /* p_type = PPOINTER ; */
9775 /* if (SPEC_OCLS(etype) == idata ) */
9776 /* p_type = IPOINTER ; */
9778 /* p_type = POINTER ; */
9781 /* now that we have the pointer type we assign
9782 the pointer values */
9788 genNearPointerSet (right,result,ic);
9792 genPagedPointerSet (right,result,ic);
9796 genFarPointerSet (right,result,ic);
9800 genGenPointerSet (right,result,ic);
9804 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9805 "genPointerSet: illegal pointer type");
9809 /*-----------------------------------------------------------------*/
9810 /* genIfx - generate code for Ifx statement */
9811 /*-----------------------------------------------------------------*/
9812 static void genIfx (iCode *ic, iCode *popIc)
9814 operand *cond = IC_COND(ic);
9818 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9820 aopOp(cond,ic,FALSE);
9822 /* get the value into acc */
9823 if (AOP_TYPE(cond) != AOP_CRY)
9824 pic14_toBoolean(cond);
9828 /* if there was something to be popped then do it */
9834 /* This assumes that CARRY is set iff cond is true */
9837 assert (!IC_FALSE(ic));
9838 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9840 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9842 assert (IC_FALSE(ic));
9843 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9845 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9849 static int hasWarned = 0;
9852 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9859 /* now Z is set iff !cond */
9862 assert (!IC_FALSE(ic));
9864 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9867 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9873 /* the result is now in the accumulator */
9874 freeAsmop(cond,NULL,ic,TRUE);
9877 /*-----------------------------------------------------------------*/
9878 /* genAddrOf - generates code for address of */
9879 /*-----------------------------------------------------------------*/
9880 static void genAddrOf (iCode *ic)
9882 operand *right, *result, *left;
9886 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9889 //aopOp(IC_RESULT(ic),ic,FALSE);
9891 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9892 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9893 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9895 DEBUGpic14_AopType(__LINE__,left,right,result);
9896 assert (IS_SYMOP (left));
9898 /* sanity check: generic pointers to code space are not yet supported,
9899 * pionters to codespace must not be assigned addresses of __data values. */
9901 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9902 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)));
9903 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)));
9904 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)));
9905 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)));
9908 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9909 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9910 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9911 OP_SYMBOL(left)->name);
9912 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9913 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9914 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9915 OP_SYMBOL(left)->name);
9918 size = AOP_SIZE(IC_RESULT(ic));
9919 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9921 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9926 /* fixing bug #863624, reported from (errolv) */
9927 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9928 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9931 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9932 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9937 if (IS_GENPTR(OP_SYM_TYPE(result)))
9939 /* provide correct tag */
9940 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9941 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9942 movwf (AOP(result), 2);
9945 freeAsmop(left,NULL,ic,FALSE);
9946 freeAsmop(result,NULL,ic,TRUE);
9951 /*-----------------------------------------------------------------*/
9952 /* genFarFarAssign - assignment when both are in far space */
9953 /*-----------------------------------------------------------------*/
9954 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9956 int size = AOP_SIZE(right);
9959 /* first push the right side on to the stack */
9961 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9963 pic14_emitcode ("push","acc");
9966 freeAsmop(right,NULL,ic,FALSE);
9967 /* now assign DPTR to result */
9968 aopOp(result,ic,FALSE);
9969 size = AOP_SIZE(result);
9971 pic14_emitcode ("pop","acc");
9972 aopPut(AOP(result),"a",--offset);
9974 freeAsmop(result,NULL,ic,FALSE);
9979 /*-----------------------------------------------------------------*/
9980 /* genAssign - generate code for assignment */
9981 /*-----------------------------------------------------------------*/
9982 static void genAssign (iCode *ic)
9984 operand *result, *right;
9985 int size, offset,know_W;
9986 unsigned long lit = 0L;
9988 result = IC_RESULT(ic);
9989 right = IC_RIGHT(ic) ;
9992 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9994 /* if they are the same */
9995 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9998 aopOp(right,ic,FALSE);
9999 aopOp(result,ic,TRUE);
10001 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10003 /* if they are the same registers */
10004 if (pic14_sameRegs(AOP(right),AOP(result)))
10007 /* special case: assign from __code */
10008 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10009 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10010 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10011 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10012 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10014 emitpComment ("genAssign from CODESPACE");
10015 genConstPointerGet (right, result, ic);
10019 /* just for symmetry reasons... */
10020 if (!IS_ITEMP(result)
10021 && IS_SYMOP (result)
10022 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10024 assert ( !"cannot write to CODESPACE" );
10027 /* if the result is a bit */
10028 if (AOP_TYPE(result) == AOP_CRY) {
10030 /* if the right size is a literal then
10031 we know what the value is */
10032 if (AOP_TYPE(right) == AOP_LIT) {
10034 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10035 popGet(AOP(result),0));
10037 if (((int) operandLitValue(right)))
10038 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10039 AOP(result)->aopu.aop_dir,
10040 AOP(result)->aopu.aop_dir);
10042 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10043 AOP(result)->aopu.aop_dir,
10044 AOP(result)->aopu.aop_dir);
10048 /* the right is also a bit variable */
10049 if (AOP_TYPE(right) == AOP_CRY) {
10050 emitpcode(POC_BCF, popGet(AOP(result),0));
10051 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10052 emitpcode(POC_BSF, popGet(AOP(result),0));
10054 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10055 AOP(result)->aopu.aop_dir,
10056 AOP(result)->aopu.aop_dir);
10057 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10058 AOP(right)->aopu.aop_dir,
10059 AOP(right)->aopu.aop_dir);
10060 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10061 AOP(result)->aopu.aop_dir,
10062 AOP(result)->aopu.aop_dir);
10066 /* we need to or */
10067 emitpcode(POC_BCF, popGet(AOP(result),0));
10068 pic14_toBoolean(right);
10070 emitpcode(POC_BSF, popGet(AOP(result),0));
10071 //aopPut(AOP(result),"a",0);
10075 /* bit variables done */
10077 size = AOP_SIZE(result);
10079 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10080 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10081 if(aopIdx(AOP(result),0) == 4) {
10082 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10083 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10084 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10087 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10093 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10094 if(AOP_TYPE(right) == AOP_LIT) {
10095 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10097 if(know_W != (int)(lit&0xff))
10098 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10100 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10102 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10104 } else if (AOP_TYPE(right) == AOP_CRY) {
10105 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10107 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10108 emitpcode(POC_INCF, popGet(AOP(result),0));
10111 mov2w_op (right, offset);
10112 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10120 freeAsmop (right,NULL,ic,FALSE);
10121 freeAsmop (result,NULL,ic,TRUE);
10124 /*-----------------------------------------------------------------*/
10125 /* genJumpTab - genrates code for jump table */
10126 /*-----------------------------------------------------------------*/
10127 static void genJumpTab (iCode *ic)
10133 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10135 aopOp(IC_JTCOND(ic),ic,FALSE);
10136 /* get the condition into accumulator */
10137 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10139 /* multiply by three */
10140 pic14_emitcode("add","a,acc");
10141 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10143 jtab = newiTempLabel(NULL);
10144 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10145 pic14_emitcode("jmp","@a+dptr");
10146 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10148 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10149 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10150 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10151 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10153 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10154 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10155 emitpLabel(jtab->key);
10157 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10159 /* now generate the jump labels */
10160 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10161 jtab = setNextItem(IC_JTLABELS(ic))) {
10162 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10163 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10169 /*-----------------------------------------------------------------*/
10170 /* genMixedOperation - gen code for operators between mixed types */
10171 /*-----------------------------------------------------------------*/
10173 TSD - Written for the PIC port - but this unfortunately is buggy.
10174 This routine is good in that it is able to efficiently promote
10175 types to different (larger) sizes. Unfortunately, the temporary
10176 variables that are optimized out by this routine are sometimes
10177 used in other places. So until I know how to really parse the
10178 iCode tree, I'm going to not be using this routine :(.
10180 static int genMixedOperation (iCode *ic)
10184 operand *result = IC_RESULT(ic);
10185 sym_link *ctype = operandType(IC_LEFT(ic));
10186 operand *right = IC_RIGHT(ic);
10192 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10194 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10200 nextright = IC_RIGHT(nextic);
10201 nextleft = IC_LEFT(nextic);
10202 nextresult = IC_RESULT(nextic);
10204 aopOp(right,ic,FALSE);
10205 aopOp(result,ic,FALSE);
10206 aopOp(nextright, nextic, FALSE);
10207 aopOp(nextleft, nextic, FALSE);
10208 aopOp(nextresult, nextic, FALSE);
10210 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10212 operand *t = right;
10216 pic14_emitcode(";remove right +","");
10218 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10220 operand *t = right;
10224 pic14_emitcode(";remove left +","");
10228 big = AOP_SIZE(nextleft);
10229 small = AOP_SIZE(nextright);
10231 switch(nextic->op) {
10234 pic14_emitcode(";optimize a +","");
10235 /* if unsigned or not an integral type */
10236 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10237 pic14_emitcode(";add a bit to something","");
10240 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10242 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10243 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10244 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10246 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10254 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10255 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10256 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10259 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10261 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10262 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10263 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10264 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10265 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10268 pic14_emitcode("rlf","known_zero,w");
10275 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10276 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10277 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10279 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10289 freeAsmop(right,NULL,ic,TRUE);
10290 freeAsmop(result,NULL,ic,TRUE);
10291 freeAsmop(nextright,NULL,ic,TRUE);
10292 freeAsmop(nextleft,NULL,ic,TRUE);
10294 nextic->generated = 1;
10301 /*-----------------------------------------------------------------*/
10302 /* genCast - gen code for casting */
10303 /*-----------------------------------------------------------------*/
10304 static void genCast (iCode *ic)
10306 operand *result = IC_RESULT(ic);
10307 sym_link *restype = operandType(result);
10308 sym_link *rtype = operandType(IC_RIGHT(ic));
10309 operand *right = IC_RIGHT(ic);
10313 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10314 /* if they are equivalent then do nothing */
10315 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10318 aopOp(right,ic,FALSE) ;
10319 aopOp(result,ic,FALSE);
10321 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10323 /* if the result is a bit */
10324 if (AOP_TYPE(result) == AOP_CRY) {
10325 assert(!"assigning to bit variables is not supported");
10328 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10330 size = AOP_SIZE(result);
10332 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10334 emitpcode(POC_CLRF, popGet(AOP(result),0));
10335 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10336 emitpcode(POC_INCF, popGet(AOP(result),0));
10339 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10344 if (IS_PTR(restype))
10346 operand *result = IC_RESULT(ic);
10347 //operand *left = IC_LEFT(ic);
10348 operand *right = IC_RIGHT(ic);
10351 /* copy common part */
10352 int max, size = AOP_SIZE(result);
10353 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10354 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10356 /* warn if we discard generic opinter tag */
10357 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10359 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10365 mov2w_op (right, size);
10366 movwf (AOP(result), size);
10369 /* upcast into generic pointer type? */
10370 if (IS_GENPTR(restype)
10371 && (size < AOP_SIZE(result))
10372 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10374 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10377 switch (DCL_TYPE(rtype))
10379 case POINTER: /* __data */
10380 case FPOINTER: /* __data */
10381 assert (AOP_SIZE(right) == 2);
10382 tag = GPTRTAG_DATA;
10385 case CPOINTER: /* __code */
10386 assert (AOP_SIZE(right) == 2);
10387 tag = GPTRTAG_CODE;
10390 case GPOINTER: /* unknown destination, __data or __code */
10391 /* assume __data space (address of immediate) */
10392 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10393 if (AOP(right)->code)
10394 tag = GPTRTAG_CODE;
10396 tag = GPTRTAG_DATA;
10400 assert (!"unhandled pointer type");
10403 /* convert other values into pointers to __data space */
10404 tag = GPTRTAG_DATA;
10407 assert (AOP_SIZE(result) == 3);
10409 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10411 emitpcode(POC_MOVLW, popGetLit(tag));
10412 movwf(AOP(result), 2);
10415 addSign(result, max, 0);
10420 /* if they are the same size : or less */
10421 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10423 /* if they are in the same place */
10424 if (pic14_sameRegs(AOP(right),AOP(result)))
10427 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10428 if (IS_PTR_CONST(rtype))
10429 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10430 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10431 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10433 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10434 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10435 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10436 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10437 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10438 if(AOP_SIZE(result) <2)
10439 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10443 /* if they in different places then copy */
10444 size = AOP_SIZE(result);
10447 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10448 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10450 //aopPut(AOP(result),
10451 // aopGet(AOP(right),offset,FALSE,FALSE),
10460 /* so we now know that the size of destination is greater
10461 than the size of the source.
10462 Now, if the next iCode is an operator then we might be
10463 able to optimize the operation without performing a cast.
10465 if(0 && genMixedOperation(ic)) {
10466 /* XXX: cannot optimize: must copy regs! */
10470 /* we move to result for the size of source */
10471 size = AOP_SIZE(right);
10474 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10475 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10479 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10482 freeAsmop(right,NULL,ic,TRUE);
10483 freeAsmop(result,NULL,ic,TRUE);
10487 /*-----------------------------------------------------------------*/
10488 /* genDjnz - generate decrement & jump if not zero instrucion */
10489 /*-----------------------------------------------------------------*/
10490 static int genDjnz (iCode *ic, iCode *ifx)
10492 symbol *lbl, *lbl1;
10494 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10499 /* if the if condition has a false label
10500 then we cannot save */
10504 /* if the minus is not of the form
10506 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10507 !IS_OP_LITERAL(IC_RIGHT(ic)))
10510 if (operandLitValue(IC_RIGHT(ic)) != 1)
10513 /* if the size of this greater than one then no
10515 if (getSize(operandType(IC_RESULT(ic))) > 1)
10518 /* otherwise we can save BIG */
10519 lbl = newiTempLabel(NULL);
10520 lbl1= newiTempLabel(NULL);
10522 aopOp(IC_RESULT(ic),ic,FALSE);
10524 if (IS_AOP_PREG(IC_RESULT(ic))) {
10525 pic14_emitcode("dec","%s",
10526 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10527 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10528 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10532 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10533 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10535 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10536 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10539 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10540 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10541 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10542 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10545 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10546 ifx->generated = 1;
10550 /*-----------------------------------------------------------------*/
10551 /* genReceive - generate code for a receive iCode */
10552 /*-----------------------------------------------------------------*/
10553 static void genReceive (iCode *ic)
10556 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10558 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10559 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10560 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10562 int size = getSize(operandType(IC_RESULT(ic)));
10563 int offset = fReturnSizePic - size;
10565 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10566 fReturn[fReturnSizePic - offset - 1] : "acc"));
10569 aopOp(IC_RESULT(ic),ic,FALSE);
10570 size = AOP_SIZE(IC_RESULT(ic));
10573 pic14_emitcode ("pop","acc");
10574 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10579 aopOp(IC_RESULT(ic),ic,FALSE);
10581 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10582 assignResultValue(IC_RESULT(ic));
10585 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10588 /*-----------------------------------------------------------------*/
10589 /* genDummyRead - generate code for dummy read of volatiles */
10590 /*-----------------------------------------------------------------*/
10592 genDummyRead (iCode * ic)
10595 pic14_emitcode ("; genDummyRead","");
10596 pic14_emitcode ("; not implemented","");
10601 /*-----------------------------------------------------------------*/
10602 /* genpic14Code - generate code for pic14 based controllers */
10603 /*-----------------------------------------------------------------*/
10605 * At this point, ralloc.c has gone through the iCode and attempted
10606 * to optimize in a way suitable for a PIC. Now we've got to generate
10607 * PIC instructions that correspond to the iCode.
10609 * Once the instructions are generated, we'll pass through both the
10610 * peep hole optimizer and the pCode optimizer.
10611 *-----------------------------------------------------------------*/
10613 void genpic14Code (iCode *lic)
10620 lineHead = lineCurr = NULL;
10622 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10625 /* if debug information required */
10626 if (options.debug && currFunc) {
10628 debugFile->writeFunction (currFunc, lic);
10633 for (ic = lic ; ic ; ic = ic->next ) {
10635 //DEBUGpic14_emitcode(";ic","");
10636 //fprintf (stderr, "in ic loop\n");
10637 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10638 //ic->lineno, printCLine(ic->filename, ic->lineno));
10640 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10642 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10643 cline = printCLine (ic->filename, ic->lineno);
10644 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10645 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10646 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10649 if (options.iCodeInAsm) {
10650 char *iLine = printILine(ic);
10651 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10654 /* if the result is marked as
10655 spilt and rematerializable or code for
10656 this has already been generated then
10658 if (resultRemat(ic) || ic->generated )
10661 /* depending on the operation */
10680 /* IPOP happens only when trying to restore a
10681 spilt live range, if there is an ifx statement
10682 following this pop then the if statement might
10683 be using some of the registers being popped which
10684 would destory the contents of the register so
10685 we need to check for this condition and handle it */
10687 ic->next->op == IFX &&
10688 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10689 genIfx (ic->next,ic);
10707 genEndFunction (ic);
10727 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10744 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10748 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10755 /* note these two are xlated by algebraic equivalence
10756 during parsing SDCC.y */
10757 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10758 "got '>=' or '<=' shouldn't have come here");
10762 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10774 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10778 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10782 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10806 genRightShift (ic);
10809 case GET_VALUE_AT_ADDRESS:
10814 if (POINTER_SET(ic))
10841 addSet(&_G.sendSet,ic);
10844 case DUMMY_READ_VOLATILE:
10849 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10856 /* now we are ready to call the
10857 peep hole optimizer */
10858 if (!options.nopeep) {
10859 peepHole (&lineHead);
10861 /* now do the actual printing */
10862 printLine (lineHead,codeOutBuf);
10865 DFPRINTF((stderr,"printing pBlock\n\n"));
10866 printpBlock(stdout,pb);
10872 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10873 * (meaning: representing its own address) or not (referencing its contents).
10874 * This can only be decided based on the operand's type. */
10876 aop_isLitLike (asmop *aop)
10879 if (aop->type == AOP_LIT) return 1;
10880 if (aop->type == AOP_IMMD) return 1;
10881 if ((aop->type == AOP_PCODE) &&
10882 ((aop->aopu.pcop->type == PO_LITERAL)))
10884 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10885 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10892 op_isLitLike (operand *op)
10895 if (aop_isLitLike (AOP(op))) return 1;
10896 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10897 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;