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;
73 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
74 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
75 const char *AopType(short type);
77 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
79 /* this is the down and dirty file with all kinds of
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
84 static char *zero = "#0x00";
85 static char *one = "#0x01";
86 static char *spname = "sp";
88 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
89 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
90 static char **fReturn = fReturnpic14;
92 //static char *accUse[] = {"a","b"};
94 //static short rbank = -1;
106 /* Resolved ifx structure. This structure stores information
107 about an iCode ifx that makes it easier to generate code.
109 typedef struct resolvedIfx {
110 symbol *lbl; /* pointer to a label */
111 int condition; /* true or false ifx */
112 int generated; /* set true when the code associated with the ifx
116 extern int pic14_ptrRegReq ;
117 extern int pic14_nRegs;
118 extern FILE *codeOutFile;
119 static void saverbank (int, iCode *,bool);
121 static lineNode *lineHead = NULL;
122 static lineNode *lineCurr = NULL;
125 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
126 0xE0, 0xC0, 0x80, 0x00};
127 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
133 /*-----------------------------------------------------------------*/
134 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
135 /* exponent of 2 is returned, otherwise -1 is */
137 /* note that this is similar to the function `powof2' in SDCCsymt */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
145 if( (num & (num-1)) == 0) {
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
161 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
163 ((result) ? AopType(AOP_TYPE(result)) : "-"),
164 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165 ((result) ? AOP_SIZE(result) : 0),
166 ((left) ? AopType(AOP_TYPE(left)) : "-"),
167 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
168 ((left) ? AOP_SIZE(left) : 0),
169 ((right) ? AopType(AOP_TYPE(right)) : "-"),
170 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171 ((right) ? AOP_SIZE(right) : 0));
175 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
178 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
180 ((result) ? AopType(AOP_TYPE(result)) : "-"),
181 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182 ((left) ? AopType(AOP_TYPE(left)) : "-"),
183 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
184 ((right) ? AopType(AOP_TYPE(right)) : "-"),
185 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
189 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
192 char lb[INITIAL_INLINEASM];
193 unsigned char *lbp = (unsigned char *)lb;
195 if(!debug_verbose && !options.debug)
202 sprintf(lb,"%s\t",inst);
204 sprintf(lb,"%s",inst);
205 vsprintf(lb+(strlen(lb)),fmt,ap);
209 while (isspace(*lbp)) lbp++;
212 lineCurr = (lineCurr ?
213 connectLine(lineCurr,newLineNode(lb)) :
214 (lineHead = newLineNode(lb)));
215 lineCurr->isInline = _G.inLine;
216 lineCurr->isDebug = _G.debugLine;
218 addpCode2pBlock(pb,newpCodeCharP(lb));
223 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
225 #if defined (HAVE_VSNPRINTF)
226 vsnprintf (buf, size, fmt, ap);
227 #elif defined (HAVE_VSPRINTF)
228 vsprintf (buf, size, fmt, ap);
229 if (strlen (buf) >= size)
231 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
233 #elif defined (HAVE_SNPRINTF)
234 snprintf (buf, size, "vs(n)printf required");
235 #elif defined (HAVE_SRINTF)
236 sprintf (buf, "vs(n)printf required");
237 if (strlen (buf) >= size)
239 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
242 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
246 void emitpComment (const char *fmt, ...)
253 Safe_vsnprintf (buffer, 4096, fmt, va);
254 //fprintf (stderr, "%s\n" ,buffer);
255 addpCode2pBlock (pb, newpCodeCharP (buffer));
258 Safe_vsnprintf (buffer, 4096, fmt, va);
259 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
265 void emitpLabel(int key)
267 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
270 /* gen.h defines a macro emitpcode that should be used to call emitpcode
271 * as this allows for easy debugging (ever asked the question: where was
272 * this instruction geenrated? Here is the answer... */
273 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
276 addpCode2pBlock(pb,newpCode(poc,pcop));
278 static int has_warned = 0;
280 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
283 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
288 void emitpcodeNULLop(PIC_OPCODE poc)
291 addpCode2pBlock(pb,newpCode(poc,NULL));
296 /*-----------------------------------------------------------------*/
297 /* pic14_emitcode - writes the code into a file : for now it is simple */
298 /*-----------------------------------------------------------------*/
299 void pic14_emitcode (char *inst,char *fmt, ...)
302 char lb[INITIAL_INLINEASM];
303 unsigned char *lbp = (unsigned char *)lb;
309 sprintf(lb,"%s\t",inst);
311 sprintf(lb,"%s",inst);
312 vsprintf(lb+(strlen(lb)),fmt,ap);
316 while (isspace(*lbp)) lbp++;
319 lineCurr = (lineCurr ?
320 connectLine(lineCurr,newLineNode(lb)) :
321 (lineHead = newLineNode(lb)));
322 lineCurr->isInline = _G.inLine;
323 lineCurr->isDebug = _G.debugLine;
326 addpCode2pBlock(pb,newpCodeCharP(lb));
331 /*-----------------------------------------------------------------*/
332 /* pic14_emitDebuggerSymbol - associate the current code location */
333 /* with a debugger symbol */
334 /*-----------------------------------------------------------------*/
336 pic14_emitDebuggerSymbol (char * debugSym)
339 pic14_emitcode ("", ";%s ==.", debugSym);
344 /*-----------------------------------------------------------------*/
345 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
346 /*-----------------------------------------------------------------*/
347 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
349 bool r0iu = FALSE , r1iu = FALSE;
350 bool r0ou = FALSE , r1ou = FALSE;
352 /* the logic: if r0 & r1 used in the instruction
353 then we are in trouble otherwise */
355 /* first check if r0 & r1 are used by this
356 instruction, in which case we are in trouble */
357 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
358 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
363 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
364 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
366 /* if no usage of r0 then return it */
367 if (!r0iu && !r0ou) {
368 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
369 (*aopp)->type = AOP_R0;
371 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
374 /* if no usage of r1 then return it */
375 if (!r1iu && !r1ou) {
376 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
377 (*aopp)->type = AOP_R1;
379 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
382 /* now we know they both have usage */
383 /* if r0 not used in this instruction */
385 /* push it if not already pushed */
387 //pic14_emitcode ("push","%s",
388 // pic14_regWithIdx(R0_IDX)->dname);
392 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
393 (*aopp)->type = AOP_R0;
395 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
398 /* if r1 not used then */
401 /* push it if not already pushed */
403 //pic14_emitcode ("push","%s",
404 // pic14_regWithIdx(R1_IDX)->dname);
408 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
409 (*aopp)->type = AOP_R1;
410 return pic14_regWithIdx(R1_IDX);
414 /* I said end of world but not quite end of world yet */
415 /* if this is a result then we can push it on the stack*/
417 (*aopp)->type = AOP_STK;
421 /* other wise this is true end of the world */
422 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
423 "getFreePtr should never reach here");
428 /*-----------------------------------------------------------------*/
429 /* newAsmop - creates a new asmOp */
430 /*-----------------------------------------------------------------*/
431 asmop *newAsmop (short type)
435 aop = Safe_calloc(1,sizeof(asmop));
440 static void genSetDPTR(int n)
444 pic14_emitcode(";", "Select standard DPTR");
445 pic14_emitcode("mov", "dps, #0x00");
449 pic14_emitcode(";", "Select alternate DPTR");
450 pic14_emitcode("mov", "dps, #0x01");
454 /*-----------------------------------------------------------------*/
455 /* resolveIfx - converts an iCode ifx into a form more useful for */
456 /* generating code */
457 /*-----------------------------------------------------------------*/
458 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
463 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
465 resIfx->condition = 1; /* assume that the ifx is true */
466 resIfx->generated = 0; /* indicate that the ifx has not been used */
469 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
471 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
472 __FUNCTION__,__LINE__,resIfx->lbl->key);
476 resIfx->lbl = IC_TRUE(ifx);
478 resIfx->lbl = IC_FALSE(ifx);
479 resIfx->condition = 0;
483 DEBUGpic14_emitcode("; ***","ifx true is non-null");
485 DEBUGpic14_emitcode("; ***","ifx false is non-null");
489 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
492 /*-----------------------------------------------------------------*/
493 /* pointerCode - returns the code for a pointer type */
494 /*-----------------------------------------------------------------*/
496 static int pointerCode (sym_link *etype)
499 return PTR_TYPE(SPEC_OCLS(etype));
504 /*-----------------------------------------------------------------*/
505 /* aopForSym - for a true symbol */
506 /*-----------------------------------------------------------------*/
507 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
510 memmap *space= SPEC_OCLS(sym->etype);
512 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
513 /* if already has one */
518 /* assign depending on the storage class */
519 /* if it is on the stack or indirectly addressable */
520 /* space we need to assign either r0 or r1 to it */
521 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
522 sym->aop = aop = newAsmop(0);
523 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
524 aop->size = getSize(sym->type);
526 /* now assign the address of the variable to
527 the pointer register */
528 if (aop->type != AOP_STK) {
532 pic14_emitcode("push","acc");
534 pic14_emitcode("mov","a,_bp");
535 pic14_emitcode("add","a,#0x%02x",
537 ((char)(sym->stack - _G.nRegsSaved )) :
538 ((char)sym->stack)) & 0xff);
539 pic14_emitcode("mov","%s,a",
540 aop->aopu.aop_ptr->name);
543 pic14_emitcode("pop","acc");
545 pic14_emitcode("mov","%s,#%s",
546 aop->aopu.aop_ptr->name,
548 aop->paged = space->paged;
550 aop->aopu.aop_stk = sym->stack;
554 if (sym->onStack && options.stack10bit)
556 /* It's on the 10 bit stack, which is located in
560 //DEBUGpic14_emitcode(";","%d",__LINE__);
563 pic14_emitcode("push","acc");
565 pic14_emitcode("mov","a,_bp");
566 pic14_emitcode("add","a,#0x%02x",
568 ((char)(sym->stack - _G.nRegsSaved )) :
569 ((char)sym->stack)) & 0xff);
572 pic14_emitcode ("mov","dpx1,#0x40");
573 pic14_emitcode ("mov","dph1,#0x00");
574 pic14_emitcode ("mov","dpl1, a");
578 pic14_emitcode("pop","acc");
580 sym->aop = aop = newAsmop(AOP_DPTR2);
581 aop->size = getSize(sym->type);
586 //DEBUGpic14_emitcode(";","%d",__LINE__);
587 /* if in bit space */
588 if (IN_BITSPACE(space)) {
589 sym->aop = aop = newAsmop (AOP_CRY);
590 aop->aopu.aop_dir = sym->rname ;
591 aop->size = getSize(sym->type);
592 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
595 /* if it is in direct space */
596 if (IN_DIRSPACE(space)) {
597 sym->aop = aop = newAsmop (AOP_DIR);
598 aop->aopu.aop_dir = sym->rname ;
599 aop->size = getSize(sym->type);
600 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
604 /* special case for a function */
605 if (IS_FUNC(sym->type)) {
607 sym->aop = aop = newAsmop(AOP_PCODE);
608 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
609 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
610 PCOI(aop->aopu.pcop)->_function = 1;
611 PCOI(aop->aopu.pcop)->index = 0;
612 aop->size = FPTRSIZE;
614 sym->aop = aop = newAsmop(AOP_IMMD);
615 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
616 strcpy(aop->aopu.aop_immd,sym->rname);
617 aop->size = FPTRSIZE;
619 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
623 if (IS_ARRAY(sym->type)) {
624 sym->aop = aop = newAsmop(AOP_PCODE);
625 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
626 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
627 PCOI(aop->aopu.pcop)->_function = 0;
628 PCOI(aop->aopu.pcop)->index = 0;
629 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
631 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
635 /* only remaining is far space */
636 /* in which case DPTR gets the address */
637 sym->aop = aop = newAsmop(AOP_PCODE);
639 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
640 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
641 PCOI(aop->aopu.pcop)->index = 0;
643 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
644 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
646 allocDirReg (IC_LEFT(ic));
648 aop->size = FPTRSIZE;
650 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
651 sym->aop = aop = newAsmop(AOP_DPTR);
652 pic14_emitcode ("mov","dptr,#%s", sym->rname);
653 aop->size = getSize(sym->type);
655 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
658 /* if it is in code space */
659 if (IN_CODESPACE(space))
665 /*-----------------------------------------------------------------*/
666 /* aopForRemat - rematerialzes an object */
667 /*-----------------------------------------------------------------*/
668 static asmop *aopForRemat (operand *op) // x symbol *sym)
670 symbol *sym = OP_SYMBOL(op);
672 asmop *aop = newAsmop(AOP_PCODE);
676 ic = sym->rematiCode;
678 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
679 if(IS_OP_POINTER(op)) {
680 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
684 val += (int) operandLitValue(IC_RIGHT(ic));
685 } else if (ic->op == '-') {
686 val -= (int) operandLitValue(IC_RIGHT(ic));
690 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
693 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
694 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
695 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
696 PCOI(aop->aopu.pcop)->index = val;
698 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
699 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
700 val, IS_PTR_CONST(operandType(op)));
702 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
704 allocDirReg (IC_LEFT(ic));
709 int aopIdx (asmop *aop, int offset)
714 if(aop->type != AOP_REG)
717 return aop->aopu.aop_reg[offset]->rIdx;
720 /*-----------------------------------------------------------------*/
721 /* regsInCommon - two operands have some registers in common */
722 /*-----------------------------------------------------------------*/
723 static bool regsInCommon (operand *op1, operand *op2)
728 /* if they have registers in common */
729 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
732 sym1 = OP_SYMBOL(op1);
733 sym2 = OP_SYMBOL(op2);
735 if (sym1->nRegs == 0 || sym2->nRegs == 0)
738 for (i = 0 ; i < sym1->nRegs ; i++) {
743 for (j = 0 ; j < sym2->nRegs ;j++ ) {
747 if (sym2->regs[j] == sym1->regs[i])
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent */
757 /*-----------------------------------------------------------------*/
758 static bool operandsEqu ( operand *op1, operand *op2)
762 /* if they not symbols */
763 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
766 sym1 = OP_SYMBOL(op1);
767 sym2 = OP_SYMBOL(op2);
769 /* if both are itemps & one is spilt
770 and the other is not then false */
771 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
772 sym1->isspilt != sym2->isspilt )
775 /* if they are the same */
779 if (sym1->rname[0] && sym2->rname[0]
780 && strcmp (sym1->rname, sym2->rname) == 0)
784 /* if left is a tmp & right is not */
788 (sym1->usl.spillLoc == sym2))
795 (sym2->usl.spillLoc == sym1))
801 /*-----------------------------------------------------------------*/
802 /* pic14_sameRegs - two asmops have the same registers */
803 /*-----------------------------------------------------------------*/
804 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
811 if (aop1->type != AOP_REG ||
812 aop2->type != AOP_REG )
815 if (aop1->size != aop2->size )
818 for (i = 0 ; i < aop1->size ; i++ )
819 if (aop1->aopu.aop_reg[i] !=
820 aop2->aopu.aop_reg[i] )
826 /*-----------------------------------------------------------------*/
827 /* aopOp - allocates an asmop for an operand : */
828 /*-----------------------------------------------------------------*/
829 void aopOp (operand *op, iCode *ic, bool result)
838 /* if this a literal */
839 if (IS_OP_LITERAL(op)) {
840 op->aop = aop = newAsmop(AOP_LIT);
841 aop->aopu.aop_lit = op->operand.valOperand;
842 aop->size = getSize(operandType(op));
847 sym_link *type = operandType(op);
848 if(IS_PTR_CONST(type))
849 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
852 /* if already has a asmop then continue */
856 /* if the underlying symbol has a aop */
857 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
858 DEBUGpic14_emitcode(";","%d",__LINE__);
859 op->aop = OP_SYMBOL(op)->aop;
863 /* if this is a true symbol */
864 if (IS_TRUE_SYMOP(op)) {
865 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
866 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
870 /* this is a temporary : this has
876 e) can be a return use only */
881 /* if the type is a conditional */
882 if (sym->regType == REG_CND) {
883 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
888 /* if it is spilt then two situations
890 b) has a spill location */
891 if (sym->isspilt || sym->nRegs == 0) {
893 DEBUGpic14_emitcode(";","%d",__LINE__);
894 /* rematerialize it NOW */
897 sym->aop = op->aop = aop = aopForRemat (op);
898 aop->size = getSize(sym->type);
899 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
904 /* WREG is not usable as an ordinary operand with PIC architecture,
905 * one might introduce a scratch register that can be used to make
906 * WREG accesible as an operand... disable WREG for now */
909 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
910 aop->size = getSize(sym->type);
911 for ( i = 0 ; i < 2 ; i++ )
912 aop->aopu.aop_str[i] = accUse[i];
913 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
919 if(sym->isptr) { // && sym->uptr
920 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
921 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
923 //PCOI(aop->aopu.pcop)->_const = 0;
924 //PCOI(aop->aopu.pcop)->index = 0;
926 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
927 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
929 //allocDirReg (IC_LEFT(ic));
931 aop->size = getSize(sym->type);
932 DEBUGpic14_emitcode(";","%d",__LINE__);
939 aop = op->aop = sym->aop = newAsmop(AOP_STR);
940 aop->size = getSize(sym->type);
941 for ( i = 0 ; i < fReturnSizePic ; i++ )
942 aop->aopu.aop_str[i] = fReturn[i];
944 DEBUGpic14_emitcode(";","%d",__LINE__);
949 /* else spill location */
950 if (sym->usl.spillLoc)
952 asmop *oldAsmOp = NULL;
954 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
956 /* force a new aop if sizes differ */
957 oldAsmOp = sym->usl.spillLoc->aop;
958 sym->usl.spillLoc->aop = NULL;
960 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
961 __FUNCTION__,__LINE__,
962 sym->usl.spillLoc->rname,
963 sym->rname, sym->usl.spillLoc->offset);
965 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
966 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
968 /* Don't reuse the new aop, go with the last one */
969 sym->usl.spillLoc->aop = oldAsmOp;
971 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
972 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
974 sym->usl.spillLoc->offset);
975 aop->size = getSize(sym->type);
982 sym_link *type = operandType(op);
983 if(IS_PTR_CONST(type))
984 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
987 /* must be in a register */
988 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
989 sym->aop = op->aop = aop = newAsmop(AOP_REG);
990 aop->size = sym->nRegs;
991 for ( i = 0 ; i < sym->nRegs ;i++)
992 aop->aopu.aop_reg[i] = sym->regs[i];
995 /*-----------------------------------------------------------------*/
996 /* freeAsmop - free up the asmop given to an operand */
997 /*----------------------------------------------------------------*/
998 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1015 /* depending on the asmop type only three cases need work AOP_RO
1016 , AOP_R1 && AOP_STK */
1018 switch (aop->type) {
1022 pic14_emitcode ("pop","ar0");
1026 bitVectUnSetBit(ic->rUsed,R0_IDX);
1032 pic14_emitcode ("pop","ar1");
1036 bitVectUnSetBit(ic->rUsed,R1_IDX);
1042 int stk = aop->aopu.aop_stk + aop->size;
1043 bitVectUnSetBit(ic->rUsed,R0_IDX);
1044 bitVectUnSetBit(ic->rUsed,R1_IDX);
1046 getFreePtr(ic,&aop,FALSE);
1048 if (options.stack10bit)
1050 /* I'm not sure what to do here yet... */
1053 "*** Warning: probably generating bad code for "
1054 "10 bit stack mode.\n");
1058 pic14_emitcode ("mov","a,_bp");
1059 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1060 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1062 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1066 pic14_emitcode("pop","acc");
1067 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1069 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072 freeAsmop(op,NULL,ic,TRUE);
1074 pic14_emitcode("pop","ar0");
1079 pic14_emitcode("pop","ar1");
1087 /* all other cases just dealloc */
1091 OP_SYMBOL(op)->aop = NULL;
1092 /* if the symbol has a spill */
1094 SPIL_LOC(op)->aop = NULL;
1099 /*-----------------------------------------------------------------*/
1100 /* aopGet - for fetching value of the aop */
1101 /*-----------------------------------------------------------------*/
1102 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1107 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1108 /* offset is greater than
1110 if (offset > (aop->size - 1) &&
1111 aop->type != AOP_LIT)
1114 /* depending on type */
1115 switch (aop->type) {
1119 DEBUGpic14_emitcode(";","%d",__LINE__);
1120 /* if we need to increment it */
1121 while (offset > aop->coff) {
1122 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1126 while (offset < aop->coff) {
1127 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1131 aop->coff = offset ;
1133 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1134 return (dname ? "acc" : "a");
1136 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1137 rs = Safe_calloc(1,strlen(s)+1);
1143 DEBUGpic14_emitcode(";","%d",__LINE__);
1144 if (aop->type == AOP_DPTR2)
1149 while (offset > aop->coff) {
1150 pic14_emitcode ("inc","dptr");
1154 while (offset < aop->coff) {
1155 pic14_emitcode("lcall","__decdptr");
1161 pic14_emitcode("clr","a");
1162 pic14_emitcode("movc","a,@a+dptr");
1165 pic14_emitcode("movx","a,@dptr");
1168 if (aop->type == AOP_DPTR2)
1173 return (dname ? "acc" : "a");
1178 sprintf (s,"%s",aop->aopu.aop_immd);
1181 sprintf(s,"(%s >> %d)",
1186 aop->aopu.aop_immd);
1187 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1188 rs = Safe_calloc(1,strlen(s)+1);
1194 sprintf(s,"(%s + %d)",
1197 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1199 sprintf(s,"%s",aop->aopu.aop_dir);
1200 rs = Safe_calloc(1,strlen(s)+1);
1206 // return aop->aopu.aop_reg[offset]->dname;
1208 return aop->aopu.aop_reg[offset]->name;
1211 //pic14_emitcode(";","%d",__LINE__);
1212 return aop->aopu.aop_dir;
1215 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1216 return "AOP_accumulator_bug";
1219 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1220 rs = Safe_strdup(s);
1224 aop->coff = offset ;
1225 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1228 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1230 return aop->aopu.aop_str[offset];
1234 pCodeOp *pcop = aop->aopu.pcop;
1235 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1238 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1239 sprintf(s,"(%s+%d)", pcop->name,offset);
1241 DEBUGpic14_emitcode(";","%s",pcop->name);
1242 sprintf(s,"%s", pcop->name);
1245 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1248 rs = Safe_calloc(1,strlen(s)+1);
1254 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1255 "aopget got unsupported aop->type");
1260 /*-----------------------------------------------------------------*/
1261 /* popGetTempReg - create a new temporary pCodeOp */
1262 /*-----------------------------------------------------------------*/
1263 pCodeOp *popGetTempReg(void)
1268 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1269 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1270 PCOR(pcop)->r->wasUsed=1;
1271 PCOR(pcop)->r->isFree=0;
1277 /*-----------------------------------------------------------------*/
1278 /* popReleaseTempReg - create a new temporary pCodeOp */
1279 /*-----------------------------------------------------------------*/
1280 void popReleaseTempReg(pCodeOp *pcop)
1283 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1284 PCOR(pcop)->r->isFree = 1;
1287 /*-----------------------------------------------------------------*/
1288 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1289 /*-----------------------------------------------------------------*/
1290 pCodeOp *popGetLabel(unsigned int key)
1293 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1295 if(key>(unsigned int)max_key)
1298 return newpCodeOpLabel(NULL,key+100+labelOffset);
1301 /*-------------------------------------------------------------------*/
1302 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1303 /*-------------------------------------------------------------------*/
1304 pCodeOp *popGetHighLabel(unsigned int key)
1307 pcop = popGetLabel(key);
1308 PCOLAB(pcop)->offset = 1;
1312 /*-----------------------------------------------------------------*/
1313 /* popGetLit - asm operator to pcode operator conversion */
1314 /*-----------------------------------------------------------------*/
1315 pCodeOp *popGetLit(unsigned int lit)
1318 return newpCodeOpLit((unsigned char)lit);
1321 /*-----------------------------------------------------------------*/
1322 /* popGetImmd - asm operator to pcode immediate conversion */
1323 /*-----------------------------------------------------------------*/
1324 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1327 return newpCodeOpImmd(name, offset,index, 0, is_func);
1330 extern set *externs;
1332 /*-----------------------------------------------------------------*/
1333 /* popGetWithString - asm operator to pcode operator conversion */
1334 /*-----------------------------------------------------------------*/
1335 pCodeOp *popGetWithString(char *str, int isExtern)
1341 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1345 pcop = newpCodeOp(str,PO_STR);
1346 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1351 pCodeOp *popGetExternal (char *str)
1353 pCodeOp *pcop = popGetWithString (str, 1);
1359 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1361 if (!strcmp (str, sym->rname))
1367 sym = newSymbol(str, 0);
1368 strncpy(sym->rname, str, SDCC_NAME_MAX);
1369 addSet (&externs, sym);
1375 /*-----------------------------------------------------------------*/
1376 /* popRegFromString - */
1377 /*-----------------------------------------------------------------*/
1378 pCodeOp *popRegFromString(char *str, int size, int offset)
1381 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1382 pcop->type = PO_DIR;
1384 DEBUGpic14_emitcode(";","%d",__LINE__);
1389 pcop->name = Safe_calloc(1,strlen(str)+1);
1390 strcpy(pcop->name,str);
1392 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1394 PCOR(pcop)->r = dirregWithName(pcop->name);
1395 if(PCOR(pcop)->r == NULL) {
1396 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1397 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1398 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1400 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1402 PCOR(pcop)->instance = offset;
1407 /*-----------------------------------------------------------------*/
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *popRegFromIdx(int rIdx)
1413 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1414 __FUNCTION__,__LINE__,rIdx);
1416 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1418 PCOR(pcop)->rIdx = rIdx;
1419 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1420 PCOR(pcop)->r->isFree = 0;
1421 PCOR(pcop)->r->wasUsed = 1;
1423 pcop->type = PCOR(pcop)->r->pc_type;
1429 /*-----------------------------------------------------------------*/
1430 /* popGet - asm operator to pcode operator conversion */
1431 /*-----------------------------------------------------------------*/
1432 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1434 //char *s = buffer ;
1439 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1440 /* offset is greater than
1446 /* XXX: still needed for BIT operands (AOP_CRY) */
1447 if (offset > (aop->size - 1) &&
1448 aop->type != AOP_LIT &&
1449 aop->type != AOP_PCODE)
1451 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1452 return NULL; //zero;
1455 /* depending on type */
1456 switch (aop->type) {
1463 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1467 DEBUGpic14_emitcode(";","%d",__LINE__);
1468 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1471 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1473 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1474 pcop->type = PO_DIR;
1476 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1477 strcpy(pcop->name,aop->aopu.aop_dir);
1478 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1479 if(PCOR(pcop)->r == NULL) {
1480 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1481 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1482 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1484 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1486 PCOR(pcop)->instance = offset;
1494 assert (offset < aop->size);
1495 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1497 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1498 PCOR(pcop)->rIdx = rIdx;
1499 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1500 PCOR(pcop)->r->wasUsed=1;
1501 PCOR(pcop)->r->isFree=0;
1503 PCOR(pcop)->instance = offset;
1504 pcop->type = PCOR(pcop)->r->pc_type;
1505 //rs = aop->aopu.aop_reg[offset]->name;
1506 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1511 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1512 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1513 //if(PCOR(pcop)->r == NULL)
1514 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1518 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1521 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1522 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1524 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1525 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1526 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1527 pcop->type = PCOR(pcop)->r->pc_type;
1528 pcop->name = PCOR(pcop)->r->name;
1535 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1537 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1538 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1539 switch (aop->aopu.pcop->type)
1542 pcop = pCodeOpCopy (aop->aopu.pcop);
1543 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1544 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1545 PCOI(pcop)->index += offset;
1546 //PCOI(pcop)->offset = 0;
1549 pcop = pCodeOpCopy (aop->aopu.pcop);
1550 PCOR(pcop)->instance = offset;
1553 assert ( !"unhandled pCode type" );
1559 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1560 "popGet got unsupported aop->type");
1564 /*-----------------------------------------------------------------*/
1565 /* popGetAddr - access the low/high word of a symbol (immediate) */
1566 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1567 /*-----------------------------------------------------------------*/
1568 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1570 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1572 pCodeOp *pcop = aop->aopu.pcop;
1573 assert (offset <= GPTRSIZE);
1575 /* special case: index >= 2 should return GPOINTER-style values */
1578 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1582 pcop = pCodeOpCopy (pcop);
1583 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1584 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1585 PCOI(pcop)->offset += offset;
1586 PCOI(pcop)->index += index;
1587 //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);
1590 return popGet (aop, offset + index);
1594 /*-----------------------------------------------------------------*/
1595 /* aopPut - puts a string for a aop */
1596 /*-----------------------------------------------------------------*/
1597 void aopPut (asmop *aop, char *s, int offset)
1602 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1604 if (aop->size && offset > ( aop->size - 1)) {
1605 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1606 "aopPut got offset > aop->size");
1610 /* will assign value to value */
1611 /* depending on where it is ofcourse */
1612 switch (aop->type) {
1615 sprintf(d,"(%s + %d)",
1616 aop->aopu.aop_dir,offset);
1617 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1620 sprintf(d,"%s",aop->aopu.aop_dir);
1623 DEBUGpic14_emitcode(";","%d",__LINE__);
1625 pic14_emitcode("movf","%s,w",s);
1626 pic14_emitcode("movwf","%s",d);
1629 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1630 if(offset >= aop->size) {
1631 emitpcode(POC_CLRF,popGet(aop,offset));
1634 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1637 emitpcode(POC_MOVWF,popGet(aop,offset));
1643 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1644 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1647 strcmp(s,"r0") == 0 ||
1648 strcmp(s,"r1") == 0 ||
1649 strcmp(s,"r2") == 0 ||
1650 strcmp(s,"r3") == 0 ||
1651 strcmp(s,"r4") == 0 ||
1652 strcmp(s,"r5") == 0 ||
1653 strcmp(s,"r6") == 0 ||
1654 strcmp(s,"r7") == 0 )
1655 pic14_emitcode("mov","%s,%s ; %d",
1656 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1660 if(strcmp(s,"W")==0 )
1661 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1663 pic14_emitcode("movwf","%s",
1664 aop->aopu.aop_reg[offset]->name);
1666 if(strcmp(s,zero)==0) {
1667 emitpcode(POC_CLRF,popGet(aop,offset));
1669 } else if(strcmp(s,"W")==0) {
1670 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1671 pcop->type = PO_GPR_REGISTER;
1673 PCOR(pcop)->rIdx = -1;
1674 PCOR(pcop)->r = NULL;
1676 DEBUGpic14_emitcode(";","%d",__LINE__);
1677 pcop->name = Safe_strdup(s);
1678 emitpcode(POC_MOVFW,pcop);
1679 emitpcode(POC_MOVWF,popGet(aop,offset));
1680 } else if(strcmp(s,one)==0) {
1681 emitpcode(POC_CLRF,popGet(aop,offset));
1682 emitpcode(POC_INCF,popGet(aop,offset));
1684 emitpcode(POC_MOVWF,popGet(aop,offset));
1692 if (aop->type == AOP_DPTR2)
1698 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1699 "aopPut writting to code space");
1703 while (offset > aop->coff) {
1705 pic14_emitcode ("inc","dptr");
1708 while (offset < aop->coff) {
1710 pic14_emitcode("lcall","__decdptr");
1715 /* if not in accumulater */
1718 pic14_emitcode ("movx","@dptr,a");
1720 if (aop->type == AOP_DPTR2)
1728 while (offset > aop->coff) {
1730 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1732 while (offset < aop->coff) {
1734 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1740 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1745 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1747 if (strcmp(s,"r0") == 0 ||
1748 strcmp(s,"r1") == 0 ||
1749 strcmp(s,"r2") == 0 ||
1750 strcmp(s,"r3") == 0 ||
1751 strcmp(s,"r4") == 0 ||
1752 strcmp(s,"r5") == 0 ||
1753 strcmp(s,"r6") == 0 ||
1754 strcmp(s,"r7") == 0 ) {
1756 sprintf(buffer,"a%s",s);
1757 pic14_emitcode("mov","@%s,%s",
1758 aop->aopu.aop_ptr->name,buffer);
1760 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1765 if (strcmp(s,"a") == 0)
1766 pic14_emitcode("push","acc");
1768 pic14_emitcode("push","%s",s);
1773 /* if bit variable */
1774 if (!aop->aopu.aop_dir) {
1775 pic14_emitcode("clr","a");
1776 pic14_emitcode("rlc","a");
1779 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1782 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1785 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1787 lbl = newiTempLabel(NULL);
1789 if (strcmp(s,"a")) {
1792 pic14_emitcode("clr","c");
1793 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1794 pic14_emitcode("cpl","c");
1795 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1796 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1803 if (strcmp(aop->aopu.aop_str[offset],s))
1804 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1809 if (!offset && (strcmp(s,"acc") == 0))
1812 if (strcmp(aop->aopu.aop_str[offset],s))
1813 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1817 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1818 "aopPut got unsupported aop->type");
1824 /*-----------------------------------------------------------------*/
1825 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1826 /*-----------------------------------------------------------------*/
1827 static void mov2w_op (operand *op, int offset)
1832 /* for PO_IMMEDIATEs: use address or value? */
1833 if (op_isLitLike (op))
1835 /* access address of op */
1836 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1837 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1839 if (offset == GPTRSIZE-1)
1840 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1842 emitpcode (POC_MOVLW, popGetLit (0));
1845 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1847 /* access value stored in op */
1848 mov2w (AOP(op), offset);
1853 /*-----------------------------------------------------------------*/
1854 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1855 /*-----------------------------------------------------------------*/
1856 void mov2w (asmop *aop, int offset)
1862 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1864 if ( aop_isLitLike (aop) )
1865 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1867 emitpcode(POC_MOVFW,popGet(aop,offset));
1871 static void movwf (asmop *op, int offset)
1873 emitpcode (POC_MOVWF, popGet(op, offset));
1876 static pCodeOp *get_argument_pcop (int idx)
1878 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1879 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1882 static pCodeOp *get_return_val_pcop (int offset)
1884 assert (offset > 0 && "the most significant byte is returned via WREG");
1885 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1888 static void pass_argument (operand *op, int offset, int idx)
1891 mov2w_op (op, offset);
1893 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1896 static void get_returnvalue (operand *op, int offset, int idx)
1899 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1900 movwf(AOP(op), offset);
1903 static void call_libraryfunc (char *name)
1905 /* library code might reside in different page... */
1906 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1907 /* call the library function */
1908 emitpcode (POC_CALL, popGetExternal (name));
1909 /* might return from different page... */
1910 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1913 /*-----------------------------------------------------------------*/
1914 /* reAdjustPreg - points a register back to where it should */
1915 /*-----------------------------------------------------------------*/
1916 static void reAdjustPreg (asmop *aop)
1920 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1922 if ((size = aop->size) <= 1)
1925 switch (aop->type) {
1929 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1933 if (aop->type == AOP_DPTR2)
1939 pic14_emitcode("lcall","__decdptr");
1942 if (aop->type == AOP_DPTR2)
1955 /*-----------------------------------------------------------------*/
1956 /* opIsGptr: returns non-zero if the passed operand is */
1957 /* a generic pointer type. */
1958 /*-----------------------------------------------------------------*/
1959 static int opIsGptr(operand *op)
1961 sym_link *type = operandType(op);
1963 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1964 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1972 /*-----------------------------------------------------------------*/
1973 /* pic14_getDataSize - get the operand data size */
1974 /*-----------------------------------------------------------------*/
1975 int pic14_getDataSize(operand *op)
1979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1982 size = getSize(OP_SYM_ETYPE(op));
1984 //return AOP_SIZE(op);
1986 // tsd- in the pic port, the genptr size is 1, so this code here
1987 // fails. ( in the 8051 port, the size was 4).
1989 size = AOP_SIZE(op);
1990 if (IS_GENPTR(OP_SYM_TYPE(op)))
1992 sym_link *type = operandType(op);
1993 if (IS_GENPTR(type))
1995 /* generic pointer; arithmetic operations
1996 * should ignore the high byte (pointer type).
1999 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2006 /*-----------------------------------------------------------------*/
2007 /* pic14_outAcc - output Acc */
2008 /*-----------------------------------------------------------------*/
2009 void pic14_outAcc(operand *result)
2012 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2013 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2016 size = pic14_getDataSize(result);
2018 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2021 /* unsigned or positive */
2023 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2028 /*-----------------------------------------------------------------*/
2029 /* pic14_outBitC - output a bit C */
2030 /*-----------------------------------------------------------------*/
2031 void pic14_outBitC(operand *result)
2034 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2035 /* if the result is bit */
2036 if (AOP_TYPE(result) == AOP_CRY)
2037 aopPut(AOP(result),"c",0);
2039 pic14_emitcode("clr","a ; %d", __LINE__);
2040 pic14_emitcode("rlc","a");
2041 pic14_outAcc(result);
2045 /*-----------------------------------------------------------------*/
2046 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2047 /*-----------------------------------------------------------------*/
2048 void pic14_toBoolean(operand *oper)
2050 int size = AOP_SIZE(oper);
2053 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2058 /* MOVFW does not load the flags... */
2059 if (AOP_TYPE(oper) == AOP_ACC) {
2060 emitpcode(POC_IORLW, popGetLit(0));
2063 emitpcode(POC_MOVLW, popGetLit(0));
2067 if ( AOP_TYPE(oper) != AOP_ACC) {
2068 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2073 while (offset < size) {
2074 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2076 /* Z is set iff (oper == 0) */
2080 /*-----------------------------------------------------------------*/
2081 /* genNot - generate code for ! operation */
2082 /*-----------------------------------------------------------------*/
2083 static void genNot (iCode *ic)
2090 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2091 /* assign asmOps to operand & result */
2092 aopOp (IC_LEFT(ic),ic,FALSE);
2093 aopOp (IC_RESULT(ic),ic,TRUE);
2095 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2096 /* if in bit space then a special case */
2097 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2098 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2099 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2100 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2102 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2103 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2104 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2109 size = AOP_SIZE(IC_LEFT(ic));
2110 mov2w (AOP(IC_LEFT(ic)),0);
2113 if (op_isLitLike (IC_LEFT(ic)))
2114 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2116 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2118 emitpcode(POC_MOVLW, popGetLit (0));
2120 emitpcode(POC_MOVLW, popGetLit (1));
2121 movwf(AOP(IC_RESULT(ic)), 0);
2123 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2125 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2130 /* release the aops */
2131 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2132 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2136 /*-----------------------------------------------------------------*/
2137 /* genCpl - generate code for complement */
2138 /*-----------------------------------------------------------------*/
2139 static void genCpl (iCode *ic)
2141 operand *left, *result;
2146 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2147 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2148 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2150 /* if both are in bit space then
2152 if (AOP_TYPE(result) == AOP_CRY &&
2153 AOP_TYPE(left) == AOP_CRY ) {
2155 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2156 pic14_emitcode("cpl","c");
2157 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2161 size = AOP_SIZE(result);
2162 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2165 if(AOP_TYPE(left) == AOP_ACC)
2166 emitpcode(POC_XORLW, popGetLit(0xff));
2168 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2170 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2173 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2177 /* release the aops */
2178 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2179 freeAsmop(result,NULL,ic,TRUE);
2182 /*-----------------------------------------------------------------*/
2183 /* genUminusFloat - unary minus for floating points */
2184 /*-----------------------------------------------------------------*/
2185 static void genUminusFloat(operand *op,operand *result)
2187 int size ,offset =0 ;
2192 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2193 /* for this we just need to flip the
2194 first it then copy the rest in place */
2195 size = AOP_SIZE(op) - 1;
2196 l = aopGet(AOP(op),3,FALSE,FALSE);
2200 pic14_emitcode("cpl","acc.7");
2201 aopPut(AOP(result),"a",3);
2205 aopGet(AOP(op),offset,FALSE,FALSE),
2211 /*-----------------------------------------------------------------*/
2212 /* genUminus - unary minus code generation */
2213 /*-----------------------------------------------------------------*/
2214 static void genUminus (iCode *ic)
2217 sym_link *optype, *rtype;
2221 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2223 aopOp(IC_LEFT(ic),ic,FALSE);
2224 aopOp(IC_RESULT(ic),ic,TRUE);
2226 /* if both in bit space then special
2228 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2229 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2231 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2232 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2233 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2238 optype = operandType(IC_LEFT(ic));
2239 rtype = operandType(IC_RESULT(ic));
2241 /* if float then do float stuff */
2242 if (IS_FLOAT(optype)) {
2243 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2247 /* otherwise subtract from zero by taking the 2's complement */
2248 size = AOP_SIZE(IC_LEFT(ic));
2250 for(i=0; i<size; i++) {
2251 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2252 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2254 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2255 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2259 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2260 for(i=1; i<size; i++) {
2262 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2266 /* release the aops */
2267 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2268 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2271 /*-----------------------------------------------------------------*/
2272 /* saveRegisters - will look for a call and save the registers */
2273 /*-----------------------------------------------------------------*/
2274 static void saveRegisters(iCode *lic)
2283 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2285 for (ic = lic ; ic ; ic = ic->next)
2286 if (ic->op == CALL || ic->op == PCALL)
2290 fprintf(stderr,"found parameter push with no function call\n");
2294 /* if the registers have been saved already then
2296 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2299 /* find the registers in use at this time
2300 and push them away to safety */
2301 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2305 if (options.useXstack) {
2306 if (bitVectBitValue(rsave,R0_IDX))
2307 pic14_emitcode("mov","b,r0");
2308 pic14_emitcode("mov","r0,%s",spname);
2309 for (i = 0 ; i < pic14_nRegs ; i++) {
2310 if (bitVectBitValue(rsave,i)) {
2312 pic14_emitcode("mov","a,b");
2314 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2315 pic14_emitcode("movx","@r0,a");
2316 pic14_emitcode("inc","r0");
2319 pic14_emitcode("mov","%s,r0",spname);
2320 if (bitVectBitValue(rsave,R0_IDX))
2321 pic14_emitcode("mov","r0,b");
2323 //for (i = 0 ; i < pic14_nRegs ; i++) {
2324 // if (bitVectBitValue(rsave,i))
2325 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2328 dtype = operandType(IC_LEFT(ic));
2329 if (currFunc && dtype &&
2330 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2331 IFFUNC_ISISR(currFunc->type) &&
2334 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2337 /*-----------------------------------------------------------------*/
2338 /* unsaveRegisters - pop the pushed registers */
2339 /*-----------------------------------------------------------------*/
2340 static void unsaveRegisters (iCode *ic)
2347 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2348 /* find the registers in use at this time
2349 and push them away to safety */
2350 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2353 if (options.useXstack) {
2354 pic14_emitcode("mov","r0,%s",spname);
2355 for (i = pic14_nRegs ; i >= 0 ; i--) {
2356 if (bitVectBitValue(rsave,i)) {
2357 pic14_emitcode("dec","r0");
2358 pic14_emitcode("movx","a,@r0");
2360 pic14_emitcode("mov","b,a");
2362 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2366 pic14_emitcode("mov","%s,r0",spname);
2367 if (bitVectBitValue(rsave,R0_IDX))
2368 pic14_emitcode("mov","r0,b");
2370 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2371 // if (bitVectBitValue(rsave,i))
2372 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2378 /*-----------------------------------------------------------------*/
2380 /*-----------------------------------------------------------------*/
2381 static void pushSide(operand * oper, int size)
2385 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2387 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2388 if (AOP_TYPE(oper) != AOP_REG &&
2389 AOP_TYPE(oper) != AOP_DIR &&
2391 pic14_emitcode("mov","a,%s",l);
2392 pic14_emitcode("push","acc");
2394 pic14_emitcode("push","%s",l);
2399 /*-----------------------------------------------------------------*/
2400 /* assignResultValue - */
2401 /*-----------------------------------------------------------------*/
2402 static void assignResultValue(operand * oper)
2404 int size = AOP_SIZE(oper);
2409 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2411 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2413 /* assign MSB first (passed via WREG) */
2415 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2421 /*-----------------------------------------------------------------*/
2422 /* genIpush - genrate code for pushing this gets a little complex */
2423 /*-----------------------------------------------------------------*/
2424 static void genIpush (iCode *ic)
2428 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2430 int size, offset = 0 ;
2434 /* if this is not a parm push : ie. it is spill push
2435 and spill push is always done on the local stack */
2436 if (!ic->parmPush) {
2438 /* and the item is spilt then do nothing */
2439 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2442 aopOp(IC_LEFT(ic),ic,FALSE);
2443 size = AOP_SIZE(IC_LEFT(ic));
2444 /* push it on the stack */
2446 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2451 pic14_emitcode("push","%s",l);
2456 /* this is a paramter push: in this case we call
2457 the routine to find the call and save those
2458 registers that need to be saved */
2461 /* then do the push */
2462 aopOp(IC_LEFT(ic),ic,FALSE);
2465 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2466 size = AOP_SIZE(IC_LEFT(ic));
2469 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2470 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2471 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2473 pic14_emitcode("mov","a,%s",l);
2474 pic14_emitcode("push","acc");
2476 pic14_emitcode("push","%s",l);
2479 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2483 /*-----------------------------------------------------------------*/
2484 /* genIpop - recover the registers: can happen only for spilling */
2485 /*-----------------------------------------------------------------*/
2486 static void genIpop (iCode *ic)
2490 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2491 assert (!"genIpop -- unimplemented");
2496 /* if the temp was not pushed then */
2497 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2500 aopOp(IC_LEFT(ic),ic,FALSE);
2501 size = AOP_SIZE(IC_LEFT(ic));
2504 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2507 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2511 /*-----------------------------------------------------------------*/
2512 /* unsaverbank - restores the resgister bank from stack */
2513 /*-----------------------------------------------------------------*/
2514 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2518 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2524 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2526 if (options.useXstack) {
2528 r = getFreePtr(ic,&aop,FALSE);
2531 pic14_emitcode("mov","%s,_spx",r->name);
2532 pic14_emitcode("movx","a,@%s",r->name);
2533 pic14_emitcode("mov","psw,a");
2534 pic14_emitcode("dec","%s",r->name);
2537 pic14_emitcode ("pop","psw");
2540 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2541 if (options.useXstack) {
2542 pic14_emitcode("movx","a,@%s",r->name);
2543 //pic14_emitcode("mov","(%s+%d),a",
2544 // regspic14[i].base,8*bank+regspic14[i].offset);
2545 pic14_emitcode("dec","%s",r->name);
2548 pic14_emitcode("pop",""); //"(%s+%d)",
2549 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2552 if (options.useXstack) {
2554 pic14_emitcode("mov","_spx,%s",r->name);
2555 freeAsmop(NULL,aop,ic,TRUE);
2561 /*-----------------------------------------------------------------*/
2562 /* saverbank - saves an entire register bank on the stack */
2563 /*-----------------------------------------------------------------*/
2564 static void saverbank (int bank, iCode *ic, bool pushPsw)
2568 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2574 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2575 if (options.useXstack) {
2578 r = getFreePtr(ic,&aop,FALSE);
2579 pic14_emitcode("mov","%s,_spx",r->name);
2583 for (i = 0 ; i < pic14_nRegs ;i++) {
2584 if (options.useXstack) {
2585 pic14_emitcode("inc","%s",r->name);
2586 //pic14_emitcode("mov","a,(%s+%d)",
2587 // regspic14[i].base,8*bank+regspic14[i].offset);
2588 pic14_emitcode("movx","@%s,a",r->name);
2590 pic14_emitcode("push","");// "(%s+%d)",
2591 //regspic14[i].base,8*bank+regspic14[i].offset);
2595 if (options.useXstack) {
2596 pic14_emitcode("mov","a,psw");
2597 pic14_emitcode("movx","@%s,a",r->name);
2598 pic14_emitcode("inc","%s",r->name);
2599 pic14_emitcode("mov","_spx,%s",r->name);
2600 freeAsmop (NULL,aop,ic,TRUE);
2603 pic14_emitcode("push","psw");
2605 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2611 /*-----------------------------------------------------------------*/
2612 /* genCall - generates a call statement */
2613 /*-----------------------------------------------------------------*/
2614 static void genCall (iCode *ic)
2623 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2625 /* if caller saves & we have not saved then */
2629 /* if we are calling a function that is not using
2630 the same register bank then we need to save the
2631 destination registers on the stack */
2632 dtype = operandType(IC_LEFT(ic));
2633 if (currFunc && dtype &&
2634 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2635 IFFUNC_ISISR(currFunc->type) &&
2638 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2640 /* if send set is not empty the assign */
2643 /* For the Pic port, there is no data stack.
2644 * So parameters passed to functions are stored
2645 * in registers. (The pCode optimizer will get
2646 * rid of most of these :).
2648 int psuedoStkPtr=-1;
2649 int firstTimeThruLoop = 1;
2651 _G.sendSet = reverseSet(_G.sendSet);
2653 /* First figure how many parameters are getting passed */
2654 for (sic = setFirstItem(_G.sendSet) ; sic ;
2655 sic = setNextItem(_G.sendSet)) {
2657 aopOp(IC_LEFT(sic),sic,FALSE);
2658 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2659 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2662 for (sic = setFirstItem(_G.sendSet) ; sic ;
2663 sic = setNextItem(_G.sendSet)) {
2664 int size, offset = 0;
2666 aopOp(IC_LEFT(sic),sic,FALSE);
2667 size = AOP_SIZE(IC_LEFT(sic));
2670 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2671 AopType(AOP_TYPE(IC_LEFT(sic))));
2673 if(!firstTimeThruLoop) {
2674 /* If this is not the first time we've been through the loop
2675 * then we need to save the parameter in a temporary
2676 * register. The last byte of the last parameter is
2678 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2681 firstTimeThruLoop=0;
2683 mov2w_op (IC_LEFT(sic), offset);
2686 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2691 sym = OP_SYMBOL(IC_LEFT(ic));
2692 name = sym->rname[0] ? sym->rname : sym->name;
2693 isExtern = IS_EXTERN(sym->etype);
2695 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2697 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2699 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2702 /* if we need assign a result value */
2703 if ((IS_ITEMP(IC_RESULT(ic)) &&
2704 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2705 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2706 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2709 aopOp(IC_RESULT(ic),ic,FALSE);
2712 assignResultValue(IC_RESULT(ic));
2714 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2715 AopType(AOP_TYPE(IC_RESULT(ic))));
2717 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2720 /* if register bank was saved then pop them */
2722 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2724 /* if we hade saved some registers then unsave them */
2725 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2726 unsaveRegisters (ic);
2731 /*-----------------------------------------------------------------*/
2732 /* genPcall - generates a call by pointer statement */
2733 /*-----------------------------------------------------------------*/
2734 static void genPcall (iCode *ic)
2737 symbol *albl = newiTempLabel(NULL);
2738 symbol *blbl = newiTempLabel(NULL);
2745 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2746 /* if caller saves & we have not saved then */
2750 /* if we are calling a function that is not using
2751 the same register bank then we need to save the
2752 destination registers on the stack */
2753 dtype = operandType(IC_LEFT(ic));
2754 if (currFunc && dtype &&
2755 IFFUNC_ISISR(currFunc->type) &&
2756 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2757 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2760 aopOp(left,ic,FALSE);
2761 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2763 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2765 pushSide(IC_LEFT(ic), FPTRSIZE);
2767 /* if send set is not empty, assign parameters */
2770 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2771 /* no way to pass args - W always gets used to make the call */
2773 /* first idea - factor out a common helper function and call it.
2774 But don't know how to get it generated only once in its own block
2776 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2779 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2780 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2781 buffer = Safe_calloc(1,strlen(rname)+16);
2782 sprintf(buffer, "%s_goto_helper", rname);
2783 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2787 emitpcode(POC_CALL,popGetLabel(albl->key));
2788 pcop = popGetLabel(blbl->key);
2789 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2790 emitpcode(POC_GOTO,pcop);
2791 emitpLabel(albl->key);
2793 emitpcode(poc,popGetAddr(AOP(left),1,0));
2794 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2795 emitpcode(poc,popGetAddr(AOP(left),0,0));
2796 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2798 emitpLabel(blbl->key);
2800 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2802 /* if we need to assign a result value */
2803 if ((IS_ITEMP(IC_RESULT(ic)) &&
2804 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2805 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2806 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2809 aopOp(IC_RESULT(ic),ic,FALSE);
2814 assignResultValue(IC_RESULT(ic));
2816 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2819 /* if register bank was saved then unsave them */
2820 if (currFunc && dtype &&
2821 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2822 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2824 /* if we hade saved some registers then
2827 unsaveRegisters (ic);
2831 /*-----------------------------------------------------------------*/
2832 /* resultRemat - result is rematerializable */
2833 /*-----------------------------------------------------------------*/
2834 static int resultRemat (iCode *ic)
2836 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2839 if (SKIP_IC(ic) || ic->op == IFX)
2842 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2843 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2844 if (sym->remat && !POINTER_SET(ic))
2851 #if defined(__BORLANDC__) || defined(_MSC_VER)
2852 #define STRCASECMP stricmp
2854 #define STRCASECMP strcasecmp
2858 /*-----------------------------------------------------------------*/
2859 /* inExcludeList - return 1 if the string is in exclude Reg list */
2860 /*-----------------------------------------------------------------*/
2861 static bool inExcludeList(char *s)
2863 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2866 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2867 if (options.excludeRegs[i] &&
2868 STRCASECMP(options.excludeRegs[i],"none") == 0)
2871 for ( i = 0 ; options.excludeRegs[i]; i++) {
2872 if (options.excludeRegs[i] &&
2873 STRCASECMP(s,options.excludeRegs[i]) == 0)
2880 /*-----------------------------------------------------------------*/
2881 /* genFunction - generated code for function entry */
2882 /*-----------------------------------------------------------------*/
2883 static void genFunction (iCode *ic)
2890 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2892 labelOffset += (max_key+4);
2896 /* create the function header */
2897 pic14_emitcode(";","-----------------------------------------");
2898 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2899 pic14_emitcode(";","-----------------------------------------");
2901 /* prevent this symbol from being emitted as 'extern' */
2902 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2904 pic14_emitcode("","%s:",sym->rname);
2905 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2907 ftype = operandType(IC_LEFT(ic));
2909 /* if critical function then turn interrupts off */
2910 if (IFFUNC_ISCRITICAL(ftype))
2911 pic14_emitcode("clr","ea");
2913 /* here we need to generate the equates for the
2914 register bank if required */
2916 if (FUNC_REGBANK(ftype) != rbank) {
2919 rbank = FUNC_REGBANK(ftype);
2920 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2921 if (strcmp(regspic14[i].base,"0") == 0)
2922 pic14_emitcode("","%s = 0x%02x",
2924 8*rbank+regspic14[i].offset);
2926 pic14_emitcode ("","%s = %s + 0x%02x",
2929 8*rbank+regspic14[i].offset);
2934 /* if this is an interrupt service routine */
2935 if (IFFUNC_ISISR(sym->type)) {
2936 /* already done in pic14createInterruptVect() - delete me
2937 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2938 emitpcodeNULLop(POC_NOP);
2939 emitpcodeNULLop(POC_NOP);
2940 emitpcodeNULLop(POC_NOP);
2942 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2943 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2944 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2945 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2946 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2947 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2948 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2950 pBlockConvert2ISR(pb);
2951 pic14_hasInterrupt = 1;
2953 if (!inExcludeList("acc"))
2954 pic14_emitcode ("push","acc");
2955 if (!inExcludeList("b"))
2956 pic14_emitcode ("push","b");
2957 if (!inExcludeList("dpl"))
2958 pic14_emitcode ("push","dpl");
2959 if (!inExcludeList("dph"))
2960 pic14_emitcode ("push","dph");
2961 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2963 pic14_emitcode ("push", "dpx");
2964 /* Make sure we're using standard DPTR */
2965 pic14_emitcode ("push", "dps");
2966 pic14_emitcode ("mov", "dps, #0x00");
2967 if (options.stack10bit)
2969 /* This ISR could conceivably use DPTR2. Better save it. */
2970 pic14_emitcode ("push", "dpl1");
2971 pic14_emitcode ("push", "dph1");
2972 pic14_emitcode ("push", "dpx1");
2975 /* if this isr has no bank i.e. is going to
2976 run with bank 0 , then we need to save more
2978 if (!FUNC_REGBANK(sym->type)) {
2980 /* if this function does not call any other
2981 function then we can be economical and
2982 save only those registers that are used */
2983 if (! IFFUNC_HASFCALL(sym->type)) {
2986 /* if any registers used */
2987 if (sym->regsUsed) {
2988 /* save the registers used */
2989 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2990 if (bitVectBitValue(sym->regsUsed,i) ||
2991 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2992 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2997 /* this function has a function call cannot
2998 determines register usage so we will have the
3000 saverbank(0,ic,FALSE);
3005 /* if callee-save to be used for this function
3006 then save the registers being used in this function */
3007 if (IFFUNC_CALLEESAVES(sym->type)) {
3010 /* if any registers used */
3011 if (sym->regsUsed) {
3012 /* save the registers used */
3013 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3014 if (bitVectBitValue(sym->regsUsed,i) ||
3015 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3016 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3024 /* set the register bank to the desired value */
3025 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3026 pic14_emitcode("push","psw");
3027 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3030 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3032 if (options.useXstack) {
3033 pic14_emitcode("mov","r0,%s",spname);
3034 pic14_emitcode("mov","a,_bp");
3035 pic14_emitcode("movx","@r0,a");
3036 pic14_emitcode("inc","%s",spname);
3040 /* set up the stack */
3041 pic14_emitcode ("push","_bp"); /* save the callers stack */
3043 pic14_emitcode ("mov","_bp,%s",spname);
3046 /* adjust the stack for the function */
3051 werror(W_STACK_OVERFLOW,sym->name);
3053 if (i > 3 && sym->recvSize < 4) {
3055 pic14_emitcode ("mov","a,sp");
3056 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3057 pic14_emitcode ("mov","sp,a");
3062 pic14_emitcode("inc","sp");
3067 pic14_emitcode ("mov","a,_spx");
3068 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3069 pic14_emitcode ("mov","_spx,a");
3074 /*-----------------------------------------------------------------*/
3075 /* genEndFunction - generates epilogue for functions */
3076 /*-----------------------------------------------------------------*/
3077 static void genEndFunction (iCode *ic)
3079 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3083 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3085 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3087 pic14_emitcode ("mov","%s,_bp",spname);
3090 /* if use external stack but some variables were
3091 added to the local stack then decrement the
3093 if (options.useXstack && sym->stack) {
3094 pic14_emitcode("mov","a,sp");
3095 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3096 pic14_emitcode("mov","sp,a");
3100 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3101 if (options.useXstack) {
3102 pic14_emitcode("mov","r0,%s",spname);
3103 pic14_emitcode("movx","a,@r0");
3104 pic14_emitcode("mov","_bp,a");
3105 pic14_emitcode("dec","%s",spname);
3109 pic14_emitcode ("pop","_bp");
3113 /* restore the register bank */
3114 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3115 pic14_emitcode ("pop","psw");
3117 if (IFFUNC_ISISR(sym->type)) {
3119 /* now we need to restore the registers */
3120 /* if this isr has no bank i.e. is going to
3121 run with bank 0 , then we need to save more
3123 if (!FUNC_REGBANK(sym->type)) {
3125 /* if this function does not call any other
3126 function then we can be economical and
3127 save only those registers that are used */
3128 if (! IFFUNC_HASFCALL(sym->type)) {
3131 /* if any registers used */
3132 if (sym->regsUsed) {
3133 /* save the registers used */
3134 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3135 if (bitVectBitValue(sym->regsUsed,i) ||
3136 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3137 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3142 /* this function has a function call cannot
3143 determines register usage so we will have the
3145 unsaverbank(0,ic,FALSE);
3149 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3151 if (options.stack10bit)
3153 pic14_emitcode ("pop", "dpx1");
3154 pic14_emitcode ("pop", "dph1");
3155 pic14_emitcode ("pop", "dpl1");
3157 pic14_emitcode ("pop", "dps");
3158 pic14_emitcode ("pop", "dpx");
3160 if (!inExcludeList("dph"))
3161 pic14_emitcode ("pop","dph");
3162 if (!inExcludeList("dpl"))
3163 pic14_emitcode ("pop","dpl");
3164 if (!inExcludeList("b"))
3165 pic14_emitcode ("pop","b");
3166 if (!inExcludeList("acc"))
3167 pic14_emitcode ("pop","acc");
3169 if (IFFUNC_ISCRITICAL(sym->type))
3170 pic14_emitcode("setb","ea");
3173 /* if debug then send end of function */
3174 /* if (options.debug && currFunc) { */
3176 debugFile->writeEndFunction (currFunc, ic, 1);
3179 pic14_emitcode ("reti","");
3180 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3181 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3182 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3183 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3184 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3185 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3186 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3187 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3188 emitpcodeNULLop(POC_RETFIE);
3191 if (IFFUNC_ISCRITICAL(sym->type))
3192 pic14_emitcode("setb","ea");
3194 if (IFFUNC_CALLEESAVES(sym->type)) {
3197 /* if any registers used */
3198 if (sym->regsUsed) {
3199 /* save the registers used */
3200 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3201 if (bitVectBitValue(sym->regsUsed,i) ||
3202 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3203 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3209 /* if debug then send end of function */
3211 debugFile->writeEndFunction (currFunc, ic, 1);
3214 pic14_emitcode ("return","");
3215 emitpcodeNULLop(POC_RETURN);
3217 /* Mark the end of a function */
3218 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3223 /*-----------------------------------------------------------------*/
3224 /* genRet - generate code for return statement */
3225 /*-----------------------------------------------------------------*/
3226 static void genRet (iCode *ic)
3228 int size,offset = 0;
3232 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3233 /* if we have no return value then
3234 just generate the "ret" */
3238 /* we have something to return then
3239 move the return value into place */
3240 aopOp(IC_LEFT(ic),ic,FALSE);
3241 size = AOP_SIZE(IC_LEFT(ic));
3243 for (offset = 0; offset < size; offset++)
3245 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3248 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3251 /* generate a jump to the return label
3252 if the next is not the return statement */
3253 if (!(ic->next && ic->next->op == LABEL &&
3254 IC_LABEL(ic->next) == returnLabel)) {
3256 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3261 /*-----------------------------------------------------------------*/
3262 /* genLabel - generates a label */
3263 /*-----------------------------------------------------------------*/
3264 static void genLabel (iCode *ic)
3268 /* special case never generate */
3269 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3270 if (IC_LABEL(ic) == entryLabel)
3273 emitpLabel(IC_LABEL(ic)->key);
3274 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3277 /*-----------------------------------------------------------------*/
3278 /* genGoto - generates a goto */
3279 /*-----------------------------------------------------------------*/
3281 static void genGoto (iCode *ic)
3285 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3286 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3290 /*-----------------------------------------------------------------*/
3291 /* genMultbits :- multiplication of bits */
3292 /*-----------------------------------------------------------------*/
3293 static void genMultbits (operand *left,
3298 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3300 if(!pic14_sameRegs(AOP(result),AOP(right)))
3301 emitpcode(POC_BSF, popGet(AOP(result),0));
3303 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3304 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3305 emitpcode(POC_BCF, popGet(AOP(result),0));
3310 /*-----------------------------------------------------------------*/
3311 /* genMultOneByte : 8 bit multiplication & division */
3312 /*-----------------------------------------------------------------*/
3313 static void genMultOneByte (operand *left,
3317 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3325 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3326 DEBUGpic14_AopType(__LINE__,left,right,result);
3327 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3329 /* (if two literals, the value is computed before) */
3330 /* if one literal, literal on the right */
3331 if (AOP_TYPE(left) == AOP_LIT){
3337 assert (AOP_SIZE(left) == AOP_SIZE(right));
3339 size = min(AOP_SIZE(result),AOP_SIZE(left));
3340 offset = Gstack_base_addr - (2*size - 1);
3342 /* pass right operand as argument */
3343 for (i=0; i < size; i++)
3345 mov2w (AOP(right), i);
3346 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3349 /* pass left operand as argument */
3350 for (i=0; i < size; i++)
3352 mov2w (AOP(left), i);
3353 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3355 assert (offset == Gstack_base_addr);
3357 /* call library routine */
3358 assert (size > 0 && size <= 4);
3359 call_libraryfunc (func[size]);
3362 movwf (AOP(result), size-1);
3363 for (i=0; i < size - 1; i++)
3365 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3366 movwf (AOP(result), size - 2 - i);
3369 /* now (zero-/sign) extend the result to its size */
3370 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3373 /*-----------------------------------------------------------------*/
3374 /* genMult - generates code for multiplication */
3375 /*-----------------------------------------------------------------*/
3376 static void genMult (iCode *ic)
3378 operand *left = IC_LEFT(ic);
3379 operand *right = IC_RIGHT(ic);
3380 operand *result= IC_RESULT(ic);
3384 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3385 /* assign the amsops */
3386 aopOp (left,ic,FALSE);
3387 aopOp (right,ic,FALSE);
3388 aopOp (result,ic,TRUE);
3390 DEBUGpic14_AopType(__LINE__,left,right,result);
3392 /* special cases first */
3394 if (AOP_TYPE(left) == AOP_CRY &&
3395 AOP_TYPE(right)== AOP_CRY) {
3396 genMultbits(left,right,result);
3400 /* if both are of size == 1 */
3401 if (AOP_SIZE(left) == 1 &&
3402 AOP_SIZE(right) == 1 ) {
3403 genMultOneByte(left,right,result);
3407 /* should have been converted to function call */
3411 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3412 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3413 freeAsmop(result,NULL,ic,TRUE);
3416 /*-----------------------------------------------------------------*/
3417 /* genDivbits :- division of bits */
3418 /*-----------------------------------------------------------------*/
3419 static void genDivbits (operand *left,
3428 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3429 /* the result must be bit */
3430 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3431 l = aopGet(AOP(left),0,FALSE,FALSE);
3435 pic14_emitcode("div","ab");
3436 pic14_emitcode("rrc","a");
3437 aopPut(AOP(result),"c",0);
3440 /*-----------------------------------------------------------------*/
3441 /* genDivOneByte : 8 bit division */
3442 /*-----------------------------------------------------------------*/
3443 static void genDivOneByte (operand *left,
3450 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3452 assert (AOP_SIZE(result) == 1);
3453 assert (AOP_SIZE(right) == 1);
3454 assert (AOP_SIZE(left) == 1);
3456 size = min(AOP_SIZE(result),AOP_SIZE(left));
3458 if (AOP_TYPE(right) == AOP_LIT)
3460 /* XXX: might add specialized code */
3463 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3465 /* unsigned division */
3467 mov2w(AOP(right),0);
3468 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3470 call_libraryfunc("__divuchar");
3471 movwf(AOP(result),0);
3476 temp = popGetTempReg();
3477 lbl = newiTempLabel(NULL);
3479 /* XXX: improve this naive approach:
3480 [result] = [a] / [b]
3481 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3485 movwf temp // temp <-- left
3486 movf right,W // W <-- right
3490 subwf temp,F // temp <-- temp - W
3491 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3493 decf result // we just subtract once too often
3496 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3497 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3500 emitpcode(POC_MOVWF, temp);
3501 mov2w(AOP(right),0);
3502 emitpcode(POC_CLRF, popGet(AOP(result),0));
3504 emitpLabel(lbl->key);
3505 emitpcode(POC_INCF, popGet(AOP(result),0));
3506 emitpcode(POC_SUBWF, temp);
3508 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3509 emitpcode(POC_DECF, popGet(AOP(result),0));
3514 /* signed division */
3515 mov2w(AOP(right),0);
3516 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3518 call_libraryfunc("__divschar");
3519 movwf(AOP(result),0);
3522 /* now performed the signed/unsigned division -- extend result */
3523 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3526 /*-----------------------------------------------------------------*/
3527 /* genDiv - generates code for division */
3528 /*-----------------------------------------------------------------*/
3529 static void genDiv (iCode *ic)
3531 operand *left = IC_LEFT(ic);
3532 operand *right = IC_RIGHT(ic);
3533 operand *result= IC_RESULT(ic);
3536 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3537 /* assign the amsops */
3538 aopOp (left,ic,FALSE);
3539 aopOp (right,ic,FALSE);
3540 aopOp (result,ic,TRUE);
3542 /* special cases first */
3544 if (AOP_TYPE(left) == AOP_CRY &&
3545 AOP_TYPE(right)== AOP_CRY) {
3546 genDivbits(left,right,result);
3550 /* if both are of size == 1 */
3551 if (AOP_SIZE(left) == 1 &&
3552 AOP_SIZE(right) == 1 ) {
3553 genDivOneByte(left,right,result);
3557 /* should have been converted to function call */
3560 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3561 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3562 freeAsmop(result,NULL,ic,TRUE);
3565 /*-----------------------------------------------------------------*/
3566 /* genModbits :- modulus of bits */
3567 /*-----------------------------------------------------------------*/
3568 static void genModbits (operand *left,
3576 /* the result must be bit */
3577 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3578 l = aopGet(AOP(left),0,FALSE,FALSE);
3582 pic14_emitcode("div","ab");
3583 pic14_emitcode("mov","a,b");
3584 pic14_emitcode("rrc","a");
3585 aopPut(AOP(result),"c",0);
3588 /*-----------------------------------------------------------------*/
3589 /* genModOneByte : 8 bit modulus */
3590 /*-----------------------------------------------------------------*/
3591 static void genModOneByte (operand *left,
3598 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3600 assert (AOP_SIZE(result) == 1);
3601 assert (AOP_SIZE(right) == 1);
3602 assert (AOP_SIZE(left) == 1);
3604 size = min(AOP_SIZE(result),AOP_SIZE(left));
3606 if (AOP_TYPE(right) == AOP_LIT)
3608 /* XXX: might add specialized code */
3611 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3613 /* unsigned division */
3615 mov2w(AOP(right),0);
3616 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3618 call_libraryfunc("__moduchar");
3619 movwf(AOP(result),0);
3624 lbl = newiTempLabel(NULL);
3626 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3628 /* XXX: improve this naive approach:
3629 [result] = [a] % [b]
3630 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3634 movwf result // result <-- left
3635 movf right,W // W <-- right
3637 subwf result,F // result <-- result - W
3638 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3640 addwf result, F // we just subtract once too often
3643 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3644 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3646 if (!pic14_sameRegs(AOP(left), AOP(result)))
3649 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3651 mov2w(AOP(right),0);
3653 emitpLabel(lbl->key);
3654 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3656 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3657 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3662 /* signed division */
3663 mov2w(AOP(right),0);
3664 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3666 call_libraryfunc("__modschar");
3667 movwf(AOP(result),0);
3670 /* now we performed the signed/unsigned modulus -- extend result */
3671 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3674 /*-----------------------------------------------------------------*/
3675 /* genMod - generates code for division */
3676 /*-----------------------------------------------------------------*/
3677 static void genMod (iCode *ic)
3679 operand *left = IC_LEFT(ic);
3680 operand *right = IC_RIGHT(ic);
3681 operand *result= IC_RESULT(ic);
3684 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3685 /* assign the amsops */
3686 aopOp (left,ic,FALSE);
3687 aopOp (right,ic,FALSE);
3688 aopOp (result,ic,TRUE);
3690 /* special cases first */
3692 if (AOP_TYPE(left) == AOP_CRY &&
3693 AOP_TYPE(right)== AOP_CRY) {
3694 genModbits(left,right,result);
3698 /* if both are of size == 1 */
3699 if (AOP_SIZE(left) == 1 &&
3700 AOP_SIZE(right) == 1 ) {
3701 genModOneByte(left,right,result);
3705 /* should have been converted to function call */
3709 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3710 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3711 freeAsmop(result,NULL,ic,TRUE);
3714 /*-----------------------------------------------------------------*/
3715 /* genIfxJump :- will create a jump depending on the ifx */
3716 /*-----------------------------------------------------------------*/
3718 note: May need to add parameter to indicate when a variable is in bit space.
3720 static void genIfxJump (iCode *ic, char *jval)
3724 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3725 /* if true label then we jump if condition
3727 if ( IC_TRUE(ic) ) {
3729 if(strcmp(jval,"a") == 0)
3731 else if (strcmp(jval,"c") == 0)
3734 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3735 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3738 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3739 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3743 /* false label is present */
3744 if(strcmp(jval,"a") == 0)
3746 else if (strcmp(jval,"c") == 0)
3749 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3750 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3753 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3754 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3759 /* mark the icode as generated */
3764 /*-----------------------------------------------------------------*/
3766 /*-----------------------------------------------------------------*/
3767 static void genSkip(iCode *ifx,int status_bit)
3773 if ( IC_TRUE(ifx) ) {
3774 switch(status_bit) {
3789 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3790 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3794 switch(status_bit) {
3808 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3809 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3816 /*-----------------------------------------------------------------*/
3818 /*-----------------------------------------------------------------*/
3819 static void genSkipc(resolvedIfx *rifx)
3830 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3831 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3832 rifx->generated = 1;
3836 /*-----------------------------------------------------------------*/
3838 /*-----------------------------------------------------------------*/
3839 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3845 if( (rifx->condition ^ invert_condition) & 1)
3850 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3851 rifx->generated = 1;
3856 /*-----------------------------------------------------------------*/
3858 /*-----------------------------------------------------------------*/
3859 static void genSkipz(iCode *ifx, int condition)
3862 assert (ifx != NULL);
3870 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3872 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3875 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3877 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3883 /*-----------------------------------------------------------------*/
3885 /*-----------------------------------------------------------------*/
3886 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3893 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3895 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3898 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3899 rifx->generated = 1;
3904 /*-----------------------------------------------------------------*/
3905 /* genChkZeroes :- greater or less than comparison */
3906 /* For each byte in a literal that is zero, inclusive or the */
3907 /* the corresponding byte in the operand with W */
3908 /* returns true if any of the bytes are zero */
3909 /*-----------------------------------------------------------------*/
3910 static int genChkZeroes(operand *op, int lit, int size)
3917 i = (lit >> (size*8)) & 0xff;
3921 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3923 emitpcode(POC_IORFW, popGet(AOP(op),size));
3933 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3934 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3935 #define DEBUGpc emitpComment
3937 /*-----------------------------------------------------------------*/
3938 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3939 /* aop (if it's NOT a literal) or from lit (if */
3940 /* aop is a literal) */
3941 /*-----------------------------------------------------------------*/
3942 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3943 if (aop->type == AOP_LIT) {
3944 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3946 emitpcode (POC_MOVFW, popGet (aop, offset));
3950 /* genCmp performs a left < right comparison, stores
3951 * the outcome in result (if != NULL) and generates
3952 * control flow code for the ifx (if != NULL).
3954 * This version leaves in sequences like
3955 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3956 * which should be optmized by the peephole
3957 * optimizer - RN 2005-01-01 */
3958 static void genCmp (operand *left,operand *right,
3959 operand *result, iCode *ifx, int sign)
3969 int invert_result = 0;
3973 assert (AOP_SIZE(left) == AOP_SIZE(right));
3974 assert (left && right);
3976 size = AOP_SIZE(right) - 1;
3977 mask = (0x100UL << (size*8)) - 1;
3978 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3983 resolveIfx (&rIfx, ifx);
3985 /**********************************************************************
3986 * handle bits - bit compares are promoted to int compares seemingly! *
3987 **********************************************************************/
3989 // THIS IS COMPLETELY UNTESTED!
3990 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3991 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3992 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3993 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3996 // 1 < {0,1} is false --> clear C by skipping the next instruction
3997 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3998 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3999 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4000 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4001 emitCLRC; // only skipped for left=0 && right=1
4003 goto correct_result_in_carry;
4007 /*************************************************
4008 * make sure that left is register (or the like) *
4009 *************************************************/
4010 if (!isAOP_REGlike(left)) {
4011 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4012 assert (isAOP_LIT(left));
4013 assert (isAOP_REGlike(right));
4014 // swap left and right
4015 // left < right <==> right > left <==> (right >= left + 1)
4016 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4018 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4019 // MAXVALUE < right? always false
4020 if (performedLt) emitCLRC; else emitSETC;
4021 goto correct_result_in_carry;
4024 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4025 // that's why we handled it above.
4032 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4033 } else if (isAOP_LIT(right)) {
4034 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4037 assert (isAOP_REGlike(left)); // left must be register or the like
4038 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4040 /*************************************************
4041 * special cases go here *
4042 *************************************************/
4044 if (isAOP_LIT(right)) {
4046 // unsigned comparison to a literal
4047 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4049 // unsigned left < 0? always false
4050 if (performedLt) emitCLRC; else emitSETC;
4051 goto correct_result_in_carry;
4054 // signed comparison to a literal
4055 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4056 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4057 // signed left < 0x80000000? always false
4058 if (performedLt) emitCLRC; else emitSETC;
4059 goto correct_result_in_carry;
4060 } else if (lit == 0) {
4061 // compare left < 0; set CARRY if SIGNBIT(left) is set
4062 if (performedLt) emitSETC; else emitCLRC;
4063 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4064 if (performedLt) emitCLRC; else emitSETC;
4065 goto correct_result_in_carry;
4068 } // right is literal
4070 /*************************************************
4071 * perform a general case comparison *
4072 * make sure we get CARRY==1 <==> left >= right *
4073 *************************************************/
4074 // compare most significant bytes
4075 //DEBUGpc ("comparing bytes at offset %d", size);
4077 // unsigned comparison
4078 pic14_mov2w_regOrLit (AOP(right), lit, size);
4079 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4081 // signed comparison
4082 // (add 2^n to both operands then perform an unsigned comparison)
4083 if (isAOP_LIT(right)) {
4084 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4085 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4087 if (litbyte == 0x80) {
4088 // left >= 0x80 -- always true, but more bytes to come
4089 mov2w (AOP(left), size);
4090 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4093 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4094 mov2w (AOP(left), size);
4095 emitpcode (POC_ADDLW, popGetLit (0x80));
4096 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4099 pCodeOp *pctemp = popGetTempReg();
4100 mov2w (AOP(left), size);
4101 emitpcode (POC_ADDLW, popGetLit (0x80));
4102 emitpcode (POC_MOVWF, pctemp);
4103 mov2w (AOP(right), size);
4104 emitpcode (POC_ADDLW, popGetLit (0x80));
4105 emitpcode (POC_SUBFW, pctemp);
4106 popReleaseTempReg(pctemp);
4110 // compare remaining bytes (treat as unsigned case from above)
4111 templbl = newiTempLabel ( NULL );
4114 //DEBUGpc ("comparing bytes at offset %d", offs);
4116 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4117 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4118 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4120 emitpLabel (templbl->key);
4121 goto result_in_carry;
4125 /****************************************************
4126 * now CARRY contains the result of the comparison: *
4127 * SUBWF sets CARRY iff *
4128 * F-W >= 0 <==> F >= W <==> !(F < W) *
4129 * (F=left, W=right) *
4130 ****************************************************/
4134 // value will be used in the following genSkipc()
4135 rIfx.condition ^= 1;
4138 correct_result_in_carry:
4140 // assign result to variable (if neccessary)
4141 if (result && AOP_TYPE(result) != AOP_CRY) {
4142 //DEBUGpc ("assign result");
4143 size = AOP_SIZE(result);
4145 emitpcode (POC_CLRF, popGet (AOP(result), size));
4147 if (invert_result) {
4149 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4151 emitpcode (POC_RLF, popGet (AOP(result), 0));
4155 // perform conditional jump
4157 //DEBUGpc ("generate control flow");
4165 /* OLD VERSION -- BUGGY, DO NOT USE */
4167 /*-----------------------------------------------------------------*/
4168 /* genCmp :- greater or less than comparison */
4169 /*-----------------------------------------------------------------*/
4170 static void genCmp (operand *left,operand *right,
4171 operand *result, iCode *ifx, int sign)
4173 int size; //, offset = 0 ;
4174 unsigned long lit = 0L,i = 0;
4175 resolvedIfx rFalseIfx;
4176 // resolvedIfx rTrueIfx;
4180 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4183 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4184 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4188 resolveIfx(&rFalseIfx,ifx);
4189 truelbl = newiTempLabel(NULL);
4190 size = max(AOP_SIZE(left),AOP_SIZE(right));
4192 DEBUGpic14_AopType(__LINE__,left,right,result);
4196 /* if literal is on the right then swap with left */
4197 if ((AOP_TYPE(right) == AOP_LIT)) {
4198 operand *tmp = right ;
4199 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4200 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4203 lit = (lit - 1) & mask;
4206 rFalseIfx.condition ^= 1;
4209 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4210 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4214 //if(IC_TRUE(ifx) == NULL)
4215 /* if left & right are bit variables */
4216 if (AOP_TYPE(left) == AOP_CRY &&
4217 AOP_TYPE(right) == AOP_CRY ) {
4218 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4219 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4221 /* subtract right from left if at the
4222 end the carry flag is set then we know that
4223 left is greater than right */
4225 symbol *lbl = newiTempLabel(NULL);
4228 if(AOP_TYPE(right) == AOP_LIT) {
4230 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4232 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4239 genSkipCond(&rFalseIfx,left,size-1,7);
4241 /* no need to compare to 0...*/
4242 /* NOTE: this is a de-generate compare that most certainly
4243 * creates some dead code. */
4244 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4246 if(ifx) ifx->generated = 1;
4253 //i = (lit >> (size*8)) & 0xff;
4254 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4256 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4258 i = ((0-lit) & 0xff);
4261 /* lit is 0x7f, all signed chars are less than
4262 * this except for 0x7f itself */
4263 emitpcode(POC_XORLW, popGetLit(0x7f));
4264 genSkipz2(&rFalseIfx,0);
4266 emitpcode(POC_ADDLW, popGetLit(0x80));
4267 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4268 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4273 genSkipz2(&rFalseIfx,1);
4275 emitpcode(POC_ADDLW, popGetLit(i));
4276 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4280 if(ifx) ifx->generated = 1;
4284 /* chars are out of the way. now do ints and longs */
4287 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4294 genSkipCond(&rFalseIfx,left,size,7);
4295 if(ifx) ifx->generated = 1;
4300 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4302 //rFalseIfx.condition ^= 1;
4303 //genSkipCond(&rFalseIfx,left,size,7);
4304 //rFalseIfx.condition ^= 1;
4306 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4307 if(rFalseIfx.condition)
4308 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4310 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4312 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4313 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4314 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4317 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4319 if(rFalseIfx.condition) {
4321 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4327 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4328 emitpLabel(truelbl->key);
4329 if(ifx) ifx->generated = 1;
4336 if( (lit & 0xff) == 0) {
4337 /* lower byte is zero */
4338 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4339 i = ((lit >> 8) & 0xff) ^0x80;
4340 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4341 emitpcode(POC_ADDLW, popGetLit( 0x80));
4342 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4343 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4346 if(ifx) ifx->generated = 1;
4351 /* Special cases for signed longs */
4352 if( (lit & 0xffffff) == 0) {
4353 /* lower byte is zero */
4354 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4355 i = ((lit >> 8*3) & 0xff) ^0x80;
4356 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4357 emitpcode(POC_ADDLW, popGetLit( 0x80));
4358 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4359 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4362 if(ifx) ifx->generated = 1;
4370 if(lit & (0x80 << (size*8))) {
4371 /* lit is negative */
4372 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4374 //genSkipCond(&rFalseIfx,left,size,7);
4376 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4378 if(rFalseIfx.condition)
4379 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4381 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4385 /* lit is positive */
4386 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4387 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4388 if(rFalseIfx.condition)
4389 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4391 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4395 /* There are no more special cases, so perform a general compare */
4397 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4398 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4402 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4404 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4406 //rFalseIfx.condition ^= 1;
4407 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4409 emitpLabel(truelbl->key);
4411 if(ifx) ifx->generated = 1;
4418 /* sign is out of the way. So now do an unsigned compare */
4419 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4422 /* General case - compare to an unsigned literal on the right.*/
4424 i = (lit >> (size*8)) & 0xff;
4425 emitpcode(POC_MOVLW, popGetLit(i));
4426 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4428 i = (lit >> (size*8)) & 0xff;
4431 emitpcode(POC_MOVLW, popGetLit(i));
4433 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4435 /* this byte of the lit is zero,
4436 *if it's not the last then OR in the variable */
4438 emitpcode(POC_IORFW, popGet(AOP(left),size));
4443 emitpLabel(lbl->key);
4444 //if(emitFinalCheck)
4445 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4447 emitpLabel(truelbl->key);
4449 if(ifx) ifx->generated = 1;
4456 if(AOP_TYPE(left) == AOP_LIT) {
4457 //symbol *lbl = newiTempLabel(NULL);
4459 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4462 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4465 if((lit == 0) && (sign == 0)){
4468 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4470 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4472 genSkipz2(&rFalseIfx,0);
4473 if(ifx) ifx->generated = 1;
4480 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4481 /* degenerate compare can never be true */
4482 if(rFalseIfx.condition == 0)
4483 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4485 if(ifx) ifx->generated = 1;
4490 /* signed comparisons to a literal byte */
4492 int lp1 = (lit+1) & 0xff;
4494 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4497 rFalseIfx.condition ^= 1;
4498 genSkipCond(&rFalseIfx,right,0,7);
4501 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4502 emitpcode(POC_XORLW, popGetLit(0x7f));
4503 genSkipz2(&rFalseIfx,1);
4506 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4507 emitpcode(POC_ADDLW, popGetLit(0x80));
4508 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4509 rFalseIfx.condition ^= 1;
4510 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4513 if(ifx) ifx->generated = 1;
4515 /* unsigned comparisons to a literal byte */
4517 switch(lit & 0xff ) {
4519 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4520 genSkipz2(&rFalseIfx,0);
4521 if(ifx) ifx->generated = 1;
4524 genSkipCond(&rFalseIfx,right,0,7);
4525 if(ifx) ifx->generated = 1;
4529 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4530 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4531 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4532 rFalseIfx.condition ^= 1;
4533 if (AOP_TYPE(result) == AOP_CRY) {
4534 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4535 if(ifx) ifx->generated = 1;
4537 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4538 emitpcode(POC_CLRF, popGet(AOP(result),0));
4539 emitpcode(POC_RLF, popGet(AOP(result),0));
4540 emitpcode(POC_MOVLW, popGetLit(0x01));
4541 emitpcode(POC_XORWF, popGet(AOP(result),0));
4552 /* Size is greater than 1 */
4560 /* this means lit = 0xffffffff, or -1 */
4563 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4564 rFalseIfx.condition ^= 1;
4565 genSkipCond(&rFalseIfx,right,size,7);
4566 if(ifx) ifx->generated = 1;
4573 if(rFalseIfx.condition) {
4574 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4575 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4578 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4580 emitpcode(POC_IORFW, popGet(AOP(right),size));
4584 if(rFalseIfx.condition) {
4585 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4586 emitpLabel(truelbl->key);
4588 rFalseIfx.condition ^= 1;
4589 genSkipCond(&rFalseIfx,right,s,7);
4592 if(ifx) ifx->generated = 1;
4596 if((size == 1) && (0 == (lp1&0xff))) {
4597 /* lower byte of signed word is zero */
4598 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4599 i = ((lp1 >> 8) & 0xff) ^0x80;
4600 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4601 emitpcode(POC_ADDLW, popGetLit( 0x80));
4602 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4603 rFalseIfx.condition ^= 1;
4604 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4607 if(ifx) ifx->generated = 1;
4611 if(lit & (0x80 << (size*8))) {
4612 /* Lit is less than zero */
4613 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4614 //rFalseIfx.condition ^= 1;
4615 //genSkipCond(&rFalseIfx,left,size,7);
4616 //rFalseIfx.condition ^= 1;
4617 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4618 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4620 if(rFalseIfx.condition)
4621 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4623 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4627 /* Lit is greater than or equal to zero */
4628 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4629 //rFalseIfx.condition ^= 1;
4630 //genSkipCond(&rFalseIfx,right,size,7);
4631 //rFalseIfx.condition ^= 1;
4633 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4634 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4636 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4637 if(rFalseIfx.condition)
4638 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4640 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4645 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4646 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4650 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4652 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4654 rFalseIfx.condition ^= 1;
4655 //rFalseIfx.condition = 1;
4656 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4658 emitpLabel(truelbl->key);
4660 if(ifx) ifx->generated = 1;
4665 /* compare word or long to an unsigned literal on the right.*/
4670 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4673 break; /* handled above */
4676 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4678 emitpcode(POC_IORFW, popGet(AOP(right),size));
4679 genSkipz2(&rFalseIfx,0);
4683 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4685 emitpcode(POC_IORFW, popGet(AOP(right),size));
4688 if(rFalseIfx.condition)
4689 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4691 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4694 emitpcode(POC_MOVLW, popGetLit(lit+1));
4695 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4697 rFalseIfx.condition ^= 1;
4698 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4701 emitpLabel(truelbl->key);
4703 if(ifx) ifx->generated = 1;
4709 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4710 i = (lit >> (size*8)) & 0xff;
4712 emitpcode(POC_MOVLW, popGetLit(i));
4713 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4716 i = (lit >> (size*8)) & 0xff;
4719 emitpcode(POC_MOVLW, popGetLit(i));
4721 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4723 /* this byte of the lit is zero,
4724 *if it's not the last then OR in the variable */
4726 emitpcode(POC_IORFW, popGet(AOP(right),size));
4731 emitpLabel(lbl->key);
4733 rFalseIfx.condition ^= 1;
4734 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4738 emitpLabel(truelbl->key);
4739 if(ifx) ifx->generated = 1;
4743 /* Compare two variables */
4745 DEBUGpic14_emitcode(";sign","%d",sign);
4749 /* Sigh. thus sucks... */
4751 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4752 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4753 emitpcode(POC_MOVLW, popGetLit(0x80));
4754 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4755 emitpcode(POC_XORFW, popGet(AOP(right),size));
4756 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4758 /* Signed char comparison */
4759 /* Special thanks to Nikolai Golovchenko for this snippet */
4760 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4761 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4762 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4763 emitpcode(POC_XORFW, popGet(AOP(left),0));
4764 emitpcode(POC_XORFW, popGet(AOP(right),0));
4765 emitpcode(POC_ADDLW, popGetLit(0x80));
4767 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4768 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4770 if(ifx) ifx->generated = 1;
4776 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4777 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4781 /* The rest of the bytes of a multi-byte compare */
4785 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4788 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4789 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4794 emitpLabel(lbl->key);
4796 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4797 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4798 (AOP_TYPE(result) == AOP_REG)) {
4799 emitpcode(POC_CLRF, popGet(AOP(result),0));
4800 emitpcode(POC_RLF, popGet(AOP(result),0));
4802 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4804 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4805 if(ifx) ifx->generated = 1;
4812 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4813 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4814 pic14_outBitC(result);
4816 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4817 /* if the result is used in the next
4818 ifx conditional branch then generate
4819 code a little differently */
4821 genIfxJump (ifx,"c");
4823 pic14_outBitC(result);
4824 /* leave the result in acc */
4830 /*-----------------------------------------------------------------*/
4831 /* genCmpGt :- greater than comparison */
4832 /*-----------------------------------------------------------------*/
4833 static void genCmpGt (iCode *ic, iCode *ifx)
4835 operand *left, *right, *result;
4836 sym_link *letype , *retype;
4840 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4842 right= IC_RIGHT(ic);
4843 result = IC_RESULT(ic);
4845 letype = getSpec(operandType(left));
4846 retype =getSpec(operandType(right));
4847 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4848 /* assign the amsops */
4849 aopOp (left,ic,FALSE);
4850 aopOp (right,ic,FALSE);
4851 aopOp (result,ic,TRUE);
4853 genCmp(right, left, result, ifx, sign);
4855 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4856 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4857 freeAsmop(result,NULL,ic,TRUE);
4860 /*-----------------------------------------------------------------*/
4861 /* genCmpLt - less than comparisons */
4862 /*-----------------------------------------------------------------*/
4863 static void genCmpLt (iCode *ic, iCode *ifx)
4865 operand *left, *right, *result;
4866 sym_link *letype , *retype;
4870 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4872 right= IC_RIGHT(ic);
4873 result = IC_RESULT(ic);
4875 letype = getSpec(operandType(left));
4876 retype =getSpec(operandType(right));
4877 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4879 /* assign the amsops */
4880 aopOp (left,ic,FALSE);
4881 aopOp (right,ic,FALSE);
4882 aopOp (result,ic,TRUE);
4884 genCmp(left, right, result, ifx, sign);
4886 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4887 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4888 freeAsmop(result,NULL,ic,TRUE);
4892 /*-----------------------------------------------------------------*/
4893 /* genc16bit2lit - compare a 16 bit value to a literal */
4894 /*-----------------------------------------------------------------*/
4895 static void genc16bit2lit(operand *op, int lit, int offset)
4900 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4901 if( (lit&0xff) == 0)
4906 switch( BYTEofLONG(lit,i)) {
4908 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4911 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4914 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4917 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4918 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4923 switch( BYTEofLONG(lit,i)) {
4925 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4929 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4933 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4936 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4938 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4946 /*-----------------------------------------------------------------*/
4947 /* gencjneshort - compare and jump if not equal */
4948 /*-----------------------------------------------------------------*/
4949 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4951 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4956 //unsigned long lit = 0L;
4958 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4959 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4962 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4963 DEBUGpic14_AopType(__LINE__,left,right,result);
4965 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4966 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4967 if (AOP_SIZE(result)) {
4968 for (offset = 0; offset < AOP_SIZE(result); offset++)
4969 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4972 assert (AOP_SIZE(left) == AOP_SIZE(right));
4973 //resolveIfx(&rIfx,ifx);
4974 lbl = newiTempLabel (NULL);
4977 mov2w (AOP(right),size);
4978 emitpcode (POC_XORFW, popGet (AOP(left), size));
4982 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4985 emitpLabel (lbl->key);
4986 if (AOP_SIZE(result)) {
4988 emitpcode (POC_INCF, popGet (AOP(result), 0));
4991 genSkipz (ifx, NULL != IC_TRUE(ifx));
4998 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4999 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5000 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5001 for (offset=0; offset < AOP_SIZE(result); offset++)
5003 emitpcode (POC_CLRF, popGet (AOP(result), offset));
5008 /* if the left side is a literal or
5009 if the right is in a pointer register and left
5011 if ((AOP_TYPE(left) == AOP_LIT) ||
5012 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5017 if(AOP_TYPE(right) == AOP_LIT)
5018 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5020 /* if the right side is a literal then anything goes */
5021 if (AOP_TYPE(right) == AOP_LIT &&
5022 AOP_TYPE(left) != AOP_DIR ) {
5025 genc16bit2lit(left, lit, 0);
5027 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5033 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5034 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5036 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5040 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5048 /* if the right side is in a register or in direct space or
5049 if the left is a pointer register & right is not */
5050 else if (AOP_TYPE(right) == AOP_REG ||
5051 AOP_TYPE(right) == AOP_DIR ||
5052 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5053 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5054 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5055 int lbl_key = lbl->key;
5058 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5059 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5060 __FUNCTION__,__LINE__);
5064 /* switch(size) { */
5066 /* genc16bit2lit(left, lit, 0); */
5068 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5074 if((AOP_TYPE(left) == AOP_DIR) &&
5075 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5077 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5078 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5080 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5082 switch (lit & 0xff) {
5084 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5087 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5088 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5089 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5093 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5094 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5095 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5096 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5100 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5101 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5106 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5109 if(AOP_TYPE(result) == AOP_CRY) {
5110 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5115 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5117 /* fix me. probably need to check result size too */
5118 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5123 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5133 } else if(AOP_TYPE(right) == AOP_REG &&
5134 AOP_TYPE(left) != AOP_DIR){
5138 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5139 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5140 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5145 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5150 /* right is a pointer reg need both a & b */
5153 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5155 pic14_emitcode("mov","b,%s",l);
5156 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5157 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5162 emitpcode(POC_INCF,popGet(AOP(result),0));
5164 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5166 emitpLabel(lbl->key);
5168 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5177 /*-----------------------------------------------------------------*/
5178 /* gencjne - compare and jump if not equal */
5179 /*-----------------------------------------------------------------*/
5180 static void gencjne(operand *left, operand *right, iCode *ifx)
5182 symbol *tlbl = newiTempLabel(NULL);
5184 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5185 gencjneshort(left, right, lbl);
5187 pic14_emitcode("mov","a,%s",one);
5188 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5189 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5190 pic14_emitcode("clr","a");
5191 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5193 emitpLabel(lbl->key);
5194 emitpLabel(tlbl->key);
5199 /*-----------------------------------------------------------------*/
5200 /* genCmpEq - generates code for equal to */
5201 /*-----------------------------------------------------------------*/
5202 static void genCmpEq (iCode *ic, iCode *ifx)
5204 operand *left, *right, *result;
5206 symbol *false_label;
5209 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5212 DEBUGpic14_emitcode ("; ifx is non-null","");
5214 DEBUGpic14_emitcode ("; ifx is null","");
5216 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5217 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5218 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5220 DEBUGpic14_AopType(__LINE__,left,right,result);
5222 /* if literal, move literal to right */
5223 if (op_isLitLike (IC_LEFT(ic))) {
5224 operand *tmp = right ;
5230 if (ifx && !IC_TRUE(ifx))
5232 assert (IC_FALSE(ifx));
5233 false_label = IC_FALSE(ifx);
5236 size = min(AOP_SIZE(left),AOP_SIZE(right));
5237 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5238 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5240 /* assume left != right */
5243 for (i=0; i < AOP_SIZE(result); i++)
5245 emitpcode(POC_CLRF, popGet(AOP(result),i));
5249 if (AOP_TYPE(right) == AOP_LIT)
5251 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5253 size = AOP_SIZE(left);
5254 assert(!op_isLitLike(left));
5259 mov2w(AOP(left), 0);
5260 for (i=1; i < size; i++)
5261 emitpcode(POC_IORFW,popGet(AOP(left),i));
5262 /* now Z is set iff `left == right' */
5264 if (!false_label) false_label = newiTempLabel(NULL);
5265 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5269 for (i=0; i < size; i++)
5272 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5273 /* now Z is cleared if `left != right' */
5275 if (!false_label) false_label = newiTempLabel(NULL);
5276 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5283 /* right is no literal */
5286 for (i=0; i < size; i++)
5288 mov2w(AOP(right),i);
5289 emitpcode(POC_XORFW,popGet(AOP(left),i));
5290 /* now Z is cleared if `left != right' */
5292 if (!false_label) false_label = newiTempLabel(NULL);
5293 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5297 /* if we reach here, left == right */
5299 if (AOP_SIZE(result) > 0)
5301 emitpcode(POC_INCF, popGet(AOP(result),0));
5304 if (ifx && IC_TRUE(ifx))
5306 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5309 if (false_label && (!ifx || IC_TRUE(ifx)))
5310 emitpLabel(false_label->key);
5312 if (ifx) ifx->generated = 1;
5314 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5315 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5316 freeAsmop(result,NULL,ic,TRUE);
5319 /*-----------------------------------------------------------------*/
5320 /* ifxForOp - returns the icode containing the ifx for operand */
5321 /*-----------------------------------------------------------------*/
5322 static iCode *ifxForOp ( operand *op, iCode *ic )
5325 /* if true symbol then needs to be assigned */
5326 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5327 if (IS_TRUE_SYMOP(op))
5330 /* if this has register type condition and
5331 the next instruction is ifx with the same operand
5332 and live to of the operand is upto the ifx only then */
5334 ic->next->op == IFX &&
5335 IC_COND(ic->next)->key == op->key &&
5336 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5340 ic->next->op == IFX &&
5341 IC_COND(ic->next)->key == op->key) {
5342 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5346 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5348 ic->next->op == IFX)
5349 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5352 ic->next->op == IFX &&
5353 IC_COND(ic->next)->key == op->key) {
5354 DEBUGpic14_emitcode ("; "," key is okay");
5355 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5356 OP_SYMBOL(op)->liveTo,
5363 /*-----------------------------------------------------------------*/
5364 /* genAndOp - for && operation */
5365 /*-----------------------------------------------------------------*/
5366 static void genAndOp (iCode *ic)
5368 operand *left,*right, *result;
5372 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5373 /* note here that && operations that are in an
5374 if statement are taken away by backPatchLabels
5375 only those used in arthmetic operations remain */
5376 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5377 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5378 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5380 DEBUGpic14_AopType(__LINE__,left,right,result);
5382 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5383 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5384 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5386 /* if both are bit variables */
5387 /* if (AOP_TYPE(left) == AOP_CRY && */
5388 /* AOP_TYPE(right) == AOP_CRY ) { */
5389 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5390 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5391 /* pic14_outBitC(result); */
5393 /* tlbl = newiTempLabel(NULL); */
5394 /* pic14_toBoolean(left); */
5395 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5396 /* pic14_toBoolean(right); */
5397 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5398 /* pic14_outBitAcc(result); */
5401 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5402 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5403 freeAsmop(result,NULL,ic,TRUE);
5407 /*-----------------------------------------------------------------*/
5408 /* genOrOp - for || operation */
5409 /*-----------------------------------------------------------------*/
5412 modified this code, but it doesn't appear to ever get called
5415 static void genOrOp (iCode *ic)
5417 operand *left,*right, *result;
5421 /* note here that || operations that are in an
5422 if statement are taken away by backPatchLabels
5423 only those used in arthmetic operations remain */
5425 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5426 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5427 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5428 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5430 DEBUGpic14_AopType(__LINE__,left,right,result);
5432 for (i=0; i < AOP_SIZE(result); i++)
5434 emitpcode(POC_CLRF, popGet(AOP(result), i));
5437 tlbl = newiTempLabel(NULL);
5438 pic14_toBoolean(left);
5440 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5441 pic14_toBoolean(right);
5442 emitpLabel(tlbl->key);
5443 /* here Z is clear IFF `left || right' */
5445 emitpcode(POC_INCF, popGet(AOP(result), 0));
5447 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5448 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5449 freeAsmop(result,NULL,ic,TRUE);
5452 /*-----------------------------------------------------------------*/
5453 /* isLiteralBit - test if lit == 2^n */
5454 /*-----------------------------------------------------------------*/
5455 static int isLiteralBit(unsigned long lit)
5457 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5458 0x100L,0x200L,0x400L,0x800L,
5459 0x1000L,0x2000L,0x4000L,0x8000L,
5460 0x10000L,0x20000L,0x40000L,0x80000L,
5461 0x100000L,0x200000L,0x400000L,0x800000L,
5462 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5463 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5468 for(idx = 0; idx < 32; idx++)
5474 /*-----------------------------------------------------------------*/
5475 /* continueIfTrue - */
5476 /*-----------------------------------------------------------------*/
5477 static void continueIfTrue (iCode *ic)
5480 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5482 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5486 /*-----------------------------------------------------------------*/
5488 /*-----------------------------------------------------------------*/
5489 static void jumpIfTrue (iCode *ic)
5492 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5494 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5498 /*-----------------------------------------------------------------*/
5499 /* jmpTrueOrFalse - */
5500 /*-----------------------------------------------------------------*/
5501 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5504 // ugly but optimized by peephole
5505 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5507 symbol *nlbl = newiTempLabel(NULL);
5508 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5509 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5510 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5511 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5514 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5515 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5520 /*-----------------------------------------------------------------*/
5521 /* genAnd - code for and */
5522 /*-----------------------------------------------------------------*/
5523 static void genAnd (iCode *ic, iCode *ifx)
5525 operand *left, *right, *result;
5527 unsigned long lit = 0L;
5532 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5533 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5534 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5535 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5537 resolveIfx(&rIfx,ifx);
5539 /* if left is a literal & right is not then exchange them */
5540 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5541 AOP_NEEDSACC(left)) {
5542 operand *tmp = right ;
5547 /* if result = right then exchange them */
5548 if(pic14_sameRegs(AOP(result),AOP(right))){
5549 operand *tmp = right ;
5554 /* if right is bit then exchange them */
5555 if (AOP_TYPE(right) == AOP_CRY &&
5556 AOP_TYPE(left) != AOP_CRY){
5557 operand *tmp = right ;
5561 if(AOP_TYPE(right) == AOP_LIT)
5562 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5564 size = AOP_SIZE(result);
5566 DEBUGpic14_AopType(__LINE__,left,right,result);
5569 // result = bit & yy;
5570 if (AOP_TYPE(left) == AOP_CRY){
5571 // c = bit & literal;
5572 if(AOP_TYPE(right) == AOP_LIT){
5574 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5577 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5580 if(size && (AOP_TYPE(result) == AOP_CRY)){
5581 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5584 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5588 pic14_emitcode("clr","c");
5591 if (AOP_TYPE(right) == AOP_CRY){
5593 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5594 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5597 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5599 pic14_emitcode("rrc","a");
5600 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5606 pic14_outBitC(result);
5608 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5609 genIfxJump(ifx, "c");
5613 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5614 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5615 if((AOP_TYPE(right) == AOP_LIT) &&
5616 (AOP_TYPE(result) == AOP_CRY) &&
5617 (AOP_TYPE(left) != AOP_CRY)){
5618 int posbit = isLiteralBit(lit);
5622 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5625 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5630 while (posbit > 7) {
5634 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5635 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5636 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5643 symbol *tlbl = newiTempLabel(NULL);
5644 int sizel = AOP_SIZE(left);
5646 pic14_emitcode("setb","c");
5648 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5649 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5651 if((posbit = isLiteralBit(bytelit)) != 0)
5652 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5654 if(bytelit != 0x0FFL)
5655 pic14_emitcode("anl","a,%s",
5656 aopGet(AOP(right),offset,FALSE,TRUE));
5657 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5662 // bit = left & literal
5664 pic14_emitcode("clr","c");
5665 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5667 // if(left & literal)
5670 jmpTrueOrFalse(ifx, tlbl);
5674 pic14_outBitC(result);
5678 /* if left is same as result */
5679 if(pic14_sameRegs(AOP(result),AOP(left))){
5681 for(;size--; offset++,lit>>=8) {
5682 if(AOP_TYPE(right) == AOP_LIT){
5683 switch(lit & 0xff) {
5685 /* and'ing with 0 has clears the result */
5686 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5689 /* and'ing with 0xff is a nop when the result and left are the same */
5694 int p = my_powof2( (~lit) & 0xff );
5696 /* only one bit is set in the literal, so use a bcf instruction */
5697 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5700 if(know_W != (int)(lit&0xff))
5701 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5703 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5708 if (AOP_TYPE(left) == AOP_ACC) {
5709 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5711 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5712 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5719 // left & result in different registers
5720 if(AOP_TYPE(result) == AOP_CRY){
5722 // if(size), result in bit
5723 // if(!size && ifx), conditional oper: if(left & right)
5724 symbol *tlbl = newiTempLabel(NULL);
5725 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5727 pic14_emitcode("setb","c");
5729 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5730 pic14_emitcode("anl","a,%s",
5731 aopGet(AOP(left),offset,FALSE,FALSE));
5732 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5737 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5738 pic14_outBitC(result);
5740 jmpTrueOrFalse(ifx, tlbl);
5742 for(;(size--);offset++) {
5744 // result = left & right
5745 if(AOP_TYPE(right) == AOP_LIT){
5746 int t = (lit >> (offset*8)) & 0x0FFL;
5749 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5752 if(AOP_TYPE(left) != AOP_ACC) {
5753 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5755 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5758 if(AOP_TYPE(left) == AOP_ACC) {
5759 emitpcode(POC_ANDLW, popGetLit(t));
5761 emitpcode(POC_MOVLW, popGetLit(t));
5762 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5764 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5769 if (AOP_TYPE(left) == AOP_ACC) {
5770 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5772 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5773 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5775 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5781 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5782 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5783 freeAsmop(result,NULL,ic,TRUE);
5786 /*-----------------------------------------------------------------*/
5787 /* genOr - code for or */
5788 /*-----------------------------------------------------------------*/
5789 static void genOr (iCode *ic, iCode *ifx)
5791 operand *left, *right, *result;
5793 unsigned long lit = 0L;
5796 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5798 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5799 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5800 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5802 DEBUGpic14_AopType(__LINE__,left,right,result);
5804 /* if left is a literal & right is not then exchange them */
5805 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5806 AOP_NEEDSACC(left)) {
5807 operand *tmp = right ;
5812 /* if result = right then exchange them */
5813 if(pic14_sameRegs(AOP(result),AOP(right))){
5814 operand *tmp = right ;
5819 /* if right is bit then exchange them */
5820 if (AOP_TYPE(right) == AOP_CRY &&
5821 AOP_TYPE(left) != AOP_CRY){
5822 operand *tmp = right ;
5827 DEBUGpic14_AopType(__LINE__,left,right,result);
5829 if(AOP_TYPE(right) == AOP_LIT)
5830 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5832 size = AOP_SIZE(result);
5836 if (AOP_TYPE(left) == AOP_CRY){
5837 if(AOP_TYPE(right) == AOP_LIT){
5838 // c = bit & literal;
5840 // lit != 0 => result = 1
5841 if(AOP_TYPE(result) == AOP_CRY){
5843 emitpcode(POC_BSF, popGet(AOP(result),0));
5844 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5845 // AOP(result)->aopu.aop_dir,
5846 // AOP(result)->aopu.aop_dir);
5848 continueIfTrue(ifx);
5852 // lit == 0 => result = left
5853 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5855 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5858 if (AOP_TYPE(right) == AOP_CRY){
5859 if(pic14_sameRegs(AOP(result),AOP(left))){
5861 emitpcode(POC_BCF, popGet(AOP(result),0));
5862 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5863 emitpcode(POC_BSF, popGet(AOP(result),0));
5865 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5866 AOP(result)->aopu.aop_dir,
5867 AOP(result)->aopu.aop_dir);
5868 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5869 AOP(right)->aopu.aop_dir,
5870 AOP(right)->aopu.aop_dir);
5871 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5872 AOP(result)->aopu.aop_dir,
5873 AOP(result)->aopu.aop_dir);
5875 if( AOP_TYPE(result) == AOP_ACC) {
5876 emitpcode(POC_MOVLW, popGetLit(0));
5877 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5878 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5879 emitpcode(POC_MOVLW, popGetLit(1));
5883 emitpcode(POC_BCF, popGet(AOP(result),0));
5884 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5885 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5886 emitpcode(POC_BSF, popGet(AOP(result),0));
5888 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5889 AOP(result)->aopu.aop_dir,
5890 AOP(result)->aopu.aop_dir);
5891 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5892 AOP(right)->aopu.aop_dir,
5893 AOP(right)->aopu.aop_dir);
5894 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5895 AOP(left)->aopu.aop_dir,
5896 AOP(left)->aopu.aop_dir);
5897 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5898 AOP(result)->aopu.aop_dir,
5899 AOP(result)->aopu.aop_dir);
5904 symbol *tlbl = newiTempLabel(NULL);
5905 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5908 emitpcode(POC_BCF, popGet(AOP(result),0));
5909 if( AOP_TYPE(right) == AOP_ACC) {
5910 emitpcode(POC_IORLW, popGetLit(0));
5912 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5913 emitpcode(POC_BSF, popGet(AOP(result),0));
5918 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5919 pic14_emitcode(";XXX setb","c");
5920 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5921 AOP(left)->aopu.aop_dir,tlbl->key+100);
5922 pic14_toBoolean(right);
5923 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5924 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5925 jmpTrueOrFalse(ifx, tlbl);
5929 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5936 pic14_outBitC(result);
5938 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5939 genIfxJump(ifx, "c");
5943 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5944 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5945 if((AOP_TYPE(right) == AOP_LIT) &&
5946 (AOP_TYPE(result) == AOP_CRY) &&
5947 (AOP_TYPE(left) != AOP_CRY)){
5949 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5952 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5954 continueIfTrue(ifx);
5957 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5958 // lit = 0, result = boolean(left)
5960 pic14_emitcode(";XXX setb","c");
5961 pic14_toBoolean(right);
5963 symbol *tlbl = newiTempLabel(NULL);
5964 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5966 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5968 genIfxJump (ifx,"a");
5972 pic14_outBitC(result);
5976 /* if left is same as result */
5977 if(pic14_sameRegs(AOP(result),AOP(left))){
5979 for(;size--; offset++,lit>>=8) {
5980 if(AOP_TYPE(right) == AOP_LIT){
5981 if((lit & 0xff) == 0)
5982 /* or'ing with 0 has no effect */
5985 int p = my_powof2(lit & 0xff);
5987 /* only one bit is set in the literal, so use a bsf instruction */
5989 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5991 if(know_W != (int)(lit & 0xff))
5992 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5993 know_W = lit & 0xff;
5994 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5999 if (AOP_TYPE(left) == AOP_ACC) {
6000 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6001 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6003 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6004 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6006 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6007 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6013 // left & result in different registers
6014 if(AOP_TYPE(result) == AOP_CRY){
6016 // if(size), result in bit
6017 // if(!size && ifx), conditional oper: if(left | right)
6018 symbol *tlbl = newiTempLabel(NULL);
6019 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6020 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6024 pic14_emitcode(";XXX setb","c");
6026 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6027 pic14_emitcode(";XXX orl","a,%s",
6028 aopGet(AOP(left),offset,FALSE,FALSE));
6029 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6034 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6035 pic14_outBitC(result);
6037 jmpTrueOrFalse(ifx, tlbl);
6038 } else for(;(size--);offset++){
6040 // result = left | right
6041 if(AOP_TYPE(right) == AOP_LIT){
6042 int t = (lit >> (offset*8)) & 0x0FFL;
6045 if (AOP_TYPE(left) != AOP_ACC) {
6046 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6048 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6052 if (AOP_TYPE(left) == AOP_ACC) {
6053 emitpcode(POC_IORLW, popGetLit(t));
6055 emitpcode(POC_MOVLW, popGetLit(t));
6056 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6058 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6063 // faster than result <- left, anl result,right
6064 // and better if result is SFR
6065 if (AOP_TYPE(left) == AOP_ACC) {
6066 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6068 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6069 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6071 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6076 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6077 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6078 freeAsmop(result,NULL,ic,TRUE);
6081 /*-----------------------------------------------------------------*/
6082 /* genXor - code for xclusive or */
6083 /*-----------------------------------------------------------------*/
6084 static void genXor (iCode *ic, iCode *ifx)
6086 operand *left, *right, *result;
6088 unsigned long lit = 0L;
6091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6093 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6094 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6095 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6097 /* if left is a literal & right is not ||
6098 if left needs acc & right does not */
6099 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6100 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6101 operand *tmp = right ;
6106 /* if result = right then exchange them */
6107 if(pic14_sameRegs(AOP(result),AOP(right))){
6108 operand *tmp = right ;
6113 /* if right is bit then exchange them */
6114 if (AOP_TYPE(right) == AOP_CRY &&
6115 AOP_TYPE(left) != AOP_CRY){
6116 operand *tmp = right ;
6120 if(AOP_TYPE(right) == AOP_LIT)
6121 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6123 size = AOP_SIZE(result);
6127 if (AOP_TYPE(left) == AOP_CRY){
6128 if(AOP_TYPE(right) == AOP_LIT){
6129 // c = bit & literal;
6131 // lit>>1 != 0 => result = 1
6132 if(AOP_TYPE(result) == AOP_CRY){
6134 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6135 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6137 continueIfTrue(ifx);
6140 pic14_emitcode("setb","c");
6144 // lit == 0, result = left
6145 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6147 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6149 // lit == 1, result = not(left)
6150 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6151 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6152 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6153 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6156 assert ( !"incomplete genXor" );
6157 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158 pic14_emitcode("cpl","c");
6165 symbol *tlbl = newiTempLabel(NULL);
6166 if (AOP_TYPE(right) == AOP_CRY){
6168 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6171 int sizer = AOP_SIZE(right);
6173 // if val>>1 != 0, result = 1
6174 pic14_emitcode("setb","c");
6176 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6178 // test the msb of the lsb
6179 pic14_emitcode("anl","a,#0xfe");
6180 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6184 pic14_emitcode("rrc","a");
6186 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6187 pic14_emitcode("cpl","c");
6188 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6193 pic14_outBitC(result);
6195 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6196 genIfxJump(ifx, "c");
6200 if(pic14_sameRegs(AOP(result),AOP(left))){
6201 /* if left is same as result */
6202 for(;size--; offset++) {
6203 if(AOP_TYPE(right) == AOP_LIT){
6204 int t = (lit >> (offset*8)) & 0x0FFL;
6208 if (IS_AOP_PREG(left)) {
6209 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6210 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6211 aopPut(AOP(result),"a",offset);
6213 emitpcode(POC_MOVLW, popGetLit(t));
6214 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6215 pic14_emitcode("xrl","%s,%s",
6216 aopGet(AOP(left),offset,FALSE,TRUE),
6217 aopGet(AOP(right),offset,FALSE,FALSE));
6220 if (AOP_TYPE(left) == AOP_ACC)
6221 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6223 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6224 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6226 if (IS_AOP_PREG(left)) {
6227 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6228 aopPut(AOP(result),"a",offset);
6230 pic14_emitcode("xrl","%s,a",
6231 aopGet(AOP(left),offset,FALSE,TRUE));
6237 // left & result in different registers
6238 if(AOP_TYPE(result) == AOP_CRY){
6240 // if(size), result in bit
6241 // if(!size && ifx), conditional oper: if(left ^ right)
6242 symbol *tlbl = newiTempLabel(NULL);
6243 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6245 pic14_emitcode("setb","c");
6247 if((AOP_TYPE(right) == AOP_LIT) &&
6248 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6249 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6251 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6252 pic14_emitcode("xrl","a,%s",
6253 aopGet(AOP(left),offset,FALSE,FALSE));
6255 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6260 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6261 pic14_outBitC(result);
6263 jmpTrueOrFalse(ifx, tlbl);
6264 } else for(;(size--);offset++){
6266 // result = left & right
6267 if(AOP_TYPE(right) == AOP_LIT){
6268 int t = (lit >> (offset*8)) & 0x0FFL;
6271 if (AOP_TYPE(left) != AOP_ACC) {
6272 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6274 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6275 pic14_emitcode("movf","%s,w",
6276 aopGet(AOP(left),offset,FALSE,FALSE));
6277 pic14_emitcode("movwf","%s",
6278 aopGet(AOP(result),offset,FALSE,FALSE));
6281 if (AOP_TYPE(left) == AOP_ACC) {
6282 emitpcode(POC_XORLW, popGetLit(t));
6284 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6286 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6289 if (AOP_TYPE(left) == AOP_ACC) {
6290 emitpcode(POC_XORLW, popGetLit(t));
6292 emitpcode(POC_MOVLW, popGetLit(t));
6293 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6295 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6296 pic14_emitcode("movlw","0x%x",t);
6297 pic14_emitcode("xorwf","%s,w",
6298 aopGet(AOP(left),offset,FALSE,FALSE));
6299 pic14_emitcode("movwf","%s",
6300 aopGet(AOP(result),offset,FALSE,FALSE));
6306 // faster than result <- left, anl result,right
6307 // and better if result is SFR
6308 if (AOP_TYPE(left) == AOP_ACC) {
6309 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6311 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6312 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6314 if ( AOP_TYPE(result) != AOP_ACC){
6315 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6321 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6322 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6323 freeAsmop(result,NULL,ic,TRUE);
6326 /*-----------------------------------------------------------------*/
6327 /* genInline - write the inline code out */
6328 /*-----------------------------------------------------------------*/
6329 static void genInline (iCode *ic)
6331 char *buffer, *bp, *bp1;
6334 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6336 _G.inLine += (!options.asmpeep);
6338 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6339 strcpy(buffer,IC_INLINE(ic));
6341 /* emit each line as a code */
6347 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6355 /* print label, use this special format with NULL directive
6356 * to denote that the argument should not be indented with tab */
6357 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6364 if ((bp1 != bp) && *bp1)
6365 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6369 _G.inLine -= (!options.asmpeep);
6372 /*-----------------------------------------------------------------*/
6373 /* genRRC - rotate right with carry */
6374 /*-----------------------------------------------------------------*/
6375 static void genRRC (iCode *ic)
6377 operand *left , *result ;
6378 int size, offset = 0, same;
6381 /* rotate right with carry */
6383 result=IC_RESULT(ic);
6384 aopOp (left,ic,FALSE);
6385 aopOp (result,ic,FALSE);
6387 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6389 same = pic14_sameRegs(AOP(result),AOP(left));
6391 size = AOP_SIZE(result);
6393 /* get the lsb and put it into the carry */
6394 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6401 emitpcode(POC_RRF, popGet(AOP(left),offset));
6403 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6404 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6410 freeAsmop(left,NULL,ic,TRUE);
6411 freeAsmop(result,NULL,ic,TRUE);
6414 /*-----------------------------------------------------------------*/
6415 /* genRLC - generate code for rotate left with carry */
6416 /*-----------------------------------------------------------------*/
6417 static void genRLC (iCode *ic)
6419 operand *left , *result ;
6420 int size, offset = 0;
6424 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6425 /* rotate right with carry */
6427 result=IC_RESULT(ic);
6428 aopOp (left,ic,FALSE);
6429 aopOp (result,ic,FALSE);
6431 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6433 same = pic14_sameRegs(AOP(result),AOP(left));
6435 /* move it to the result */
6436 size = AOP_SIZE(result);
6438 /* get the msb and put it into the carry */
6439 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6446 emitpcode(POC_RLF, popGet(AOP(left),offset));
6448 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6449 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6456 freeAsmop(left,NULL,ic,TRUE);
6457 freeAsmop(result,NULL,ic,TRUE);
6460 /*-----------------------------------------------------------------*/
6461 /* genGetHbit - generates code get highest order bit */
6462 /*-----------------------------------------------------------------*/
6463 static void genGetHbit (iCode *ic)
6465 operand *left, *result;
6467 result=IC_RESULT(ic);
6468 aopOp (left,ic,FALSE);
6469 aopOp (result,ic,FALSE);
6472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6473 /* get the highest order byte into a */
6474 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6475 if(AOP_TYPE(result) == AOP_CRY){
6476 pic14_emitcode("rlc","a");
6477 pic14_outBitC(result);
6480 pic14_emitcode("rl","a");
6481 pic14_emitcode("anl","a,#0x01");
6482 pic14_outAcc(result);
6486 freeAsmop(left,NULL,ic,TRUE);
6487 freeAsmop(result,NULL,ic,TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* AccLsh - shift left accumulator by known count */
6492 /* MARK: pic14 always rotates through CARRY! */
6493 /*-----------------------------------------------------------------*/
6494 static void AccLsh (pCodeOp *pcop,int shCount)
6497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6498 shCount &= 0x0007; // shCount : 0..7
6505 emitpcode(POC_RLF,pcop);
6509 emitpcode(POC_RLF,pcop);
6510 emitpcode(POC_RLF,pcop);
6513 emitpcode(POC_RLF,pcop);
6514 emitpcode(POC_RLF,pcop);
6515 emitpcode(POC_RLF,pcop);
6518 emitpcode(POC_SWAPF,pcop);
6521 emitpcode(POC_SWAPF,pcop);
6522 emitpcode(POC_RLF,pcop);
6525 emitpcode(POC_SWAPF,pcop);
6526 emitpcode(POC_RLF,pcop);
6527 emitpcode(POC_RLF,pcop);
6530 emitpcode(POC_RRFW,pcop);
6531 emitpcode(POC_RRF,pcop);
6534 /* clear invalid bits */
6535 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6536 emitpcode(POC_ANDWF, pcop);
6539 /*-----------------------------------------------------------------*/
6540 /* AccRsh - shift right accumulator by known count */
6541 /* MARK: pic14 always rotates through CARRY! */
6542 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6543 /* 1: mask out invalid bits (zero-extend) */
6544 /* 2: sign-extend result (pretty slow) */
6545 /*-----------------------------------------------------------------*/
6546 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6549 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6550 shCount &= 0x0007; // shCount : 0..7
6556 /* load sign if needed */
6557 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6558 else if (mask_mode == 1) emitCLRC;
6559 emitpcode(POC_RRF,pcop);
6563 /* load sign if needed */
6564 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6565 emitpcode(POC_RRF,pcop);
6566 /* load sign if needed */
6567 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568 emitpcode(POC_RRF,pcop);
6569 if (mask_mode == 2) return;
6572 /* load sign if needed */
6573 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6574 emitpcode(POC_RRF,pcop);
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 if (mask_mode == 2) return;
6584 emitpcode(POC_SWAPF,pcop);
6587 emitpcode(POC_SWAPF,pcop);
6588 emitpcode(POC_RRF,pcop);
6591 emitpcode(POC_SWAPF,pcop);
6592 emitpcode(POC_RRF,pcop);
6593 emitpcode(POC_RRF,pcop);
6599 emitpcode(POC_RLFW,pcop);
6600 emitpcode(POC_CLRF,pcop);
6602 emitpcode(POC_COMF,pcop);
6605 emitpcode(POC_RLFW,pcop);
6606 emitpcode(POC_RLF,pcop);
6613 /* leave invalid bits undefined */
6617 /* clear invalid bits -- zero-extend */
6618 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6619 emitpcode(POC_ANDWF, pcop);
6621 if (mask_mode == 2) {
6623 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6624 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6625 emitpcode(POC_IORWF, pcop);
6630 /*-----------------------------------------------------------------*/
6631 /* AccSRsh - signed right shift accumulator by known count */
6632 /*-----------------------------------------------------------------*/
6633 static void AccSRsh (int shCount)
6636 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6639 pic14_emitcode("mov","c,acc.7");
6640 pic14_emitcode("rrc","a");
6641 } else if(shCount == 2){
6642 pic14_emitcode("mov","c,acc.7");
6643 pic14_emitcode("rrc","a");
6644 pic14_emitcode("mov","c,acc.7");
6645 pic14_emitcode("rrc","a");
6647 tlbl = newiTempLabel(NULL);
6648 /* rotate right accumulator */
6649 AccRol(8 - shCount);
6650 /* and kill the higher order bits */
6651 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6652 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6653 pic14_emitcode("orl","a,#0x%02x",
6654 (unsigned char)~SRMask[shCount]);
6655 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6660 /*-----------------------------------------------------------------*/
6661 /* shiftR1Left2Result - shift right one byte from left to result */
6662 /*-----------------------------------------------------------------*/
6663 static void shiftR1Left2ResultSigned (operand *left, int offl,
6664 operand *result, int offr,
6670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6672 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6676 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6678 emitpcode(POC_RRF, popGet(AOP(result),offr));
6680 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6681 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6687 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6689 emitpcode(POC_RRF, popGet(AOP(result),offr));
6691 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6692 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6694 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6695 emitpcode(POC_RRF, popGet(AOP(result),offr));
6701 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6703 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6704 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6707 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6708 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6709 emitpcode(POC_ANDLW, popGetLit(0x1f));
6711 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6712 emitpcode(POC_IORLW, popGetLit(0xe0));
6714 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6718 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6719 emitpcode(POC_ANDLW, popGetLit(0x0f));
6720 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6721 emitpcode(POC_IORLW, popGetLit(0xf0));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6728 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6729 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6731 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6732 emitpcode(POC_ANDLW, popGetLit(0x07));
6733 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6734 emitpcode(POC_IORLW, popGetLit(0xf8));
6735 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6740 emitpcode(POC_MOVLW, popGetLit(0x00));
6741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742 emitpcode(POC_MOVLW, popGetLit(0xfe));
6743 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6744 emitpcode(POC_IORLW, popGetLit(0x01));
6745 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6748 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6749 emitpcode(POC_DECF, popGet(AOP(result),offr));
6750 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6751 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6757 emitpcode(POC_MOVLW, popGetLit(0x00));
6758 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6759 emitpcode(POC_MOVLW, popGetLit(0xff));
6760 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6762 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6763 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6764 emitpcode(POC_DECF, popGet(AOP(result),offr));
6772 /*-----------------------------------------------------------------*/
6773 /* shiftR1Left2Result - shift right one byte from left to result */
6774 /*-----------------------------------------------------------------*/
6775 static void shiftR1Left2Result (operand *left, int offl,
6776 operand *result, int offr,
6777 int shCount, int sign)
6782 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6784 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6786 /* Copy the msb into the carry if signed. */
6788 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6798 emitpcode(POC_RRF, popGet(AOP(result),offr));
6800 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6801 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6807 emitpcode(POC_RRF, popGet(AOP(result),offr));
6809 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6810 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6813 emitpcode(POC_RRF, popGet(AOP(result),offr));
6818 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6820 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6821 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6824 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6825 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6826 emitpcode(POC_ANDLW, popGetLit(0x1f));
6827 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6831 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6832 emitpcode(POC_ANDLW, popGetLit(0x0f));
6833 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6837 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6838 emitpcode(POC_ANDLW, popGetLit(0x0f));
6839 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6841 emitpcode(POC_RRF, popGet(AOP(result),offr));
6846 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6847 emitpcode(POC_ANDLW, popGetLit(0x80));
6848 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6849 emitpcode(POC_RLF, popGet(AOP(result),offr));
6850 emitpcode(POC_RLF, popGet(AOP(result),offr));
6855 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6856 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6857 emitpcode(POC_RLF, popGet(AOP(result),offr));
6866 /*-----------------------------------------------------------------*/
6867 /* shiftL1Left2Result - shift left one byte from left to result */
6868 /*-----------------------------------------------------------------*/
6869 static void shiftL1Left2Result (operand *left, int offl,
6870 operand *result, int offr, int shCount)
6876 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6878 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6879 DEBUGpic14_emitcode ("; ***","same = %d",same);
6880 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6882 /* shift left accumulator */
6883 //AccLsh(shCount); // don't comment out just yet...
6884 // aopPut(AOP(result),"a",offr);
6888 /* Shift left 1 bit position */
6889 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6891 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6893 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6894 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6898 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6899 emitpcode(POC_ANDLW,popGetLit(0x7e));
6900 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6901 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6904 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6905 emitpcode(POC_ANDLW,popGetLit(0x3e));
6906 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6907 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6908 emitpcode(POC_RLF, popGet(AOP(result),offr));
6911 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6912 emitpcode(POC_ANDLW, popGetLit(0xf0));
6913 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6916 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6917 emitpcode(POC_ANDLW, popGetLit(0xf0));
6918 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6919 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6922 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6923 emitpcode(POC_ANDLW, popGetLit(0x30));
6924 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6925 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6926 emitpcode(POC_RLF, popGet(AOP(result),offr));
6929 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6930 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6931 emitpcode(POC_RRF, popGet(AOP(result),offr));
6935 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6941 /*-----------------------------------------------------------------*/
6942 /* movLeft2Result - move byte from left to result */
6943 /*-----------------------------------------------------------------*/
6944 static void movLeft2Result (operand *left, int offl,
6945 operand *result, int offr)
6949 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6950 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6951 l = aopGet(AOP(left),offl,FALSE,FALSE);
6953 if (*l == '@' && (IS_AOP_PREG(result))) {
6954 pic14_emitcode("mov","a,%s",l);
6955 aopPut(AOP(result),"a",offr);
6957 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6958 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6963 /*-----------------------------------------------------------------*/
6964 /* shiftLeft_Left2ResultLit - shift left by known count */
6965 /*-----------------------------------------------------------------*/
6967 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6969 int size, same, offr, i;
6971 size = AOP_SIZE(left);
6972 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6974 same = pic14_sameRegs (AOP(left), AOP(result));
6977 shCount = shCount & 0x07;
6983 case 0: /* takes 0 or 2N cycles (for offr==0) */
6984 if (!same || offr) {
6985 for (i=size-1; i >= 0; i--)
6986 movLeft2Result (left, i, result, offr + i);
6990 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6992 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6993 shiftLeft_Left2ResultLit (result, result, shCount);
6994 return; /* prevent clearing result again */
6997 for (i=0; i < size; i++) {
6998 if (same && !offr) {
6999 emitpcode (POC_RLF, popGet (AOP(left), i));
7001 emitpcode (POC_RLFW, popGet (AOP(left), i));
7002 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7008 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7009 /* works in-place/with offr as well */
7010 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7011 emitpcode (POC_ANDLW, popGetLit (0xF0));
7012 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7014 for (i = size - 2; i >= 0; i--)
7016 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7017 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7018 emitpcode (POC_ANDLW, popGetLit (0x0F));
7019 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7020 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7024 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7025 /* works in-place/with offr as well */
7026 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7027 for (i = size-2; i >= 0; i--) {
7028 emitpcode (POC_RRFW, popGet (AOP(left), i));
7029 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7031 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7032 emitpcode (POC_RRF, popGet (AOP(result), offr));
7036 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7037 shiftLeft_Left2ResultLit (result, result, 1);
7038 return; /* prevent clearing result again */
7044 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7048 /*-----------------------------------------------------------------*/
7049 /* shiftRight_Left2ResultLit - shift right by known count */
7050 /*-----------------------------------------------------------------*/
7052 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7054 int size, same, offr, i;
7056 size = AOP_SIZE(left);
7057 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7059 same = pic14_sameRegs (AOP(left), AOP(result));
7062 shCount = shCount & 0x07;
7070 case 0: /* takes 0 or 2N cycles (for offr==0) */
7071 if (!same || offr) {
7072 for (i=0; i < size; i++)
7073 movLeft2Result (left, i + offr, result, i);
7077 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7078 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7080 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7081 shiftRight_Left2ResultLit (result, result, shCount, sign);
7082 return; /* prevent sign-extending result again */
7086 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7089 for (i = size-1; i >= 0; i--) {
7090 if (same && !offr) {
7091 emitpcode (POC_RRF, popGet (AOP(left), i));
7093 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7094 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7100 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7101 /* works in-place/with offr as well */
7102 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7103 emitpcode (POC_ANDLW, popGetLit (0x0F));
7104 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7106 for (i = 1; i < size; i++)
7108 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7109 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7110 emitpcode (POC_ANDLW, popGetLit (0xF0));
7111 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7112 emitpcode (POC_XORWF, popGet (AOP(result), i));
7117 emitpcode (POC_MOVLW, popGetLit (0xF0));
7118 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7119 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7123 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7124 /* works in-place/with offr as well */
7125 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7126 for (i = 0; i < size-1; i++) {
7127 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7128 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7130 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7132 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7135 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7140 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7141 shiftRight_Left2ResultLit (result, result, 1, sign);
7142 return; /* prevent sign extending result again */
7147 addSign (result, size, sign);
7151 /*-----------------------------------------------------------------*/
7152 /* shiftL2Left2Result - shift left two bytes from left to result */
7153 /*-----------------------------------------------------------------*/
7154 static void shiftL2Left2Result (operand *left, int offl,
7155 operand *result, int offr, int shCount)
7159 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7161 if(pic14_sameRegs(AOP(result), AOP(left))) {
7169 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7170 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7171 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7175 emitpcode(POC_RLF, popGet(AOP(result),offr));
7176 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7182 emitpcode(POC_MOVLW, popGetLit(0x0f));
7183 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7184 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7185 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7186 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7187 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7188 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7190 emitpcode(POC_RLF, popGet(AOP(result),offr));
7191 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7195 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7196 emitpcode(POC_RRF, popGet(AOP(result),offr));
7197 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7198 emitpcode(POC_RRF, popGet(AOP(result),offr));
7199 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7200 emitpcode(POC_ANDLW,popGetLit(0xc0));
7201 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7202 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7203 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7204 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7207 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7208 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7209 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7210 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7211 emitpcode(POC_RRF, popGet(AOP(result),offr));
7221 /* note, use a mov/add for the shift since the mov has a
7222 chance of getting optimized out */
7223 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7224 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7225 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7226 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7227 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7231 emitpcode(POC_RLF, popGet(AOP(result),offr));
7232 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7238 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7239 emitpcode(POC_ANDLW, popGetLit(0xF0));
7240 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7241 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7242 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7243 emitpcode(POC_ANDLW, popGetLit(0xF0));
7244 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7245 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7249 emitpcode(POC_RLF, popGet(AOP(result),offr));
7250 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7254 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7255 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7256 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7257 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7259 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7260 emitpcode(POC_RRF, popGet(AOP(result),offr));
7261 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7262 emitpcode(POC_ANDLW,popGetLit(0xc0));
7263 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7264 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7265 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7266 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7269 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7270 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7271 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7272 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7273 emitpcode(POC_RRF, popGet(AOP(result),offr));
7279 /*-----------------------------------------------------------------*/
7280 /* shiftR2Left2Result - shift right two bytes from left to result */
7281 /*-----------------------------------------------------------------*/
7282 static void shiftR2Left2Result (operand *left, int offl,
7283 operand *result, int offr,
7284 int shCount, int sign)
7289 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7290 same = pic14_sameRegs(AOP(result), AOP(left));
7292 if(same && ((offl + MSB16) == offr)){
7294 /* don't crash result[offr] */
7295 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7296 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7299 movLeft2Result(left,offl, result, offr);
7300 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7303 /* a:x >> shCount (x = lsb(result))*/
7306 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7308 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7317 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7322 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7323 emitpcode(POC_RRF,popGet(AOP(result),offr));
7325 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7326 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7327 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7328 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7333 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7336 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7337 emitpcode(POC_RRF,popGet(AOP(result),offr));
7344 emitpcode(POC_MOVLW, popGetLit(0xf0));
7345 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7346 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7348 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7349 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7350 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7351 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7353 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7354 emitpcode(POC_ANDLW, popGetLit(0x0f));
7355 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7357 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7358 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7359 emitpcode(POC_ANDLW, popGetLit(0xf0));
7360 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7361 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7365 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7366 emitpcode(POC_RRF, popGet(AOP(result),offr));
7370 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7371 emitpcode(POC_BTFSC,
7372 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7373 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_RLF, popGet(AOP(result),offr));
7382 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7384 emitpcode(POC_RLF, popGet(AOP(result),offr));
7385 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7386 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7387 emitpcode(POC_ANDLW,popGetLit(0x03));
7389 emitpcode(POC_BTFSC,
7390 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7391 emitpcode(POC_IORLW,popGetLit(0xfc));
7393 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7394 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7395 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7396 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7398 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7399 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7400 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7401 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7402 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7403 emitpcode(POC_RLF, popGet(AOP(result),offr));
7404 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7405 emitpcode(POC_ANDLW,popGetLit(0x03));
7407 emitpcode(POC_BTFSC,
7408 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7409 emitpcode(POC_IORLW,popGetLit(0xfc));
7411 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7412 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7419 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7420 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7421 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7422 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7425 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7427 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7431 /*-----------------------------------------------------------------*/
7432 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7433 /*-----------------------------------------------------------------*/
7434 static void shiftLLeftOrResult (operand *left, int offl,
7435 operand *result, int offr, int shCount)
7438 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7440 /* shift left accumulator */
7441 AccLsh(left,offl,shCount);
7442 /* or with result */
7443 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7444 assert ( !"broken (modifies left, fails for left==result))" );
7447 /*-----------------------------------------------------------------*/
7448 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7449 /*-----------------------------------------------------------------*/
7450 static void shiftRLeftOrResult (operand *left, int offl,
7451 operand *result, int offr, int shCount)
7454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7456 /* shift right accumulator */
7457 AccRsh(left,offl,shCount);
7458 /* or with result */
7459 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7460 assert ( !"broken (modifies left, fails for left==result))" );
7463 /*-----------------------------------------------------------------*/
7464 /* genlshOne - left shift a one byte quantity by known count */
7465 /*-----------------------------------------------------------------*/
7466 static void genlshOne (operand *result, operand *left, int shCount)
7469 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7470 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7473 /*-----------------------------------------------------------------*/
7474 /* genlshTwo - left shift two bytes by known amount != 0 */
7475 /*-----------------------------------------------------------------*/
7476 static void genlshTwo (operand *result,operand *left, int shCount)
7481 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7482 size = pic14_getDataSize(result);
7484 /* if shCount >= 8 */
7490 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7492 movLeft2Result(left, LSB, result, MSB16);
7494 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7497 /* 1 <= shCount <= 7 */
7500 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7502 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7506 /*-----------------------------------------------------------------*/
7507 /* shiftLLong - shift left one long from left to result */
7508 /* offl = LSB or MSB16 */
7509 /*-----------------------------------------------------------------*/
7510 static void shiftLLong (operand *left, operand *result, int offr )
7513 int size = AOP_SIZE(result);
7516 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7517 if(size >= LSB+offr){
7518 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7520 pic14_emitcode("add","a,acc");
7521 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7522 size >= MSB16+offr && offr != LSB )
7523 pic14_emitcode("xch","a,%s",
7524 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7526 aopPut(AOP(result),"a",LSB+offr);
7529 if(size >= MSB16+offr){
7530 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7531 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7534 pic14_emitcode("rlc","a");
7535 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7536 size >= MSB24+offr && offr != LSB)
7537 pic14_emitcode("xch","a,%s",
7538 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7540 aopPut(AOP(result),"a",MSB16+offr);
7543 if(size >= MSB24+offr){
7544 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7545 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7548 pic14_emitcode("rlc","a");
7549 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7550 size >= MSB32+offr && offr != LSB )
7551 pic14_emitcode("xch","a,%s",
7552 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7554 aopPut(AOP(result),"a",MSB24+offr);
7557 if(size > MSB32+offr){
7558 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7559 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7562 pic14_emitcode("rlc","a");
7563 aopPut(AOP(result),"a",MSB32+offr);
7566 aopPut(AOP(result),zero,LSB);
7569 /*-----------------------------------------------------------------*/
7570 /* genlshFour - shift four byte by a known amount != 0 */
7571 /*-----------------------------------------------------------------*/
7572 static void genlshFour (operand *result, operand *left, int shCount)
7577 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7578 size = AOP_SIZE(result);
7580 /* if shifting more that 3 bytes */
7581 if (shCount >= 24 ) {
7584 /* lowest order of left goes to the highest
7585 order of the destination */
7586 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7588 movLeft2Result(left, LSB, result, MSB32);
7589 aopPut(AOP(result),zero,LSB);
7590 aopPut(AOP(result),zero,MSB16);
7591 aopPut(AOP(result),zero,MSB32);
7595 /* more than two bytes */
7596 else if ( shCount >= 16 ) {
7597 /* lower order two bytes goes to higher order two bytes */
7599 /* if some more remaining */
7601 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7603 movLeft2Result(left, MSB16, result, MSB32);
7604 movLeft2Result(left, LSB, result, MSB24);
7606 aopPut(AOP(result),zero,MSB16);
7607 aopPut(AOP(result),zero,LSB);
7611 /* if more than 1 byte */
7612 else if ( shCount >= 8 ) {
7613 /* lower order three bytes goes to higher order three bytes */
7617 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7619 movLeft2Result(left, LSB, result, MSB16);
7621 else{ /* size = 4 */
7623 movLeft2Result(left, MSB24, result, MSB32);
7624 movLeft2Result(left, MSB16, result, MSB24);
7625 movLeft2Result(left, LSB, result, MSB16);
7626 aopPut(AOP(result),zero,LSB);
7628 else if(shCount == 1)
7629 shiftLLong(left, result, MSB16);
7631 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7632 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7633 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7634 aopPut(AOP(result),zero,LSB);
7639 /* 1 <= shCount <= 7 */
7640 else if(shCount <= 2){
7641 shiftLLong(left, result, LSB);
7643 shiftLLong(result, result, LSB);
7645 /* 3 <= shCount <= 7, optimize */
7647 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7648 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7649 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7655 /*-----------------------------------------------------------------*/
7656 /* genLeftShiftLiteral - left shifting by known count */
7657 /*-----------------------------------------------------------------*/
7658 static void genLeftShiftLiteral (operand *left,
7663 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7667 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7668 freeAsmop(right,NULL,ic,TRUE);
7670 aopOp(left,ic,FALSE);
7671 aopOp(result,ic,FALSE);
7673 size = getSize(operandType(result));
7676 pic14_emitcode("; shift left ","result %d, left %d",size,
7680 /* I suppose that the left size >= result size */
7683 movLeft2Result(left, size, result, size);
7687 else if(shCount >= (size * 8))
7689 aopPut(AOP(result),zero,size);
7693 genlshOne (result,left,shCount);
7698 genlshTwo (result,left,shCount);
7702 genlshFour (result,left,shCount);
7706 freeAsmop(left,NULL,ic,TRUE);
7707 freeAsmop(result,NULL,ic,TRUE);
7711 /*-----------------------------------------------------------------*
7712 * genMultiAsm - repeat assembly instruction for size of register.
7713 * if endian == 1, then the high byte (i.e base address + size of
7714 * register) is used first else the low byte is used first;
7715 *-----------------------------------------------------------------*/
7716 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7722 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7735 emitpcode(poc, popGet(AOP(reg),offset));
7742 /*-----------------------------------------------------------------*/
7743 /* genLeftShift - generates code for left shifting */
7744 /*-----------------------------------------------------------------*/
7745 static void genLeftShift (iCode *ic)
7747 operand *left,*right, *result;
7749 unsigned long lit = 0L;
7751 symbol *tlbl , *tlbl1;
7755 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7757 right = IC_RIGHT(ic);
7759 result = IC_RESULT(ic);
7761 aopOp(right,ic,FALSE);
7762 aopOp(left,ic,FALSE);
7763 aopOp(result,ic,FALSE);
7766 /* if the shift count is known then do it
7767 as efficiently as possible */
7768 if (AOP_TYPE(right) == AOP_LIT) {
7769 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7773 /* shift count is unknown then we have to form
7774 a loop get the loop count in B : Note: we take
7775 only the lower order byte since shifting
7776 more that 32 bits make no sense anyway, ( the
7777 largest size of an object can be only 32 bits ) */
7779 /* this code fails for RIGHT == RESULT */
7780 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7782 /* now move the left to the result if they are not the
7784 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7785 AOP_SIZE(result) > 1) {
7787 size = AOP_SIZE(result);
7790 l = aopGet(AOP(left),offset,FALSE,TRUE);
7791 if (*l == '@' && (IS_AOP_PREG(result))) {
7793 pic14_emitcode("mov","a,%s",l);
7794 aopPut(AOP(result),"a",offset);
7796 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7797 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7798 //aopPut(AOP(result),l,offset);
7804 if(AOP_TYPE(left) == AOP_LIT)
7805 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7807 size = AOP_SIZE(result);
7809 /* if it is only one byte then */
7811 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7812 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7813 emitpcode(POC_ANDLW, popGetLit(0xf0));
7814 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7815 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7816 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7817 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7818 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7819 emitpcode(POC_RLFW, popGet(AOP(result),0));
7820 emitpcode(POC_ANDLW, popGetLit(0xfe));
7821 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7822 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7823 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7826 tlbl = newiTempLabel(NULL);
7827 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7828 mov2w (AOP(left), 0);
7829 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7832 emitpcode(POC_COMFW, popGet(AOP(right),0));
7833 emitpcode(POC_RRF, popGet(AOP(result),0));
7834 emitpLabel(tlbl->key);
7835 emitpcode(POC_RLF, popGet(AOP(result),0));
7836 emitpcode(POC_ADDLW, popGetLit(1));
7838 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7843 if (pic14_sameRegs(AOP(left),AOP(result))) {
7845 tlbl = newiTempLabel(NULL);
7846 emitpcode(POC_COMFW, popGet(AOP(right),0));
7847 genMultiAsm(POC_RRF, result, size,1);
7848 emitpLabel(tlbl->key);
7849 genMultiAsm(POC_RLF, result, size,0);
7850 emitpcode(POC_ADDLW, popGetLit(1));
7852 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7856 //tlbl = newiTempLabel(NULL);
7858 //tlbl1 = newiTempLabel(NULL);
7860 //reAdjustPreg(AOP(result));
7862 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7863 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7864 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7866 //pic14_emitcode("add","a,acc");
7867 //aopPut(AOP(result),"a",offset++);
7869 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7871 // pic14_emitcode("rlc","a");
7872 // aopPut(AOP(result),"a",offset++);
7874 //reAdjustPreg(AOP(result));
7876 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7877 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7880 tlbl = newiTempLabel(NULL);
7881 tlbl1= newiTempLabel(NULL);
7883 size = AOP_SIZE(result);
7886 pctemp = popGetTempReg(); /* grab a temporary working register. */
7888 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7890 /* offset should be 0, 1 or 3 */
7891 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7893 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7895 emitpcode(POC_MOVWF, pctemp);
7898 emitpLabel(tlbl->key);
7901 emitpcode(POC_RLF, popGet(AOP(result),0));
7903 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7905 emitpcode(POC_DECFSZ, pctemp);
7906 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7907 emitpLabel(tlbl1->key);
7909 popReleaseTempReg(pctemp);
7913 freeAsmop (right,NULL,ic,TRUE);
7914 freeAsmop(left,NULL,ic,TRUE);
7915 freeAsmop(result,NULL,ic,TRUE);
7920 /*-----------------------------------------------------------------*/
7921 /* genrshOne - right shift a one byte quantity by known count */
7922 /*-----------------------------------------------------------------*/
7923 static void genrshOne (operand *result, operand *left,
7924 int shCount, int sign)
7927 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7928 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7931 /*-----------------------------------------------------------------*/
7932 /* genrshTwo - right shift two bytes by known amount != 0 */
7933 /*-----------------------------------------------------------------*/
7934 static void genrshTwo (operand *result,operand *left,
7935 int shCount, int sign)
7938 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7939 /* if shCount >= 8 */
7943 shiftR1Left2Result(left, MSB16, result, LSB,
7946 movLeft2Result(left, MSB16, result, LSB);
7948 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7951 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7952 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7956 /* 1 <= shCount <= 7 */
7958 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7961 /*-----------------------------------------------------------------*/
7962 /* shiftRLong - shift right one long from left to result */
7963 /* offl = LSB or MSB16 */
7964 /*-----------------------------------------------------------------*/
7965 static void shiftRLong (operand *left, int offl,
7966 operand *result, int sign)
7971 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7973 size = AOP_SIZE(left);
7974 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7977 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7981 assert (offl >= 0 && offl < size);
7983 same = pic14_sameRegs (AOP(left), AOP(result));
7985 /* perform the shift */
7988 if (same && !offl) {
7989 emitpcode (POC_RRF, popGet (AOP(result), size));
7991 emitpcode (POC_RRFW, popGet (AOP(left), size));
7992 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7996 addSign (result, AOP_SIZE(left) - offl, sign);
7999 /*-----------------------------------------------------------------*/
8000 /* genrshFour - shift four byte by a known amount != 0 */
8001 /*-----------------------------------------------------------------*/
8002 static void genrshFour (operand *result, operand *left,
8003 int shCount, int sign)
8006 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8007 /* if shifting more that 3 bytes */
8008 if(shCount >= 24 ) {
8011 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8013 movLeft2Result(left, MSB32, result, LSB);
8015 addSign(result, MSB16, sign);
8017 else if(shCount >= 16){
8020 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8022 movLeft2Result(left, MSB24, result, LSB);
8023 movLeft2Result(left, MSB32, result, MSB16);
8025 addSign(result, MSB24, sign);
8027 else if(shCount >= 8){
8030 shiftRLong(left, MSB16, result, sign);
8031 else if(shCount == 0){
8032 movLeft2Result(left, MSB16, result, LSB);
8033 movLeft2Result(left, MSB24, result, MSB16);
8034 movLeft2Result(left, MSB32, result, MSB24);
8035 addSign(result, MSB32, sign);
8038 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8039 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8040 /* the last shift is signed */
8041 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8042 addSign(result, MSB32, sign);
8045 else{ /* 1 <= shCount <= 7 */
8047 shiftRLong(left, LSB, result, sign);
8049 shiftRLong(result, LSB, result, sign);
8052 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8053 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8054 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8059 /*-----------------------------------------------------------------*/
8060 /* genRightShiftLiteral - right shifting by known count */
8061 /*-----------------------------------------------------------------*/
8062 static void genRightShiftLiteral (operand *left,
8068 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8072 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8073 freeAsmop(right,NULL,ic,TRUE);
8075 aopOp(left,ic,FALSE);
8076 aopOp(result,ic,FALSE);
8079 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8083 lsize = pic14_getDataSize(left);
8084 res_size = pic14_getDataSize(result);
8085 /* test the LEFT size !!! */
8087 /* I suppose that the left size >= result size */
8090 movLeft2Result(left, res_size, result, res_size);
8093 else if(shCount >= (lsize * 8)){
8096 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8098 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8099 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8104 emitpcode(POC_MOVLW, popGetLit(0));
8105 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8106 emitpcode(POC_MOVLW, popGetLit(0xff));
8108 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8113 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8120 genrshOne (result,left,shCount,sign);
8124 genrshTwo (result,left,shCount,sign);
8128 genrshFour (result,left,shCount,sign);
8136 freeAsmop(left,NULL,ic,TRUE);
8137 freeAsmop(result,NULL,ic,TRUE);
8142 /*-----------------------------------------------------------------*/
8143 /* genSignedRightShift - right shift of signed number */
8144 /*-----------------------------------------------------------------*/
8145 static void genSignedRightShift (iCode *ic)
8147 operand *right, *left, *result;
8150 symbol *tlbl, *tlbl1 ;
8153 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8155 /* we do it the hard way put the shift count in b
8156 and loop thru preserving the sign */
8158 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8160 right = IC_RIGHT(ic);
8162 result = IC_RESULT(ic);
8164 aopOp(right,ic,FALSE);
8165 aopOp(left,ic,FALSE);
8166 aopOp(result,ic,FALSE);
8169 if ( AOP_TYPE(right) == AOP_LIT) {
8170 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8171 //genRightShiftLiteral (left,right,result,ic,1);
8174 /* shift count is unknown then we have to form
8175 a loop get the loop count in B : Note: we take
8176 only the lower order byte since shifting
8177 more that 32 bits make no sense anyway, ( the
8178 largest size of an object can be only 32 bits ) */
8180 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8181 //pic14_emitcode("inc","b");
8182 //freeAsmop (right,NULL,ic,TRUE);
8183 //aopOp(left,ic,FALSE);
8184 //aopOp(result,ic,FALSE);
8186 /* now move the left to the result if they are not the
8188 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8189 AOP_SIZE(result) > 1) {
8191 size = AOP_SIZE(result);
8195 l = aopGet(AOP(left),offset,FALSE,TRUE);
8196 if (*l == '@' && IS_AOP_PREG(result)) {
8197 pic14_emitcode("mov","a,%s",l);
8198 aopPut(AOP(result),"a",offset);
8200 aopPut(AOP(result),l,offset);
8202 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8203 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8209 /* mov the highest order bit to OVR */
8210 tlbl = newiTempLabel(NULL);
8211 tlbl1= newiTempLabel(NULL);
8213 size = AOP_SIZE(result);
8216 pctemp = popGetTempReg(); /* grab a temporary working register. */
8218 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8220 /* offset should be 0, 1 or 3 */
8221 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8223 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8225 emitpcode(POC_MOVWF, pctemp);
8228 emitpLabel(tlbl->key);
8230 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8231 emitpcode(POC_RRF, popGet(AOP(result),offset));
8234 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8237 emitpcode(POC_DECFSZ, pctemp);
8238 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8239 emitpLabel(tlbl1->key);
8241 popReleaseTempReg(pctemp);
8243 size = AOP_SIZE(result);
8245 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8246 pic14_emitcode("rlc","a");
8247 pic14_emitcode("mov","ov,c");
8248 /* if it is only one byte then */
8250 l = aopGet(AOP(left),0,FALSE,FALSE);
8252 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8253 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8254 pic14_emitcode("mov","c,ov");
8255 pic14_emitcode("rrc","a");
8256 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8257 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8258 aopPut(AOP(result),"a",0);
8262 reAdjustPreg(AOP(result));
8263 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8264 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8265 pic14_emitcode("mov","c,ov");
8267 l = aopGet(AOP(result),offset,FALSE,FALSE);
8269 pic14_emitcode("rrc","a");
8270 aopPut(AOP(result),"a",offset--);
8272 reAdjustPreg(AOP(result));
8273 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8274 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8279 freeAsmop(left,NULL,ic,TRUE);
8280 freeAsmop(result,NULL,ic,TRUE);
8281 freeAsmop(right,NULL,ic,TRUE);
8285 /*-----------------------------------------------------------------*/
8286 /* loadSignToC - load the operand's sign bit into CARRY */
8287 /*-----------------------------------------------------------------*/
8289 static void loadSignToC (operand *op)
8292 assert (op && AOP(op) && AOP_SIZE(op));
8295 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8299 /*-----------------------------------------------------------------*/
8300 /* genRightShift - generate code for right shifting */
8301 /*-----------------------------------------------------------------*/
8302 static void genGenericShift (iCode *ic, int shiftRight)
8304 operand *right, *left, *result;
8307 symbol *tlbl, *tlbl1, *inverselbl;
8310 /* if signed then we do it the hard way preserve the
8311 sign bit moving it inwards */
8312 retype = getSpec(operandType(IC_RESULT(ic)));
8313 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8315 /* signed & unsigned types are treated the same : i.e. the
8316 signed is NOT propagated inwards : quoting from the
8317 ANSI - standard : "for E1 >> E2, is equivalent to division
8318 by 2**E2 if unsigned or if it has a non-negative value,
8319 otherwise the result is implementation defined ", MY definition
8320 is that the sign does not get propagated */
8322 right = IC_RIGHT(ic);
8324 result = IC_RESULT(ic);
8326 aopOp(right,ic,FALSE);
8327 aopOp(left,ic,FALSE);
8328 aopOp(result,ic,FALSE);
8330 /* if the shift count is known then do it
8331 as efficiently as possible */
8332 if (AOP_TYPE(right) == AOP_LIT) {
8333 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8337 shiftRight = !shiftRight;
8341 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8343 shiftLeft_Left2ResultLit (left, result, lit);
8344 //genRightShiftLiteral (left,right,result,ic, 0);
8348 /* shift count is unknown then we have to form
8349 a loop get the loop count in B : Note: we take
8350 only the lower order byte since shifting
8351 more that 32 bits make no sense anyway, ( the
8352 largest size of an object can be only 32 bits ) */
8354 /* we must not overwrite the shift counter */
8355 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8357 /* now move the left to the result if they are not the
8359 if (!pic14_sameRegs(AOP(left),AOP(result)))
8361 size = min(AOP_SIZE(result), AOP_SIZE(left));
8363 mov2w(AOP(left), size);
8364 movwf(AOP(result), size);
8366 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8369 tlbl = newiTempLabel(NULL);
8370 tlbl1= newiTempLabel(NULL);
8372 size = AOP_SIZE(result);
8374 mov2w(AOP(right),0);
8375 if (!SPEC_USIGN(operandType(right)))
8377 inverselbl = newiTempLabel(NULL);
8378 /* signed shift count -- invert shift direction for c<0 */
8379 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8380 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8382 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8383 /* check for `a = b >> c' with `-c == 0' */
8385 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8386 emitpLabel(tlbl->key);
8387 /* propagate the sign bit inwards for SIGNED result */
8388 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8389 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8390 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8392 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8394 if (!SPEC_USIGN(operandType(right)))
8396 symbol *inv_loop = newiTempLabel(NULL);
8398 shiftRight = !shiftRight; /* invert shift direction */
8400 /* we came here from the code above -- we are done */
8401 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8403 /* emit code for shifting N<0 steps, count is already in W */
8404 emitpLabel(inverselbl->key);
8405 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8406 emitpLabel(inv_loop->key);
8407 /* propagate the sign bit inwards for SIGNED result */
8408 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8409 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8410 emitpcode(POC_ADDLW, popGetLit(1));
8412 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8415 emitpLabel(tlbl1->key);
8417 freeAsmop(left,NULL,ic,TRUE);
8418 freeAsmop (right,NULL,ic,TRUE);
8419 freeAsmop(result,NULL,ic,TRUE);
8422 static void genRightShift (iCode *ic)
8424 genGenericShift(ic, 1);
8427 static void genLeftShift (iCode *ic)
8429 genGenericShift(ic, 0);
8432 /*-----------------------------------------------------------------*/
8433 /* SetIrp - Set IRP bit */
8434 /*-----------------------------------------------------------------*/
8435 void SetIrp(operand *result) {
8437 if (AOP_TYPE(result) == AOP_LIT) {
8438 unsigned lit = (unsigned)operandLitValue(result);
8444 if (PCOP(AOP(result))->type == PO_LITERAL) {
8445 int addrs = PCOL(AOP(result))->lit;
8451 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8452 if(AOP_SIZE(result) > 1) {
8453 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8461 setup_fsr (operand *ptr)
8464 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8466 /* also setup-up IRP */
8470 /*-----------------------------------------------------------------*/
8471 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8472 /* arbitrary pointer (__code, __data, generic) */
8473 /*-----------------------------------------------------------------*/
8475 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8482 if (!alreadyAddressed) setup_fsr (src);
8483 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8487 assert( AOP_SIZE(src) == 2 );
8489 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8491 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8492 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8493 call_libraryfunc ("__gptrget1");
8497 assert( AOP_SIZE(src) == 3 );
8499 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8501 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8503 call_libraryfunc ("__gptrget1");
8507 assert( !"unhandled pointer type" );
8512 /*-----------------------------------------------------------------*/
8513 /* emitPtrByteSet - emits code to set a byte from src through a */
8514 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8515 /*-----------------------------------------------------------------*/
8517 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8524 if (!alreadyAddressed) setup_fsr (dst);
8525 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8529 assert( !"trying to assign to __code pointer" );
8533 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8535 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8537 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8539 call_libraryfunc ("__gptrput1");
8543 assert( !"unhandled pointer type" );
8548 /*-----------------------------------------------------------------*/
8549 /* genUnpackBits - generates code for unpacking bits */
8550 /*-----------------------------------------------------------------*/
8551 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8553 int rsize; /* result size */
8554 sym_link *etype; /* bitfield type information */
8555 int blen; /* bitfield length */
8556 int bstr; /* bitfield starting bit within byte */
8559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8560 etype = getSpec(operandType(result));
8561 rsize = getSize (operandType (result));
8562 blen = SPEC_BLEN (etype);
8563 bstr = SPEC_BSTR (etype);
8565 /* single bit field case */
8567 if (ifx) { /* that is for an if statement */
8570 resolveIfx(&rIfx,ifx);
8571 if (ptype == -1) /* direct */
8572 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8574 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8575 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8576 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8580 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8581 for (i=0; i < AOP_SIZE(result); i++)
8582 emitpcode (POC_CLRF, popGet (AOP(result), i));
8587 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8588 /* adjust result below */
8595 emitPtrByteGet (left, ptype, FALSE);
8596 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8598 /* adjust result below */
8602 assert( !"unhandled pointer type" );
8605 /* move sign-/zero extended bit to result */
8606 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8607 emitpcode (POC_INCF, popGet (AOP(result), 0));
8609 emitpcode (POC_DECF, popGet (AOP(result), 0));
8611 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8615 else if (blen <= 8 && ((blen + bstr) <= 8))
8620 for (i=0; i < AOP_SIZE(result); i++)
8621 emitpcode (POC_CLRF, popGet (AOP(result), i));
8626 mov2w(AOP(left), 0);
8633 emitPtrByteGet (left, ptype, FALSE);
8637 assert( !"unhandled pointer type" );
8641 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8642 movwf(AOP(result), 0);
8643 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8645 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8647 /* signed bitfield */
8648 assert (bstr + blen > 0);
8649 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8650 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8651 emitpcode(POC_IORWF, popGet(AOP(result),0));
8653 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8657 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8661 /*-----------------------------------------------------------------*/
8662 /* genDataPointerGet - generates code when ptr offset is known */
8663 /*-----------------------------------------------------------------*/
8664 static void genDataPointerGet (operand *left,
8668 int size , offset = 0;
8671 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8674 /* optimization - most of the time, left and result are the same
8675 * address, but different types. for the pic code, we could omit
8678 aopOp(result,ic,TRUE);
8680 if (pic14_sameRegs (AOP(left), AOP(result)))
8683 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8685 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8687 size = AOP_SIZE(result);
8688 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8692 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8693 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8697 freeAsmop(left,NULL,ic,TRUE);
8698 freeAsmop(result,NULL,ic,TRUE);
8702 /*-----------------------------------------------------------------*/
8703 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8704 /*-----------------------------------------------------------------*/
8705 static void genNearPointerGet (operand *left,
8710 sym_link *ltype = operandType(left);
8711 sym_link *rtype = operandType(result);
8712 sym_link *retype= getSpec(rtype); /* bitfield type information */
8716 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8719 aopOp(left,ic,FALSE);
8721 /* if left is rematerialisable and
8722 result is not bit variable type and
8723 the left is pointer to data space i.e
8724 lower 128 bytes of space */
8725 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8726 !IS_BITVAR(retype) &&
8727 PIC_IS_DATA_PTR(ltype)) {
8728 genDataPointerGet (left,result,ic);
8732 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8733 aopOp (result,ic,FALSE);
8735 /* Check if can access directly instead of via a pointer */
8736 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8737 && AOP_SIZE(result) == 1)
8742 if (IS_BITFIELD(getSpec(operandType(result))))
8744 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8748 /* If the pointer value is not in a the FSR then need to put it in */
8749 /* Must set/reset IRP bit for use with FSR. */
8754 /* if bitfield then unpack the bits */
8756 /* we have can just get the values */
8757 int size = AOP_SIZE(result);
8760 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8764 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8766 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8767 if (AOP_TYPE(result) == AOP_LIT) {
8768 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8770 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8772 if (size && !direct)
8773 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8778 /* now some housekeeping stuff */
8780 /* we had to allocate for this iCode */
8781 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8782 freeAsmop(NULL,aop,ic,TRUE);
8784 /* we did not allocate which means left
8785 already in a pointer register, then
8786 if size > 0 && this could be used again
8787 we have to point it back to where it
8789 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8790 if (AOP_SIZE(result) > 1 &&
8791 !OP_SYMBOL(left)->remat &&
8792 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8794 int size = AOP_SIZE(result) - 1;
8796 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8802 freeAsmop(left,NULL,ic,TRUE);
8803 freeAsmop(result,NULL,ic,TRUE);
8808 /*-----------------------------------------------------------------*/
8809 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8810 /*-----------------------------------------------------------------*/
8811 static void genPagedPointerGet (operand *left,
8818 sym_link *rtype, *retype;
8821 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8823 rtype = operandType(result);
8824 retype= getSpec(rtype);
8826 aopOp(left,ic,FALSE);
8828 /* if the value is already in a pointer register
8829 then don't need anything more */
8830 if (!AOP_INPREG(AOP(left))) {
8831 /* otherwise get a free pointer register */
8833 preg = getFreePtr(ic,&aop,FALSE);
8834 pic14_emitcode("mov","%s,%s",
8836 aopGet(AOP(left),0,FALSE,TRUE));
8837 rname = preg->name ;
8839 rname = aopGet(AOP(left),0,FALSE,FALSE);
8841 freeAsmop(left,NULL,ic,TRUE);
8842 aopOp (result,ic,FALSE);
8844 /* if bitfield then unpack the bits */
8845 if (IS_BITFIELD(retype))
8846 genUnpackBits (result,left,rname,PPOINTER,0);
8848 /* we have can just get the values */
8849 int size = AOP_SIZE(result);
8854 pic14_emitcode("movx","a,@%s",rname);
8855 aopPut(AOP(result),"a",offset);
8860 pic14_emitcode("inc","%s",rname);
8864 /* now some housekeeping stuff */
8866 /* we had to allocate for this iCode */
8867 freeAsmop(NULL,aop,ic,TRUE);
8869 /* we did not allocate which means left
8870 already in a pointer register, then
8871 if size > 0 && this could be used again
8872 we have to point it back to where it
8874 if (AOP_SIZE(result) > 1 &&
8875 !OP_SYMBOL(left)->remat &&
8876 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8878 int size = AOP_SIZE(result) - 1;
8880 pic14_emitcode("dec","%s",rname);
8885 freeAsmop(result,NULL,ic,TRUE);
8890 /*-----------------------------------------------------------------*/
8891 /* genFarPointerGet - gget value from far space */
8892 /*-----------------------------------------------------------------*/
8893 static void genFarPointerGet (operand *left,
8894 operand *result, iCode *ic)
8897 sym_link *retype = getSpec(operandType(result));
8900 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8902 aopOp(left,ic,FALSE);
8904 /* if the operand is already in dptr
8905 then we do nothing else we move the value to dptr */
8906 if (AOP_TYPE(left) != AOP_STR) {
8907 /* if this is remateriazable */
8908 if (AOP_TYPE(left) == AOP_IMMD)
8909 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8910 else { /* we need to get it byte by byte */
8911 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8912 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8913 if (options.model == MODEL_FLAT24)
8915 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8919 /* so dptr know contains the address */
8920 freeAsmop(left,NULL,ic,TRUE);
8921 aopOp(result,ic,FALSE);
8923 /* if bit then unpack */
8924 if (IS_BITFIELD(retype))
8925 genUnpackBits(result,left,"dptr",FPOINTER,0);
8927 size = AOP_SIZE(result);
8931 pic14_emitcode("movx","a,@dptr");
8932 aopPut(AOP(result),"a",offset++);
8934 pic14_emitcode("inc","dptr");
8938 freeAsmop(result,NULL,ic,TRUE);
8943 /*-----------------------------------------------------------------*/
8944 /* genCodePointerGet - get value from code space */
8945 /*-----------------------------------------------------------------*/
8946 static void genCodePointerGet (operand *left,
8947 operand *result, iCode *ic)
8950 sym_link *retype = getSpec(operandType(result));
8952 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8954 aopOp(left,ic,FALSE);
8956 /* if the operand is already in dptr
8957 then we do nothing else we move the value to dptr */
8958 if (AOP_TYPE(left) != AOP_STR) {
8959 /* if this is remateriazable */
8960 if (AOP_TYPE(left) == AOP_IMMD)
8961 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8962 else { /* we need to get it byte by byte */
8963 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8964 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8965 if (options.model == MODEL_FLAT24)
8967 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8971 /* so dptr know contains the address */
8972 freeAsmop(left,NULL,ic,TRUE);
8973 aopOp(result,ic,FALSE);
8975 /* if bit then unpack */
8976 if (IS_BITFIELD(retype))
8977 genUnpackBits(result,left,"dptr",CPOINTER,0);
8979 size = AOP_SIZE(result);
8983 pic14_emitcode("clr","a");
8984 pic14_emitcode("movc","a,@a+dptr");
8985 aopPut(AOP(result),"a",offset++);
8987 pic14_emitcode("inc","dptr");
8991 freeAsmop(result,NULL,ic,TRUE);
8994 /*-----------------------------------------------------------------*/
8995 /* genGenPointerGet - gget value from generic pointer space */
8996 /*-----------------------------------------------------------------*/
8997 static void genGenPointerGet (operand *left,
8998 operand *result, iCode *ic)
9001 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9002 aopOp(left,ic,FALSE);
9003 aopOp(result,ic,FALSE);
9006 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9008 if (IS_BITFIELD(getSpec(operandType(result))))
9010 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9015 /* emit call to __gptrget */
9016 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9017 int size = AOP_SIZE(result);
9020 assert (size > 0 && size <= 4);
9022 /* pass arguments */
9023 assert (AOP_SIZE(left) == 3);
9024 mov2w(AOP(left), 0);
9025 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9026 mov2w(AOP(left), 1);
9027 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9028 mov2w(AOP(left), 2);
9029 call_libraryfunc (func[size]);
9032 movwf (AOP(result), --size);
9034 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9035 movwf (AOP(result), size);
9039 freeAsmop(left,NULL,ic,TRUE);
9040 freeAsmop(result,NULL,ic,TRUE);
9044 /*-----------------------------------------------------------------*/
9045 /* genConstPointerGet - get value from const generic pointer space */
9046 /*-----------------------------------------------------------------*/
9047 static void genConstPointerGet (operand *left,
9048 operand *result, iCode *ic)
9050 //sym_link *retype = getSpec(operandType(result));
9052 symbol *albl, *blbl;//, *clbl;
9059 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9060 aopOp(left,ic,FALSE);
9061 aopOp(result,ic,FALSE);
9063 size = AOP_SIZE(result);
9065 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9067 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9069 lit = op_isLitLike (left);
9070 poc = lit ? POC_MOVLW : POC_MOVFW;
9072 if (IS_BITFIELD(getSpec(operandType(result))))
9074 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9079 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9080 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9081 assert (size > 0 && size <= 4);
9084 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9086 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9087 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9088 call_libraryfunc (func[size]);
9090 movwf(AOP(result),size-1);
9091 for (i = 1; i < size; i++)
9093 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9094 movwf(AOP(result),size - 1 - i);
9099 freeAsmop(left,NULL,ic,TRUE);
9100 freeAsmop(result,NULL,ic,TRUE);
9103 /*-----------------------------------------------------------------*/
9104 /* genPointerGet - generate code for pointer get */
9105 /*-----------------------------------------------------------------*/
9106 static void genPointerGet (iCode *ic)
9108 operand *left, *result ;
9109 sym_link *type, *etype;
9113 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9116 result = IC_RESULT(ic) ;
9118 /* depending on the type of pointer we need to
9119 move it to the correct pointer register */
9120 type = operandType(left);
9121 etype = getSpec(type);
9123 if (IS_PTR_CONST(type))
9124 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9126 /* if left is of type of pointer then it is simple */
9127 if (IS_PTR(type) && !IS_FUNC(type->next))
9128 p_type = DCL_TYPE(type);
9130 /* we have to go by the storage class */
9131 p_type = PTR_TYPE(SPEC_OCLS(etype));
9133 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9135 if (SPEC_OCLS(etype)->codesp ) {
9136 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9137 //p_type = CPOINTER ;
9140 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9141 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9142 /*p_type = FPOINTER ;*/
9144 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9145 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9146 /* p_type = PPOINTER; */
9148 if (SPEC_OCLS(etype) == idata )
9149 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9150 /* p_type = IPOINTER; */
9152 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9153 /* p_type = POINTER ; */
9156 /* now that we have the pointer type we assign
9157 the pointer values */
9163 genNearPointerGet (left,result,ic);
9167 genPagedPointerGet(left,result,ic);
9171 genFarPointerGet (left,result,ic);
9175 genConstPointerGet (left,result,ic);
9179 genGenPointerGet (left,result,ic);
9182 assert ( !"unhandled pointer type" );
9188 /*-----------------------------------------------------------------*/
9189 /* genPackBits - generates code for packed bit storage */
9190 /*-----------------------------------------------------------------*/
9191 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9193 int blen; /* bitfield length */
9194 int bstr; /* bitfield starting bit within byte */
9195 int litval; /* source literal value (if AOP_LIT) */
9196 unsigned char mask; /* bitmask within current byte */
9199 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9201 blen = SPEC_BLEN (etype);
9202 bstr = SPEC_BSTR (etype);
9204 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9205 if ((blen <= 8) && ((bstr + blen) <= 8))
9207 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9208 (unsigned char) (0xFF >> (8 - bstr)));
9210 if (AOP_TYPE (right) == AOP_LIT)
9212 /* Case with a bitfield length <8 and literal source */
9213 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9220 if (AOP(result)->type == AOP_PCODE)
9221 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9223 pcop = popGet(AOP(result),0);
9224 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9230 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9234 assert( !"trying to assign to bitfield via pointer to __code space" );
9238 emitPtrByteGet(result, p_type, FALSE);
9240 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9242 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9244 emitPtrByteSet(result, p_type, TRUE);
9248 assert( !"unhandled pointer type" );
9250 } // switch (p_type)
9253 litval = lit << bstr;
9254 litval &= (~mask) & 0x00ff;
9259 mov2w (AOP(result), 0);
9260 if ((litval|mask) != 0x00ff)
9261 emitpcode(POC_ANDLW, popGetLit (mask));
9263 emitpcode(POC_IORLW, popGetLit (litval));
9264 movwf (AOP(result), 0);
9270 emitPtrByteGet(result, p_type, FALSE);
9271 if ((litval|mask) != 0x00ff)
9272 emitpcode(POC_ANDLW, popGetLit (mask));
9274 emitpcode(POC_IORLW, popGetLit (litval));
9275 emitPtrByteSet(result, p_type, TRUE);
9279 assert( !"trying to assign to bitfield via pointer to __code space" );
9283 assert( !"unhandled pointer type" );
9290 /* right is no literal */
9295 /* Note more efficient code, of pre clearing bit then only setting it if required,
9296 * can only be done if it is known that the result is not a SFR */
9297 emitpcode(POC_RRFW,popGet(AOP(right),0));
9299 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9301 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9307 emitPtrByteGet (result, p_type, FALSE);
9308 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9309 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9310 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9311 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9312 emitPtrByteSet (result, p_type, TRUE);
9316 assert( !"trying to assign to bitfield via pointer to __code space" );
9320 assert( !"unhandled pointer type" );
9325 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9326 pCodeOp *temp = popGetTempReg ();
9328 mov2w (AOP(right), 0);
9330 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9332 emitpcode(POC_MOVWF, temp);
9334 AccLsh (temp, bstr);
9340 mov2w (AOP(result), 0);
9341 emitpcode(POC_ANDLW, popGetLit (mask));
9342 emitpcode(POC_IORFW, temp);
9343 movwf (AOP(result), 0);
9349 emitPtrByteGet (result, p_type, FALSE);
9350 emitpcode(POC_ANDLW, popGetLit (mask));
9351 emitpcode(POC_IORFW, temp);
9352 emitPtrByteSet (result, p_type, TRUE);
9356 assert( !"trying to assign to bitfield via pointer to __code space" );
9360 assert( !"unhandled pointer type" );
9364 popReleaseTempReg (temp);
9366 } // if (AOP(right)->type != AOP_LIT)
9368 } // if (blen <= 8 && ((blen + bstr) <= 8))
9370 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9373 /*-----------------------------------------------------------------*/
9374 /* genDataPointerSet - remat pointer to data space */
9375 /*-----------------------------------------------------------------*/
9376 static void genDataPointerSet(operand *right,
9380 int size, offset = 0 ;
9384 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9385 aopOp(right,ic,FALSE);
9386 aopOp(result,ic,FALSE);
9388 assert (IS_SYMOP(result));
9389 assert (IS_PTR(OP_SYM_TYPE(result)));
9391 if (AOP_TYPE(right) == AOP_LIT)
9394 size = AOP_SIZE(right);
9395 ressize = getSize(OP_SYM_ETYPE(result));
9396 if (size > ressize) size = ressize;
9397 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9399 //assert( !"what's going on here?" );
9402 if ( AOP_TYPE(result) == AOP_PCODE) {
9403 fprintf(stderr,"genDataPointerSet %s, %d\n",
9404 AOP(result)->aopu.pcop->name,
9405 PCOI(AOP(result)->aopu.pcop)->offset);
9409 // tsd, was l+1 - the underline `_' prefix was being stripped
9411 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9413 if (AOP_TYPE(right) == AOP_LIT) {
9414 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9415 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9417 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9418 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9420 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9423 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9424 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9425 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9431 freeAsmop(right,NULL,ic,TRUE);
9432 freeAsmop(result,NULL,ic,TRUE);
9435 /*-----------------------------------------------------------------*/
9436 /* genNearPointerSet - pic14_emitcode for near pointer put */
9437 /*-----------------------------------------------------------------*/
9438 static void genNearPointerSet (operand *right,
9443 sym_link *ptype = operandType(result);
9444 sym_link *retype = getSpec(operandType(right));
9445 sym_link *letype = getSpec(ptype);
9450 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9451 aopOp(result,ic,FALSE);
9454 /* if the result is rematerializable &
9455 in data space & not a bit variable */
9456 //if (AOP_TYPE(result) == AOP_IMMD &&
9457 if (AOP_TYPE(result) == AOP_PCODE &&
9458 PIC_IS_DATA_PTR(ptype) &&
9459 !IS_BITVAR (retype) &&
9460 !IS_BITVAR (letype)) {
9461 genDataPointerSet (right,result,ic);
9462 freeAsmop(result,NULL,ic,TRUE);
9467 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9468 aopOp(right,ic,FALSE);
9469 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9471 /* Check if can access directly instead of via a pointer */
9472 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9476 if (IS_BITFIELD (letype))
9478 genPackBits (letype, result, right, direct?-1:POINTER);
9482 /* If the pointer value is not in a the FSR then need to put it in */
9483 /* Must set/reset IRP bit for use with FSR. */
9484 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9489 /* we have can just get the values */
9490 int size = AOP_SIZE(right);
9493 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9495 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9497 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9499 if (AOP_TYPE(right) == AOP_LIT) {
9500 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9502 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9505 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9507 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9509 if (size && !direct)
9510 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9515 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9516 /* now some housekeeping stuff */
9518 /* we had to allocate for this iCode */
9519 freeAsmop(NULL,aop,ic,TRUE);
9521 /* we did not allocate which means left
9522 already in a pointer register, then
9523 if size > 0 && this could be used again
9524 we have to point it back to where it
9526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9527 if (AOP_SIZE(right) > 1 &&
9528 !OP_SYMBOL(result)->remat &&
9529 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9531 int size = AOP_SIZE(right) - 1;
9533 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9537 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9540 freeAsmop(right,NULL,ic,TRUE);
9541 freeAsmop(result,NULL,ic,TRUE);
9545 /*-----------------------------------------------------------------*/
9546 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9547 /*-----------------------------------------------------------------*/
9548 static void genPagedPointerSet (operand *right,
9558 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9560 retype= getSpec(operandType(right));
9562 aopOp(result,ic,FALSE);
9564 /* if the value is already in a pointer register
9565 then don't need anything more */
9566 if (!AOP_INPREG(AOP(result))) {
9567 /* otherwise get a free pointer register */
9569 preg = getFreePtr(ic,&aop,FALSE);
9570 pic14_emitcode("mov","%s,%s",
9572 aopGet(AOP(result),0,FALSE,TRUE));
9573 rname = preg->name ;
9575 rname = aopGet(AOP(result),0,FALSE,FALSE);
9577 freeAsmop(result,NULL,ic,TRUE);
9578 aopOp (right,ic,FALSE);
9580 /* if bitfield then unpack the bits */
9581 if (IS_BITFIELD(retype))
9582 genPackBits (retype,result,right,rname,PPOINTER);
9584 /* we have can just get the values */
9585 int size = AOP_SIZE(right);
9589 l = aopGet(AOP(right),offset,FALSE,TRUE);
9592 pic14_emitcode("movx","@%s,a",rname);
9595 pic14_emitcode("inc","%s",rname);
9601 /* now some housekeeping stuff */
9603 /* we had to allocate for this iCode */
9604 freeAsmop(NULL,aop,ic,TRUE);
9606 /* we did not allocate which means left
9607 already in a pointer register, then
9608 if size > 0 && this could be used again
9609 we have to point it back to where it
9611 if (AOP_SIZE(right) > 1 &&
9612 !OP_SYMBOL(result)->remat &&
9613 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9615 int size = AOP_SIZE(right) - 1;
9617 pic14_emitcode("dec","%s",rname);
9622 freeAsmop(right,NULL,ic,TRUE);
9627 /*-----------------------------------------------------------------*/
9628 /* genFarPointerSet - set value from far space */
9629 /*-----------------------------------------------------------------*/
9630 static void genFarPointerSet (operand *right,
9631 operand *result, iCode *ic)
9634 sym_link *retype = getSpec(operandType(right));
9637 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9638 aopOp(result,ic,FALSE);
9640 /* if the operand is already in dptr
9641 then we do nothing else we move the value to dptr */
9642 if (AOP_TYPE(result) != AOP_STR) {
9643 /* if this is remateriazable */
9644 if (AOP_TYPE(result) == AOP_IMMD)
9645 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9646 else { /* we need to get it byte by byte */
9647 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9648 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9649 if (options.model == MODEL_FLAT24)
9651 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9655 /* so dptr know contains the address */
9656 freeAsmop(result,NULL,ic,TRUE);
9657 aopOp(right,ic,FALSE);
9659 /* if bit then unpack */
9660 if (IS_BITFIELD(retype))
9661 genPackBits(retype,result,right,"dptr",FPOINTER);
9663 size = AOP_SIZE(right);
9667 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9669 pic14_emitcode("movx","@dptr,a");
9671 pic14_emitcode("inc","dptr");
9675 freeAsmop(right,NULL,ic,TRUE);
9679 /*-----------------------------------------------------------------*/
9680 /* genGenPointerSet - set value from generic pointer space */
9681 /*-----------------------------------------------------------------*/
9682 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9684 sym_link *retype = getSpec(operandType(result));
9687 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9688 aopOp(right,ic,FALSE);
9689 aopOp(result,ic,FALSE);
9692 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9694 if (IS_BITFIELD(retype))
9696 genPackBits (retype, result, right, GPOINTER);
9701 /* emit call to __gptrput */
9702 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9703 int size = AOP_SIZE(right);
9706 assert (size == getSize(OP_SYM_ETYPE(result)));
9707 assert (size > 0 && size <= 4);
9709 /* pass arguments */
9710 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9716 mov2w_op (right, off);
9717 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9722 assert (AOP_SIZE(result) == 3);
9723 mov2w(AOP(result), 0);
9724 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9725 mov2w(AOP(result), 1);
9726 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9727 mov2w(AOP(result), 2);
9728 call_libraryfunc (func[size]);
9731 freeAsmop(right,NULL,ic,TRUE);
9732 freeAsmop(result,NULL,ic,TRUE);
9735 /*-----------------------------------------------------------------*/
9736 /* genPointerSet - stores the value into a pointer location */
9737 /*-----------------------------------------------------------------*/
9738 static void genPointerSet (iCode *ic)
9740 operand *right, *result ;
9741 sym_link *type, *etype;
9745 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9747 right = IC_RIGHT(ic);
9748 result = IC_RESULT(ic) ;
9750 /* depending on the type of pointer we need to
9751 move it to the correct pointer register */
9752 type = operandType(result);
9753 etype = getSpec(type);
9754 /* if left is of type of pointer then it is simple */
9755 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9756 p_type = DCL_TYPE(type);
9759 /* we have to go by the storage class */
9760 p_type = PTR_TYPE(SPEC_OCLS(etype));
9762 /* if (SPEC_OCLS(etype)->codesp ) { */
9763 /* p_type = CPOINTER ; */
9766 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9767 /* p_type = FPOINTER ; */
9769 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9770 /* p_type = PPOINTER ; */
9772 /* if (SPEC_OCLS(etype) == idata ) */
9773 /* p_type = IPOINTER ; */
9775 /* p_type = POINTER ; */
9778 /* now that we have the pointer type we assign
9779 the pointer values */
9785 genNearPointerSet (right,result,ic);
9789 genPagedPointerSet (right,result,ic);
9793 genFarPointerSet (right,result,ic);
9797 genGenPointerSet (right,result,ic);
9801 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9802 "genPointerSet: illegal pointer type");
9806 /*-----------------------------------------------------------------*/
9807 /* genIfx - generate code for Ifx statement */
9808 /*-----------------------------------------------------------------*/
9809 static void genIfx (iCode *ic, iCode *popIc)
9811 operand *cond = IC_COND(ic);
9815 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9817 aopOp(cond,ic,FALSE);
9819 /* get the value into acc */
9820 if (AOP_TYPE(cond) != AOP_CRY)
9821 pic14_toBoolean(cond);
9825 /* if there was something to be popped then do it */
9831 /* This assumes that CARRY is set iff cond is true */
9834 assert (!IC_FALSE(ic));
9835 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9837 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9839 assert (IC_FALSE(ic));
9840 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9842 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9846 static int hasWarned = 0;
9849 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9856 /* now Z is set iff !cond */
9859 assert (!IC_FALSE(ic));
9861 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9864 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9870 /* the result is now in the accumulator */
9871 freeAsmop(cond,NULL,ic,TRUE);
9874 /*-----------------------------------------------------------------*/
9875 /* genAddrOf - generates code for address of */
9876 /*-----------------------------------------------------------------*/
9877 static void genAddrOf (iCode *ic)
9879 operand *right, *result, *left;
9883 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9886 //aopOp(IC_RESULT(ic),ic,FALSE);
9888 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9889 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9890 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9892 DEBUGpic14_AopType(__LINE__,left,right,result);
9893 assert (IS_SYMOP (left));
9895 /* sanity check: generic pointers to code space are not yet supported,
9896 * pionters to codespace must not be assigned addresses of __data values. */
9898 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9899 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)));
9900 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)));
9901 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)));
9902 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)));
9905 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9906 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9907 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9908 OP_SYMBOL(left)->name);
9909 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9910 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9911 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9912 OP_SYMBOL(left)->name);
9915 size = AOP_SIZE(IC_RESULT(ic));
9916 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9918 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9923 /* fixing bug #863624, reported from (errolv) */
9924 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9925 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9928 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9929 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9934 if (IS_GENPTR(OP_SYM_TYPE(result)))
9936 /* provide correct tag */
9937 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9938 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9939 movwf (AOP(result), 2);
9942 freeAsmop(left,NULL,ic,FALSE);
9943 freeAsmop(result,NULL,ic,TRUE);
9948 /*-----------------------------------------------------------------*/
9949 /* genFarFarAssign - assignment when both are in far space */
9950 /*-----------------------------------------------------------------*/
9951 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9953 int size = AOP_SIZE(right);
9956 /* first push the right side on to the stack */
9958 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9960 pic14_emitcode ("push","acc");
9963 freeAsmop(right,NULL,ic,FALSE);
9964 /* now assign DPTR to result */
9965 aopOp(result,ic,FALSE);
9966 size = AOP_SIZE(result);
9968 pic14_emitcode ("pop","acc");
9969 aopPut(AOP(result),"a",--offset);
9971 freeAsmop(result,NULL,ic,FALSE);
9976 /*-----------------------------------------------------------------*/
9977 /* genAssign - generate code for assignment */
9978 /*-----------------------------------------------------------------*/
9979 static void genAssign (iCode *ic)
9981 operand *result, *right;
9982 int size, offset,know_W;
9983 unsigned long lit = 0L;
9985 result = IC_RESULT(ic);
9986 right = IC_RIGHT(ic) ;
9989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9991 /* if they are the same */
9992 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9995 aopOp(right,ic,FALSE);
9996 aopOp(result,ic,TRUE);
9998 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10000 /* if they are the same registers */
10001 if (pic14_sameRegs(AOP(right),AOP(result)))
10004 /* special case: assign from __code */
10005 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10006 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10007 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10008 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10009 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10011 emitpComment ("genAssign from CODESPACE");
10012 genConstPointerGet (right, result, ic);
10016 /* just for symmetry reasons... */
10017 if (!IS_ITEMP(result)
10018 && IS_SYMOP (result)
10019 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10021 assert ( !"cannot write to CODESPACE" );
10024 /* if the result is a bit */
10025 if (AOP_TYPE(result) == AOP_CRY) {
10027 /* if the right size is a literal then
10028 we know what the value is */
10029 if (AOP_TYPE(right) == AOP_LIT) {
10031 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10032 popGet(AOP(result),0));
10034 if (((int) operandLitValue(right)))
10035 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10036 AOP(result)->aopu.aop_dir,
10037 AOP(result)->aopu.aop_dir);
10039 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10040 AOP(result)->aopu.aop_dir,
10041 AOP(result)->aopu.aop_dir);
10045 /* the right is also a bit variable */
10046 if (AOP_TYPE(right) == AOP_CRY) {
10047 emitpcode(POC_BCF, popGet(AOP(result),0));
10048 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10049 emitpcode(POC_BSF, popGet(AOP(result),0));
10051 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10052 AOP(result)->aopu.aop_dir,
10053 AOP(result)->aopu.aop_dir);
10054 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10055 AOP(right)->aopu.aop_dir,
10056 AOP(right)->aopu.aop_dir);
10057 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10058 AOP(result)->aopu.aop_dir,
10059 AOP(result)->aopu.aop_dir);
10063 /* we need to or */
10064 emitpcode(POC_BCF, popGet(AOP(result),0));
10065 pic14_toBoolean(right);
10067 emitpcode(POC_BSF, popGet(AOP(result),0));
10068 //aopPut(AOP(result),"a",0);
10072 /* bit variables done */
10074 size = AOP_SIZE(result);
10076 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10077 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10078 if(aopIdx(AOP(result),0) == 4) {
10079 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10080 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10081 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10084 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10090 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10091 if(AOP_TYPE(right) == AOP_LIT) {
10092 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10094 if(know_W != (int)(lit&0xff))
10095 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10097 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10099 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10101 } else if (AOP_TYPE(right) == AOP_CRY) {
10102 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10104 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10105 emitpcode(POC_INCF, popGet(AOP(result),0));
10108 mov2w_op (right, offset);
10109 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10117 freeAsmop (right,NULL,ic,FALSE);
10118 freeAsmop (result,NULL,ic,TRUE);
10121 /*-----------------------------------------------------------------*/
10122 /* genJumpTab - genrates code for jump table */
10123 /*-----------------------------------------------------------------*/
10124 static void genJumpTab (iCode *ic)
10130 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10132 aopOp(IC_JTCOND(ic),ic,FALSE);
10133 /* get the condition into accumulator */
10134 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10136 /* multiply by three */
10137 pic14_emitcode("add","a,acc");
10138 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10140 jtab = newiTempLabel(NULL);
10141 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10142 pic14_emitcode("jmp","@a+dptr");
10143 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10145 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10146 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10147 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10148 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10150 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10151 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10152 emitpLabel(jtab->key);
10154 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10156 /* now generate the jump labels */
10157 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10158 jtab = setNextItem(IC_JTLABELS(ic))) {
10159 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10160 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10166 /*-----------------------------------------------------------------*/
10167 /* genMixedOperation - gen code for operators between mixed types */
10168 /*-----------------------------------------------------------------*/
10170 TSD - Written for the PIC port - but this unfortunately is buggy.
10171 This routine is good in that it is able to efficiently promote
10172 types to different (larger) sizes. Unfortunately, the temporary
10173 variables that are optimized out by this routine are sometimes
10174 used in other places. So until I know how to really parse the
10175 iCode tree, I'm going to not be using this routine :(.
10177 static int genMixedOperation (iCode *ic)
10181 operand *result = IC_RESULT(ic);
10182 sym_link *ctype = operandType(IC_LEFT(ic));
10183 operand *right = IC_RIGHT(ic);
10189 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10191 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10197 nextright = IC_RIGHT(nextic);
10198 nextleft = IC_LEFT(nextic);
10199 nextresult = IC_RESULT(nextic);
10201 aopOp(right,ic,FALSE);
10202 aopOp(result,ic,FALSE);
10203 aopOp(nextright, nextic, FALSE);
10204 aopOp(nextleft, nextic, FALSE);
10205 aopOp(nextresult, nextic, FALSE);
10207 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10209 operand *t = right;
10213 pic14_emitcode(";remove right +","");
10215 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10217 operand *t = right;
10221 pic14_emitcode(";remove left +","");
10225 big = AOP_SIZE(nextleft);
10226 small = AOP_SIZE(nextright);
10228 switch(nextic->op) {
10231 pic14_emitcode(";optimize a +","");
10232 /* if unsigned or not an integral type */
10233 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10234 pic14_emitcode(";add a bit to something","");
10237 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10239 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10240 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10241 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10243 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10251 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10252 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10253 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10256 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10258 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10259 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10260 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10261 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10262 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10265 pic14_emitcode("rlf","known_zero,w");
10272 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10273 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10274 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10276 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10286 freeAsmop(right,NULL,ic,TRUE);
10287 freeAsmop(result,NULL,ic,TRUE);
10288 freeAsmop(nextright,NULL,ic,TRUE);
10289 freeAsmop(nextleft,NULL,ic,TRUE);
10291 nextic->generated = 1;
10298 /*-----------------------------------------------------------------*/
10299 /* genCast - gen code for casting */
10300 /*-----------------------------------------------------------------*/
10301 static void genCast (iCode *ic)
10303 operand *result = IC_RESULT(ic);
10304 sym_link *restype = operandType(result);
10305 sym_link *rtype = operandType(IC_RIGHT(ic));
10306 operand *right = IC_RIGHT(ic);
10310 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10311 /* if they are equivalent then do nothing */
10312 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10315 aopOp(right,ic,FALSE) ;
10316 aopOp(result,ic,FALSE);
10318 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10320 /* if the result is a bit */
10321 if (AOP_TYPE(result) == AOP_CRY) {
10322 assert(!"assigning to bit variables is not supported");
10325 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10327 size = AOP_SIZE(result);
10329 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10331 emitpcode(POC_CLRF, popGet(AOP(result),0));
10332 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10333 emitpcode(POC_INCF, popGet(AOP(result),0));
10336 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10341 if (IS_PTR(restype))
10343 operand *result = IC_RESULT(ic);
10344 //operand *left = IC_LEFT(ic);
10345 operand *right = IC_RIGHT(ic);
10348 /* copy common part */
10349 int max, size = AOP_SIZE(result);
10350 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10351 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10353 /* warn if we discard generic opinter tag */
10354 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10356 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10362 mov2w_op (right, size);
10363 movwf (AOP(result), size);
10366 /* upcast into generic pointer type? */
10367 if (IS_GENPTR(restype)
10368 && (size < AOP_SIZE(result))
10369 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10371 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10374 switch (DCL_TYPE(rtype))
10376 case POINTER: /* __data */
10377 case FPOINTER: /* __data */
10378 assert (AOP_SIZE(right) == 2);
10379 tag = GPTRTAG_DATA;
10382 case CPOINTER: /* __code */
10383 assert (AOP_SIZE(right) == 2);
10384 tag = GPTRTAG_CODE;
10387 case GPOINTER: /* unknown destination, __data or __code */
10388 /* assume __data space (address of immediate) */
10389 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10390 if (AOP(right)->code)
10391 tag = GPTRTAG_CODE;
10393 tag = GPTRTAG_DATA;
10397 assert (!"unhandled pointer type");
10400 /* convert other values into pointers to __data space */
10401 tag = GPTRTAG_DATA;
10404 assert (AOP_SIZE(result) == 3);
10406 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10408 emitpcode(POC_MOVLW, popGetLit(tag));
10409 movwf(AOP(result), 2);
10412 addSign(result, max, 0);
10417 /* if they are the same size : or less */
10418 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10420 /* if they are in the same place */
10421 if (pic14_sameRegs(AOP(right),AOP(result)))
10424 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10425 if (IS_PTR_CONST(rtype))
10426 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10427 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10428 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10430 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10431 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10432 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10433 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10434 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10435 if(AOP_SIZE(result) <2)
10436 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10440 /* if they in different places then copy */
10441 size = AOP_SIZE(result);
10444 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10445 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10447 //aopPut(AOP(result),
10448 // aopGet(AOP(right),offset,FALSE,FALSE),
10457 /* so we now know that the size of destination is greater
10458 than the size of the source.
10459 Now, if the next iCode is an operator then we might be
10460 able to optimize the operation without performing a cast.
10462 if(0 && genMixedOperation(ic)) {
10463 /* XXX: cannot optimize: must copy regs! */
10467 /* we move to result for the size of source */
10468 size = AOP_SIZE(right);
10471 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10472 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10476 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10479 freeAsmop(right,NULL,ic,TRUE);
10480 freeAsmop(result,NULL,ic,TRUE);
10484 /*-----------------------------------------------------------------*/
10485 /* genDjnz - generate decrement & jump if not zero instrucion */
10486 /*-----------------------------------------------------------------*/
10487 static int genDjnz (iCode *ic, iCode *ifx)
10489 symbol *lbl, *lbl1;
10491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10496 /* if the if condition has a false label
10497 then we cannot save */
10501 /* if the minus is not of the form
10503 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10504 !IS_OP_LITERAL(IC_RIGHT(ic)))
10507 if (operandLitValue(IC_RIGHT(ic)) != 1)
10510 /* if the size of this greater than one then no
10512 if (getSize(operandType(IC_RESULT(ic))) > 1)
10515 /* otherwise we can save BIG */
10516 lbl = newiTempLabel(NULL);
10517 lbl1= newiTempLabel(NULL);
10519 aopOp(IC_RESULT(ic),ic,FALSE);
10521 if (IS_AOP_PREG(IC_RESULT(ic))) {
10522 pic14_emitcode("dec","%s",
10523 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10524 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10525 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10529 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10530 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10532 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10533 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10536 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10537 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10538 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10539 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10542 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10543 ifx->generated = 1;
10547 /*-----------------------------------------------------------------*/
10548 /* genReceive - generate code for a receive iCode */
10549 /*-----------------------------------------------------------------*/
10550 static void genReceive (iCode *ic)
10553 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10555 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10556 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10557 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10559 int size = getSize(operandType(IC_RESULT(ic)));
10560 int offset = fReturnSizePic - size;
10562 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10563 fReturn[fReturnSizePic - offset - 1] : "acc"));
10566 aopOp(IC_RESULT(ic),ic,FALSE);
10567 size = AOP_SIZE(IC_RESULT(ic));
10570 pic14_emitcode ("pop","acc");
10571 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10576 aopOp(IC_RESULT(ic),ic,FALSE);
10578 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10579 assignResultValue(IC_RESULT(ic));
10582 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10585 /*-----------------------------------------------------------------*/
10586 /* genDummyRead - generate code for dummy read of volatiles */
10587 /*-----------------------------------------------------------------*/
10589 genDummyRead (iCode * ic)
10592 pic14_emitcode ("; genDummyRead","");
10593 pic14_emitcode ("; not implemented","");
10598 /*-----------------------------------------------------------------*/
10599 /* genpic14Code - generate code for pic14 based controllers */
10600 /*-----------------------------------------------------------------*/
10602 * At this point, ralloc.c has gone through the iCode and attempted
10603 * to optimize in a way suitable for a PIC. Now we've got to generate
10604 * PIC instructions that correspond to the iCode.
10606 * Once the instructions are generated, we'll pass through both the
10607 * peep hole optimizer and the pCode optimizer.
10608 *-----------------------------------------------------------------*/
10610 void genpic14Code (iCode *lic)
10617 lineHead = lineCurr = NULL;
10619 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10622 /* if debug information required */
10623 if (options.debug && currFunc) {
10625 debugFile->writeFunction (currFunc, lic);
10630 for (ic = lic ; ic ; ic = ic->next ) {
10632 //DEBUGpic14_emitcode(";ic","");
10633 //fprintf (stderr, "in ic loop\n");
10634 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10635 //ic->lineno, printCLine(ic->filename, ic->lineno));
10637 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10639 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10640 cline = printCLine (ic->filename, ic->lineno);
10641 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10642 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10643 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10646 if (options.iCodeInAsm) {
10647 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10649 /* if the result is marked as
10650 spilt and rematerializable or code for
10651 this has already been generated then
10653 if (resultRemat(ic) || ic->generated )
10656 /* depending on the operation */
10675 /* IPOP happens only when trying to restore a
10676 spilt live range, if there is an ifx statement
10677 following this pop then the if statement might
10678 be using some of the registers being popped which
10679 would destory the contents of the register so
10680 we need to check for this condition and handle it */
10682 ic->next->op == IFX &&
10683 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10684 genIfx (ic->next,ic);
10702 genEndFunction (ic);
10722 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10739 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10743 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10750 /* note these two are xlated by algebraic equivalence
10751 during parsing SDCC.y */
10752 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10753 "got '>=' or '<=' shouldn't have come here");
10757 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10769 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10773 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10777 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10801 genRightShift (ic);
10804 case GET_VALUE_AT_ADDRESS:
10809 if (POINTER_SET(ic))
10836 addSet(&_G.sendSet,ic);
10839 case DUMMY_READ_VOLATILE:
10844 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10851 /* now we are ready to call the
10852 peep hole optimizer */
10853 if (!options.nopeep) {
10854 peepHole (&lineHead);
10856 /* now do the actual printing */
10857 printLine (lineHead,codeOutFile);
10860 DFPRINTF((stderr,"printing pBlock\n\n"));
10861 printpBlock(stdout,pb);
10867 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10868 * (meaning: representing its own address) or not (referencing its contents).
10869 * This can only be decided based on the operand's type. */
10871 aop_isLitLike (asmop *aop)
10874 if (aop->type == AOP_LIT) return 1;
10875 if (aop->type == AOP_IMMD) return 1;
10876 if ((aop->type == AOP_PCODE) &&
10877 ((aop->aopu.pcop->type == PO_LITERAL)))
10879 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10880 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10887 op_isLitLike (operand *op)
10890 if (aop_isLitLike (AOP(op))) return 1;
10891 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10892 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;