1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* When changing these, you must also update the assembler template
48 * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA 0x00
50 #define GPTRTAG_CODE 0x80
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
66 /* max_key keeps track of the largest label number used in
67 a function. This is then used to adjust the label offset
68 for the next function.
71 static int GpsuedoStkPtr=0;
72 static int pic14_inISR = 0;
74 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
75 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
76 const char *AopType(short type);
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
80 /* this is the down and dirty file with all kinds of
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
85 static char *zero = "#0x00";
86 static char *one = "#0x01";
87 static char *spname = "sp";
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic14;
93 //static char *accUse[] = {"a","b"};
95 //static short rbank = -1;
107 /* Resolved ifx structure. This structure stores information
108 about an iCode ifx that makes it easier to generate code.
110 typedef struct resolvedIfx {
111 symbol *lbl; /* pointer to a label */
112 int condition; /* true or false ifx */
113 int generated; /* set true when the code associated with the ifx
117 extern int pic14_ptrRegReq ;
118 extern int pic14_nRegs;
119 extern struct dbuf_s *codeOutBuf;
120 static void saverbank (int, iCode *,bool);
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
126 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
134 /*-----------------------------------------------------------------*/
135 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
136 /* exponent of 2 is returned, otherwise -1 is */
138 /* note that this is similar to the function `powof2' in SDCCsymt */
142 /*-----------------------------------------------------------------*/
143 static int my_powof2 (unsigned long num)
146 if( (num & (num-1)) == 0) {
159 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
166 ((result) ? AOP_SIZE(result) : 0),
167 ((left) ? AopType(AOP_TYPE(left)) : "-"),
168 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169 ((left) ? AOP_SIZE(left) : 0),
170 ((right) ? AopType(AOP_TYPE(right)) : "-"),
171 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
172 ((right) ? AOP_SIZE(right) : 0));
176 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
181 ((result) ? AopType(AOP_TYPE(result)) : "-"),
182 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
183 ((left) ? AopType(AOP_TYPE(left)) : "-"),
184 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
185 ((right) ? AopType(AOP_TYPE(right)) : "-"),
186 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
190 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 char lb[INITIAL_INLINEASM];
194 unsigned char *lbp = (unsigned char *)lb;
196 if(!debug_verbose && !options.debug)
203 sprintf(lb,"%s\t",inst);
205 sprintf(lb,"%s",inst);
206 vsprintf(lb+(strlen(lb)),fmt,ap);
210 while (isspace(*lbp)) lbp++;
213 lineCurr = (lineCurr ?
214 connectLine(lineCurr,newLineNode(lb)) :
215 (lineHead = newLineNode(lb)));
216 lineCurr->isInline = _G.inLine;
217 lineCurr->isDebug = _G.debugLine;
219 addpCode2pBlock(pb,newpCodeCharP(lb));
224 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
226 #if defined (HAVE_VSNPRINTF)
227 vsnprintf (buf, size, fmt, ap);
228 #elif defined (HAVE_VSPRINTF)
229 vsprintf (buf, size, fmt, ap);
230 if (strlen (buf) >= size)
232 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
234 #elif defined (HAVE_SNPRINTF)
235 snprintf (buf, size, "vs(n)printf required");
236 #elif defined (HAVE_SRINTF)
237 sprintf (buf, "vs(n)printf required");
238 if (strlen (buf) >= size)
240 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
243 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
247 void emitpComment (const char *fmt, ...)
254 Safe_vsnprintf (buffer, 4096, fmt, va);
255 //fprintf (stderr, "%s\n" ,buffer);
256 addpCode2pBlock (pb, newpCodeCharP (buffer));
259 Safe_vsnprintf (buffer, 4096, fmt, va);
260 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
266 void emitpLabel(int key)
268 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
271 /* gen.h defines a macro emitpcode that should be used to call emitpcode
272 * as this allows for easy debugging (ever asked the question: where was
273 * this instruction geenrated? Here is the answer... */
274 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
277 addpCode2pBlock(pb,newpCode(poc,pcop));
279 static int has_warned = 0;
281 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
284 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
289 void emitpcodeNULLop(PIC_OPCODE poc)
292 addpCode2pBlock(pb,newpCode(poc,NULL));
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitcode - writes the code into a file : for now it is simple */
299 /*-----------------------------------------------------------------*/
300 void pic14_emitcode (char *inst,char *fmt, ...)
303 char lb[INITIAL_INLINEASM];
310 sprintf(lb,"%s\t",inst);
312 sprintf(lb,"%s",inst);
313 vsprintf(lb+(strlen(lb)),fmt,ap);
317 while (isspace(*lbp)) lbp++;
320 lineCurr = (lineCurr ?
321 connectLine(lineCurr,newLineNode(lb)) :
322 (lineHead = newLineNode(lb)));
323 lineCurr->isInline = _G.inLine;
324 lineCurr->isDebug = _G.debugLine;
325 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
328 addpCode2pBlock(pb,newpCodeCharP(lb));
333 /*-----------------------------------------------------------------*/
334 /* pic14_emitDebuggerSymbol - associate the current code location */
335 /* with a debugger symbol */
336 /*-----------------------------------------------------------------*/
338 pic14_emitDebuggerSymbol (char * debugSym)
341 pic14_emitcode ("", ";%s ==.", debugSym);
346 /*-----------------------------------------------------------------*/
347 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
348 /*-----------------------------------------------------------------*/
349 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
351 bool r0iu = FALSE , r1iu = FALSE;
352 bool r0ou = FALSE , r1ou = FALSE;
354 /* the logic: if r0 & r1 used in the instruction
355 then we are in trouble otherwise */
357 /* first check if r0 & r1 are used by this
358 instruction, in which case we are in trouble */
359 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
360 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
365 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
366 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
368 /* if no usage of r0 then return it */
369 if (!r0iu && !r0ou) {
370 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
371 (*aopp)->type = AOP_R0;
373 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
376 /* if no usage of r1 then return it */
377 if (!r1iu && !r1ou) {
378 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
379 (*aopp)->type = AOP_R1;
381 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
384 /* now we know they both have usage */
385 /* if r0 not used in this instruction */
387 /* push it if not already pushed */
389 //pic14_emitcode ("push","%s",
390 // pic14_regWithIdx(R0_IDX)->dname);
394 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
395 (*aopp)->type = AOP_R0;
397 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
400 /* if r1 not used then */
403 /* push it if not already pushed */
405 //pic14_emitcode ("push","%s",
406 // pic14_regWithIdx(R1_IDX)->dname);
410 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
411 (*aopp)->type = AOP_R1;
412 return pic14_regWithIdx(R1_IDX);
416 /* I said end of world but not quite end of world yet */
417 /* if this is a result then we can push it on the stack*/
419 (*aopp)->type = AOP_STK;
423 /* other wise this is true end of the world */
424 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
425 "getFreePtr should never reach here");
430 /*-----------------------------------------------------------------*/
431 /* newAsmop - creates a new asmOp */
432 /*-----------------------------------------------------------------*/
433 asmop *newAsmop (short type)
437 aop = Safe_calloc(1,sizeof(asmop));
442 static void genSetDPTR(int n)
446 pic14_emitcode(";", "Select standard DPTR");
447 pic14_emitcode("mov", "dps, #0x00");
451 pic14_emitcode(";", "Select alternate DPTR");
452 pic14_emitcode("mov", "dps, #0x01");
456 /*-----------------------------------------------------------------*/
457 /* resolveIfx - converts an iCode ifx into a form more useful for */
458 /* generating code */
459 /*-----------------------------------------------------------------*/
460 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
465 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
467 resIfx->condition = 1; /* assume that the ifx is true */
468 resIfx->generated = 0; /* indicate that the ifx has not been used */
471 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
473 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
474 __FUNCTION__,__LINE__,resIfx->lbl->key);
478 resIfx->lbl = IC_TRUE(ifx);
480 resIfx->lbl = IC_FALSE(ifx);
481 resIfx->condition = 0;
485 DEBUGpic14_emitcode("; ***","ifx true is non-null");
487 DEBUGpic14_emitcode("; ***","ifx false is non-null");
491 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
494 /*-----------------------------------------------------------------*/
495 /* pointerCode - returns the code for a pointer type */
496 /*-----------------------------------------------------------------*/
498 static int pointerCode (sym_link *etype)
501 return PTR_TYPE(SPEC_OCLS(etype));
506 /*-----------------------------------------------------------------*/
507 /* aopForSym - for a true symbol */
508 /*-----------------------------------------------------------------*/
509 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
512 memmap *space= SPEC_OCLS(sym->etype);
514 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
515 /* if already has one */
520 /* assign depending on the storage class */
521 /* if it is on the stack or indirectly addressable */
522 /* space we need to assign either r0 or r1 to it */
523 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
524 sym->aop = aop = newAsmop(0);
525 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
526 aop->size = getSize(sym->type);
528 /* now assign the address of the variable to
529 the pointer register */
530 if (aop->type != AOP_STK) {
534 pic14_emitcode("push","acc");
536 pic14_emitcode("mov","a,_bp");
537 pic14_emitcode("add","a,#0x%02x",
539 ((char)(sym->stack - _G.nRegsSaved )) :
540 ((char)sym->stack)) & 0xff);
541 pic14_emitcode("mov","%s,a",
542 aop->aopu.aop_ptr->name);
545 pic14_emitcode("pop","acc");
547 pic14_emitcode("mov","%s,#%s",
548 aop->aopu.aop_ptr->name,
550 aop->paged = space->paged;
552 aop->aopu.aop_stk = sym->stack;
556 if (sym->onStack && options.stack10bit)
558 /* It's on the 10 bit stack, which is located in
562 //DEBUGpic14_emitcode(";","%d",__LINE__);
565 pic14_emitcode("push","acc");
567 pic14_emitcode("mov","a,_bp");
568 pic14_emitcode("add","a,#0x%02x",
570 ((char)(sym->stack - _G.nRegsSaved )) :
571 ((char)sym->stack)) & 0xff);
574 pic14_emitcode ("mov","dpx1,#0x40");
575 pic14_emitcode ("mov","dph1,#0x00");
576 pic14_emitcode ("mov","dpl1, a");
580 pic14_emitcode("pop","acc");
582 sym->aop = aop = newAsmop(AOP_DPTR2);
583 aop->size = getSize(sym->type);
588 //DEBUGpic14_emitcode(";","%d",__LINE__);
589 /* if in bit space */
590 if (IN_BITSPACE(space)) {
591 sym->aop = aop = newAsmop (AOP_CRY);
592 aop->aopu.aop_dir = sym->rname ;
593 aop->size = getSize(sym->type);
594 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
597 /* if it is in direct space */
598 if (IN_DIRSPACE(space)) {
599 sym->aop = aop = newAsmop (AOP_DIR);
600 aop->aopu.aop_dir = sym->rname ;
601 aop->size = getSize(sym->type);
602 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
606 /* special case for a function */
607 if (IS_FUNC(sym->type)) {
609 sym->aop = aop = newAsmop(AOP_PCODE);
610 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
611 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
612 PCOI(aop->aopu.pcop)->_function = 1;
613 PCOI(aop->aopu.pcop)->index = 0;
614 aop->size = FPTRSIZE;
616 sym->aop = aop = newAsmop(AOP_IMMD);
617 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
618 strcpy(aop->aopu.aop_immd,sym->rname);
619 aop->size = FPTRSIZE;
621 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
625 if (IS_ARRAY(sym->type)) {
626 sym->aop = aop = newAsmop(AOP_PCODE);
627 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
628 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
629 PCOI(aop->aopu.pcop)->_function = 0;
630 PCOI(aop->aopu.pcop)->index = 0;
631 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
633 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
637 /* only remaining is far space */
638 /* in which case DPTR gets the address */
639 sym->aop = aop = newAsmop(AOP_PCODE);
641 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
642 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
643 PCOI(aop->aopu.pcop)->index = 0;
645 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
646 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
648 allocDirReg (IC_LEFT(ic));
650 aop->size = FPTRSIZE;
652 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
653 sym->aop = aop = newAsmop(AOP_DPTR);
654 pic14_emitcode ("mov","dptr,#%s", sym->rname);
655 aop->size = getSize(sym->type);
657 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
660 /* if it is in code space */
661 if (IN_CODESPACE(space))
667 /*-----------------------------------------------------------------*/
668 /* aopForRemat - rematerialzes an object */
669 /*-----------------------------------------------------------------*/
670 static asmop *aopForRemat (operand *op) // x symbol *sym)
672 symbol *sym = OP_SYMBOL(op);
674 asmop *aop = newAsmop(AOP_PCODE);
678 ic = sym->rematiCode;
680 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
681 if(IS_OP_POINTER(op)) {
682 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
686 val += (int) operandLitValue(IC_RIGHT(ic));
687 } else if (ic->op == '-') {
688 val -= (int) operandLitValue(IC_RIGHT(ic));
692 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
695 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
696 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
697 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
698 PCOI(aop->aopu.pcop)->index = val;
700 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
701 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
702 val, IS_PTR_CONST(operandType(op)));
704 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
706 allocDirReg (IC_LEFT(ic));
711 int aopIdx (asmop *aop, int offset)
716 if(aop->type != AOP_REG)
719 return aop->aopu.aop_reg[offset]->rIdx;
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common */
724 /*-----------------------------------------------------------------*/
725 static bool regsInCommon (operand *op1, operand *op2)
730 /* if they have registers in common */
731 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
734 sym1 = OP_SYMBOL(op1);
735 sym2 = OP_SYMBOL(op2);
737 if (sym1->nRegs == 0 || sym2->nRegs == 0)
740 for (i = 0 ; i < sym1->nRegs ; i++) {
745 for (j = 0 ; j < sym2->nRegs ;j++ ) {
749 if (sym2->regs[j] == sym1->regs[i])
757 /*-----------------------------------------------------------------*/
758 /* operandsEqu - equivalent */
759 /*-----------------------------------------------------------------*/
760 static bool operandsEqu ( operand *op1, operand *op2)
764 /* if they not symbols */
765 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
768 sym1 = OP_SYMBOL(op1);
769 sym2 = OP_SYMBOL(op2);
771 /* if both are itemps & one is spilt
772 and the other is not then false */
773 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
774 sym1->isspilt != sym2->isspilt )
777 /* if they are the same */
781 if (sym1->rname[0] && sym2->rname[0]
782 && strcmp (sym1->rname, sym2->rname) == 0)
786 /* if left is a tmp & right is not */
790 (sym1->usl.spillLoc == sym2))
797 (sym2->usl.spillLoc == sym1))
803 /*-----------------------------------------------------------------*/
804 /* pic14_sameRegs - two asmops have the same registers */
805 /*-----------------------------------------------------------------*/
806 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
813 if (aop1->type != AOP_REG ||
814 aop2->type != AOP_REG )
817 if (aop1->size != aop2->size )
820 for (i = 0 ; i < aop1->size ; i++ )
821 if (aop1->aopu.aop_reg[i] !=
822 aop2->aopu.aop_reg[i] )
828 /*-----------------------------------------------------------------*/
829 /* aopOp - allocates an asmop for an operand : */
830 /*-----------------------------------------------------------------*/
831 void aopOp (operand *op, iCode *ic, bool result)
840 /* if this a literal */
841 if (IS_OP_LITERAL(op)) {
842 op->aop = aop = newAsmop(AOP_LIT);
843 aop->aopu.aop_lit = op->operand.valOperand;
844 aop->size = getSize(operandType(op));
849 sym_link *type = operandType(op);
850 if(IS_PTR_CONST(type))
851 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
854 /* if already has a asmop then continue */
858 /* if the underlying symbol has a aop */
859 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
860 DEBUGpic14_emitcode(";","%d",__LINE__);
861 op->aop = OP_SYMBOL(op)->aop;
865 /* if this is a true symbol */
866 if (IS_TRUE_SYMOP(op)) {
867 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
868 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
872 /* this is a temporary : this has
878 e) can be a return use only */
883 /* if the type is a conditional */
884 if (sym->regType == REG_CND) {
885 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
890 /* if it is spilt then two situations
892 b) has a spill location */
893 if (sym->isspilt || sym->nRegs == 0) {
895 DEBUGpic14_emitcode(";","%d",__LINE__);
896 /* rematerialize it NOW */
899 sym->aop = op->aop = aop = aopForRemat (op);
900 aop->size = getSize(sym->type);
901 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
906 /* WREG is not usable as an ordinary operand with PIC architecture,
907 * one might introduce a scratch register that can be used to make
908 * WREG accesible as an operand... disable WREG for now */
911 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
912 aop->size = getSize(sym->type);
913 for ( i = 0 ; i < 2 ; i++ )
914 aop->aopu.aop_str[i] = accUse[i];
915 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
921 if(sym->isptr) { // && sym->uptr
922 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
923 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
925 //PCOI(aop->aopu.pcop)->_const = 0;
926 //PCOI(aop->aopu.pcop)->index = 0;
928 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
929 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
931 //allocDirReg (IC_LEFT(ic));
933 aop->size = getSize(sym->type);
934 DEBUGpic14_emitcode(";","%d",__LINE__);
941 aop = op->aop = sym->aop = newAsmop(AOP_STR);
942 aop->size = getSize(sym->type);
943 for ( i = 0 ; i < fReturnSizePic ; i++ )
944 aop->aopu.aop_str[i] = fReturn[i];
946 DEBUGpic14_emitcode(";","%d",__LINE__);
951 /* else spill location */
952 if (sym->usl.spillLoc)
954 asmop *oldAsmOp = NULL;
956 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
958 /* force a new aop if sizes differ */
959 oldAsmOp = sym->usl.spillLoc->aop;
960 sym->usl.spillLoc->aop = NULL;
962 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
963 __FUNCTION__,__LINE__,
964 sym->usl.spillLoc->rname,
965 sym->rname, sym->usl.spillLoc->offset);
967 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
968 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
970 /* Don't reuse the new aop, go with the last one */
971 sym->usl.spillLoc->aop = oldAsmOp;
973 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
974 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
976 sym->usl.spillLoc->offset);
977 aop->size = getSize(sym->type);
984 sym_link *type = operandType(op);
985 if(IS_PTR_CONST(type))
986 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
989 /* must be in a register */
990 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
991 sym->aop = op->aop = aop = newAsmop(AOP_REG);
992 aop->size = sym->nRegs;
993 for ( i = 0 ; i < sym->nRegs ;i++)
994 aop->aopu.aop_reg[i] = sym->regs[i];
997 /*-----------------------------------------------------------------*/
998 /* freeAsmop - free up the asmop given to an operand */
999 /*----------------------------------------------------------------*/
1000 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1017 /* depending on the asmop type only three cases need work AOP_RO
1018 , AOP_R1 && AOP_STK */
1020 switch (aop->type) {
1024 pic14_emitcode ("pop","ar0");
1028 bitVectUnSetBit(ic->rUsed,R0_IDX);
1034 pic14_emitcode ("pop","ar1");
1038 bitVectUnSetBit(ic->rUsed,R1_IDX);
1044 int stk = aop->aopu.aop_stk + aop->size;
1045 bitVectUnSetBit(ic->rUsed,R0_IDX);
1046 bitVectUnSetBit(ic->rUsed,R1_IDX);
1048 getFreePtr(ic,&aop,FALSE);
1050 if (options.stack10bit)
1052 /* I'm not sure what to do here yet... */
1055 "*** Warning: probably generating bad code for "
1056 "10 bit stack mode.\n");
1060 pic14_emitcode ("mov","a,_bp");
1061 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1062 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1064 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1068 pic14_emitcode("pop","acc");
1069 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1071 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1074 freeAsmop(op,NULL,ic,TRUE);
1076 pic14_emitcode("pop","ar0");
1081 pic14_emitcode("pop","ar1");
1089 /* all other cases just dealloc */
1093 OP_SYMBOL(op)->aop = NULL;
1094 /* if the symbol has a spill */
1096 SPIL_LOC(op)->aop = NULL;
1101 /*-----------------------------------------------------------------*/
1102 /* aopGet - for fetching value of the aop */
1103 /*-----------------------------------------------------------------*/
1104 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1109 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1110 /* offset is greater than
1112 if (offset > (aop->size - 1) &&
1113 aop->type != AOP_LIT)
1116 /* depending on type */
1117 switch (aop->type) {
1121 DEBUGpic14_emitcode(";","%d",__LINE__);
1122 /* if we need to increment it */
1123 while (offset > aop->coff) {
1124 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1128 while (offset < aop->coff) {
1129 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1133 aop->coff = offset ;
1135 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1136 return (dname ? "acc" : "a");
1138 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1139 rs = Safe_calloc(1,strlen(s)+1);
1145 DEBUGpic14_emitcode(";","%d",__LINE__);
1146 if (aop->type == AOP_DPTR2)
1151 while (offset > aop->coff) {
1152 pic14_emitcode ("inc","dptr");
1156 while (offset < aop->coff) {
1157 pic14_emitcode("lcall","__decdptr");
1163 pic14_emitcode("clr","a");
1164 pic14_emitcode("movc","a,@a+dptr");
1167 pic14_emitcode("movx","a,@dptr");
1170 if (aop->type == AOP_DPTR2)
1175 return (dname ? "acc" : "a");
1180 sprintf (s,"%s",aop->aopu.aop_immd);
1183 sprintf(s,"(%s >> %d)",
1188 aop->aopu.aop_immd);
1189 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1190 rs = Safe_calloc(1,strlen(s)+1);
1196 sprintf(s,"(%s + %d)",
1199 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1201 sprintf(s,"%s",aop->aopu.aop_dir);
1202 rs = Safe_calloc(1,strlen(s)+1);
1208 // return aop->aopu.aop_reg[offset]->dname;
1210 return aop->aopu.aop_reg[offset]->name;
1213 //pic14_emitcode(";","%d",__LINE__);
1214 return aop->aopu.aop_dir;
1217 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1218 return "AOP_accumulator_bug";
1221 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1222 rs = Safe_strdup(s);
1226 aop->coff = offset ;
1227 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1230 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1232 return aop->aopu.aop_str[offset];
1236 pCodeOp *pcop = aop->aopu.pcop;
1237 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1240 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1241 sprintf(s,"(%s+%d)", pcop->name,offset);
1243 DEBUGpic14_emitcode(";","%s",pcop->name);
1244 sprintf(s,"%s", pcop->name);
1247 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1250 rs = Safe_calloc(1,strlen(s)+1);
1256 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1257 "aopget got unsupported aop->type");
1262 /*-----------------------------------------------------------------*/
1263 /* popGetTempReg - create a new temporary pCodeOp */
1264 /*-----------------------------------------------------------------*/
1265 pCodeOp *popGetTempReg(void)
1270 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1271 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1272 PCOR(pcop)->r->wasUsed=1;
1273 PCOR(pcop)->r->isFree=0;
1279 /*-----------------------------------------------------------------*/
1280 /* popReleaseTempReg - create a new temporary pCodeOp */
1281 /*-----------------------------------------------------------------*/
1282 void popReleaseTempReg(pCodeOp *pcop)
1285 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1286 PCOR(pcop)->r->isFree = 1;
1289 /*-----------------------------------------------------------------*/
1290 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1291 /*-----------------------------------------------------------------*/
1292 pCodeOp *popGetLabel(unsigned int key)
1295 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1297 if(key>(unsigned int)max_key)
1300 return newpCodeOpLabel(NULL,key+100+labelOffset);
1303 /*-------------------------------------------------------------------*/
1304 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1305 /*-------------------------------------------------------------------*/
1306 pCodeOp *popGetHighLabel(unsigned int key)
1309 pcop = popGetLabel(key);
1310 PCOLAB(pcop)->offset = 1;
1314 /*-----------------------------------------------------------------*/
1315 /* popGetLit - asm operator to pcode operator conversion */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *popGetLit(unsigned int lit)
1320 return newpCodeOpLit((unsigned char)lit);
1323 /*-----------------------------------------------------------------*/
1324 /* popGetImmd - asm operator to pcode immediate conversion */
1325 /*-----------------------------------------------------------------*/
1326 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1329 return newpCodeOpImmd(name, offset,index, 0, is_func);
1332 extern set *externs;
1334 /*-----------------------------------------------------------------*/
1335 /* popGetWithString - asm operator to pcode operator conversion */
1336 /*-----------------------------------------------------------------*/
1337 pCodeOp *popGetWithString(char *str, int isExtern)
1343 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1347 pcop = newpCodeOp(str,PO_STR);
1348 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1353 pCodeOp *popGetExternal (char *str)
1355 pCodeOp *pcop = popGetWithString (str, 1);
1361 for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1363 if (!strcmp (str, sym->rname))
1369 sym = newSymbol(str, 0);
1370 strncpy(sym->rname, str, SDCC_NAME_MAX);
1371 addSet (&externs, sym);
1377 /*-----------------------------------------------------------------*/
1378 /* popRegFromString - */
1379 /*-----------------------------------------------------------------*/
1380 pCodeOp *popRegFromString(char *str, int size, int offset)
1383 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1384 pcop->type = PO_DIR;
1386 DEBUGpic14_emitcode(";","%d",__LINE__);
1391 pcop->name = Safe_calloc(1,strlen(str)+1);
1392 strcpy(pcop->name,str);
1394 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1396 PCOR(pcop)->r = dirregWithName(pcop->name);
1397 if(PCOR(pcop)->r == NULL) {
1398 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1399 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1400 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1402 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1404 PCOR(pcop)->instance = offset;
1409 /*-----------------------------------------------------------------*/
1410 /*-----------------------------------------------------------------*/
1411 pCodeOp *popRegFromIdx(int rIdx)
1415 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1416 __FUNCTION__,__LINE__,rIdx);
1418 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1420 PCOR(pcop)->rIdx = rIdx;
1421 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1422 PCOR(pcop)->r->isFree = 0;
1423 PCOR(pcop)->r->wasUsed = 1;
1425 pcop->type = PCOR(pcop)->r->pc_type;
1431 /*-----------------------------------------------------------------*/
1432 /* popGet - asm operator to pcode operator conversion */
1433 /*-----------------------------------------------------------------*/
1434 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1436 //char *s = buffer ;
1441 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1442 /* offset is greater than
1448 /* XXX: still needed for BIT operands (AOP_CRY) */
1449 if (offset > (aop->size - 1) &&
1450 aop->type != AOP_LIT &&
1451 aop->type != AOP_PCODE)
1453 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1454 return NULL; //zero;
1457 /* depending on type */
1458 switch (aop->type) {
1465 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1469 DEBUGpic14_emitcode(";","%d",__LINE__);
1470 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1473 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1475 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1476 pcop->type = PO_DIR;
1478 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1479 strcpy(pcop->name,aop->aopu.aop_dir);
1480 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1481 if(PCOR(pcop)->r == NULL) {
1482 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1483 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1484 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1486 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1488 PCOR(pcop)->instance = offset;
1496 assert (offset < aop->size);
1497 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1499 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1500 PCOR(pcop)->rIdx = rIdx;
1501 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1502 PCOR(pcop)->r->wasUsed=1;
1503 PCOR(pcop)->r->isFree=0;
1505 PCOR(pcop)->instance = offset;
1506 pcop->type = PCOR(pcop)->r->pc_type;
1507 //rs = aop->aopu.aop_reg[offset]->name;
1508 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1513 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1514 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1515 //if(PCOR(pcop)->r == NULL)
1516 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1520 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1523 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1524 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1526 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1527 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1528 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1529 pcop->type = PCOR(pcop)->r->pc_type;
1530 pcop->name = PCOR(pcop)->r->name;
1537 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1539 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1540 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1541 switch (aop->aopu.pcop->type)
1544 pcop = pCodeOpCopy (aop->aopu.pcop);
1545 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1546 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1547 PCOI(pcop)->index += offset;
1548 //PCOI(pcop)->offset = 0;
1551 pcop = pCodeOpCopy (aop->aopu.pcop);
1552 PCOR(pcop)->instance = offset;
1555 assert ( !"unhandled pCode type" );
1561 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1562 "popGet got unsupported aop->type");
1566 /*-----------------------------------------------------------------*/
1567 /* popGetAddr - access the low/high word of a symbol (immediate) */
1568 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1569 /*-----------------------------------------------------------------*/
1570 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1572 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1574 pCodeOp *pcop = aop->aopu.pcop;
1575 assert (offset <= GPTRSIZE);
1577 /* special case: index >= 2 should return GPOINTER-style values */
1580 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1584 pcop = pCodeOpCopy (pcop);
1585 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1586 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1587 PCOI(pcop)->offset += offset;
1588 PCOI(pcop)->index += index;
1589 //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1592 return popGet (aop, offset + index);
1596 /*-----------------------------------------------------------------*/
1597 /* aopPut - puts a string for a aop */
1598 /*-----------------------------------------------------------------*/
1599 void aopPut (asmop *aop, char *s, int offset)
1604 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1606 if (aop->size && offset > ( aop->size - 1)) {
1607 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608 "aopPut got offset > aop->size");
1612 /* will assign value to value */
1613 /* depending on where it is ofcourse */
1614 switch (aop->type) {
1617 sprintf(d,"(%s + %d)",
1618 aop->aopu.aop_dir,offset);
1619 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1622 sprintf(d,"%s",aop->aopu.aop_dir);
1625 DEBUGpic14_emitcode(";","%d",__LINE__);
1627 pic14_emitcode("movf","%s,w",s);
1628 pic14_emitcode("movwf","%s",d);
1631 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1632 if(offset >= aop->size) {
1633 emitpcode(POC_CLRF,popGet(aop,offset));
1636 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1639 emitpcode(POC_MOVWF,popGet(aop,offset));
1645 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1646 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1649 strcmp(s,"r0") == 0 ||
1650 strcmp(s,"r1") == 0 ||
1651 strcmp(s,"r2") == 0 ||
1652 strcmp(s,"r3") == 0 ||
1653 strcmp(s,"r4") == 0 ||
1654 strcmp(s,"r5") == 0 ||
1655 strcmp(s,"r6") == 0 ||
1656 strcmp(s,"r7") == 0 )
1657 pic14_emitcode("mov","%s,%s ; %d",
1658 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1662 if(strcmp(s,"W")==0 )
1663 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1665 pic14_emitcode("movwf","%s",
1666 aop->aopu.aop_reg[offset]->name);
1668 if(strcmp(s,zero)==0) {
1669 emitpcode(POC_CLRF,popGet(aop,offset));
1671 } else if(strcmp(s,"W")==0) {
1672 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1673 pcop->type = PO_GPR_REGISTER;
1675 PCOR(pcop)->rIdx = -1;
1676 PCOR(pcop)->r = NULL;
1678 DEBUGpic14_emitcode(";","%d",__LINE__);
1679 pcop->name = Safe_strdup(s);
1680 emitpcode(POC_MOVFW,pcop);
1681 emitpcode(POC_MOVWF,popGet(aop,offset));
1682 } else if(strcmp(s,one)==0) {
1683 emitpcode(POC_CLRF,popGet(aop,offset));
1684 emitpcode(POC_INCF,popGet(aop,offset));
1686 emitpcode(POC_MOVWF,popGet(aop,offset));
1694 if (aop->type == AOP_DPTR2)
1700 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1701 "aopPut writting to code space");
1705 while (offset > aop->coff) {
1707 pic14_emitcode ("inc","dptr");
1710 while (offset < aop->coff) {
1712 pic14_emitcode("lcall","__decdptr");
1717 /* if not in accumulater */
1720 pic14_emitcode ("movx","@dptr,a");
1722 if (aop->type == AOP_DPTR2)
1730 while (offset > aop->coff) {
1732 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1734 while (offset < aop->coff) {
1736 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1742 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1747 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1749 if (strcmp(s,"r0") == 0 ||
1750 strcmp(s,"r1") == 0 ||
1751 strcmp(s,"r2") == 0 ||
1752 strcmp(s,"r3") == 0 ||
1753 strcmp(s,"r4") == 0 ||
1754 strcmp(s,"r5") == 0 ||
1755 strcmp(s,"r6") == 0 ||
1756 strcmp(s,"r7") == 0 ) {
1758 sprintf(buffer,"a%s",s);
1759 pic14_emitcode("mov","@%s,%s",
1760 aop->aopu.aop_ptr->name,buffer);
1762 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1767 if (strcmp(s,"a") == 0)
1768 pic14_emitcode("push","acc");
1770 pic14_emitcode("push","%s",s);
1775 /* if bit variable */
1776 if (!aop->aopu.aop_dir) {
1777 pic14_emitcode("clr","a");
1778 pic14_emitcode("rlc","a");
1781 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1784 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1787 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1789 lbl = newiTempLabel(NULL);
1791 if (strcmp(s,"a")) {
1794 pic14_emitcode("clr","c");
1795 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1796 pic14_emitcode("cpl","c");
1797 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1798 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1805 if (strcmp(aop->aopu.aop_str[offset],s))
1806 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1811 if (!offset && (strcmp(s,"acc") == 0))
1814 if (strcmp(aop->aopu.aop_str[offset],s))
1815 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1819 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1820 "aopPut got unsupported aop->type");
1826 /*-----------------------------------------------------------------*/
1827 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1828 /*-----------------------------------------------------------------*/
1829 static void mov2w_op (operand *op, int offset)
1834 /* for PO_IMMEDIATEs: use address or value? */
1835 if (op_isLitLike (op))
1837 /* access address of op */
1838 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1839 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1841 if (offset == GPTRSIZE-1)
1842 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1844 emitpcode (POC_MOVLW, popGetLit (0));
1847 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1849 /* access value stored in op */
1850 mov2w (AOP(op), offset);
1855 /*-----------------------------------------------------------------*/
1856 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1857 /*-----------------------------------------------------------------*/
1858 void mov2w (asmop *aop, int offset)
1864 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1866 if ( aop_isLitLike (aop) )
1867 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1869 emitpcode(POC_MOVFW,popGet(aop,offset));
1873 static void movwf (asmop *op, int offset)
1875 emitpcode (POC_MOVWF, popGet(op, offset));
1878 static pCodeOp *get_argument_pcop (int idx)
1880 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1881 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1884 static pCodeOp *get_return_val_pcop (int offset)
1886 assert (offset > 0 && "the most significant byte is returned via WREG");
1887 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1890 static void pass_argument (operand *op, int offset, int idx)
1893 mov2w_op (op, offset);
1895 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1898 static void get_returnvalue (operand *op, int offset, int idx)
1901 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1902 movwf(AOP(op), offset);
1905 static void call_libraryfunc (char *name)
1907 /* library code might reside in different page... */
1908 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1909 /* call the library function */
1910 emitpcode (POC_CALL, popGetExternal (name));
1911 /* might return from different page... */
1912 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1915 /*-----------------------------------------------------------------*/
1916 /* reAdjustPreg - points a register back to where it should */
1917 /*-----------------------------------------------------------------*/
1918 static void reAdjustPreg (asmop *aop)
1922 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1924 if ((size = aop->size) <= 1)
1927 switch (aop->type) {
1931 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1935 if (aop->type == AOP_DPTR2)
1941 pic14_emitcode("lcall","__decdptr");
1944 if (aop->type == AOP_DPTR2)
1957 /*-----------------------------------------------------------------*/
1958 /* opIsGptr: returns non-zero if the passed operand is */
1959 /* a generic pointer type. */
1960 /*-----------------------------------------------------------------*/
1961 static int opIsGptr(operand *op)
1963 sym_link *type = operandType(op);
1965 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1966 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1974 /*-----------------------------------------------------------------*/
1975 /* pic14_getDataSize - get the operand data size */
1976 /*-----------------------------------------------------------------*/
1977 int pic14_getDataSize(operand *op)
1981 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1984 size = getSize(OP_SYM_ETYPE(op));
1986 //return AOP_SIZE(op);
1988 // tsd- in the pic port, the genptr size is 1, so this code here
1989 // fails. ( in the 8051 port, the size was 4).
1991 size = AOP_SIZE(op);
1992 if (IS_GENPTR(OP_SYM_TYPE(op)))
1994 sym_link *type = operandType(op);
1995 if (IS_GENPTR(type))
1997 /* generic pointer; arithmetic operations
1998 * should ignore the high byte (pointer type).
2001 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2008 /*-----------------------------------------------------------------*/
2009 /* pic14_outAcc - output Acc */
2010 /*-----------------------------------------------------------------*/
2011 void pic14_outAcc(operand *result)
2014 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2015 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2018 size = pic14_getDataSize(result);
2020 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2023 /* unsigned or positive */
2025 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2030 /*-----------------------------------------------------------------*/
2031 /* pic14_outBitC - output a bit C */
2032 /*-----------------------------------------------------------------*/
2033 void pic14_outBitC(operand *result)
2036 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2037 /* if the result is bit */
2038 if (AOP_TYPE(result) == AOP_CRY)
2039 aopPut(AOP(result),"c",0);
2041 pic14_emitcode("clr","a ; %d", __LINE__);
2042 pic14_emitcode("rlc","a");
2043 pic14_outAcc(result);
2047 /*-----------------------------------------------------------------*/
2048 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
2049 /*-----------------------------------------------------------------*/
2050 void pic14_toBoolean(operand *oper)
2052 int size = AOP_SIZE(oper);
2055 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2060 /* MOVFW does not load the flags... */
2061 if (AOP_TYPE(oper) == AOP_ACC) {
2062 emitpcode(POC_IORLW, popGetLit(0));
2065 emitpcode(POC_MOVLW, popGetLit(0));
2069 if ( AOP_TYPE(oper) != AOP_ACC) {
2070 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2075 while (offset < size) {
2076 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2078 /* Z is set iff (oper == 0) */
2082 /*-----------------------------------------------------------------*/
2083 /* genNot - generate code for ! operation */
2084 /*-----------------------------------------------------------------*/
2085 static void genNot (iCode *ic)
2092 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2093 /* assign asmOps to operand & result */
2094 aopOp (IC_LEFT(ic),ic,FALSE);
2095 aopOp (IC_RESULT(ic),ic,TRUE);
2097 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2098 /* if in bit space then a special case */
2099 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2100 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2101 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2102 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2104 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2105 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2106 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2111 size = AOP_SIZE(IC_LEFT(ic));
2112 mov2w (AOP(IC_LEFT(ic)),0);
2115 if (op_isLitLike (IC_LEFT(ic)))
2116 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2118 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2120 emitpcode(POC_MOVLW, popGetLit (0));
2122 emitpcode(POC_MOVLW, popGetLit (1));
2123 movwf(AOP(IC_RESULT(ic)), 0);
2125 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2127 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2132 /* release the aops */
2133 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2134 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2138 /*-----------------------------------------------------------------*/
2139 /* genCpl - generate code for complement */
2140 /*-----------------------------------------------------------------*/
2141 static void genCpl (iCode *ic)
2143 operand *left, *result;
2148 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2149 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2150 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2152 /* if both are in bit space then
2154 if (AOP_TYPE(result) == AOP_CRY &&
2155 AOP_TYPE(left) == AOP_CRY ) {
2157 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2158 pic14_emitcode("cpl","c");
2159 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2163 size = AOP_SIZE(result);
2164 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2167 if(AOP_TYPE(left) == AOP_ACC)
2168 emitpcode(POC_XORLW, popGetLit(0xff));
2170 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2172 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2175 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2179 /* release the aops */
2180 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2181 freeAsmop(result,NULL,ic,TRUE);
2184 /*-----------------------------------------------------------------*/
2185 /* genUminusFloat - unary minus for floating points */
2186 /*-----------------------------------------------------------------*/
2187 static void genUminusFloat(operand *op,operand *result)
2189 int size ,offset =0 ;
2194 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2195 /* for this we just need to flip the
2196 first it then copy the rest in place */
2197 size = AOP_SIZE(op) - 1;
2198 l = aopGet(AOP(op),3,FALSE,FALSE);
2202 pic14_emitcode("cpl","acc.7");
2203 aopPut(AOP(result),"a",3);
2207 aopGet(AOP(op),offset,FALSE,FALSE),
2213 /*-----------------------------------------------------------------*/
2214 /* genUminus - unary minus code generation */
2215 /*-----------------------------------------------------------------*/
2216 static void genUminus (iCode *ic)
2219 sym_link *optype, *rtype;
2223 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2225 aopOp(IC_LEFT(ic),ic,FALSE);
2226 aopOp(IC_RESULT(ic),ic,TRUE);
2228 /* if both in bit space then special
2230 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2231 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2233 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2234 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2235 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2240 optype = operandType(IC_LEFT(ic));
2241 rtype = operandType(IC_RESULT(ic));
2243 /* if float then do float stuff */
2244 if (IS_FLOAT(optype)) {
2245 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2249 /* otherwise subtract from zero by taking the 2's complement */
2250 size = AOP_SIZE(IC_LEFT(ic));
2252 for(i=0; i<size; i++) {
2253 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2254 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2256 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2257 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2261 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2262 for(i=1; i<size; i++) {
2264 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2268 /* release the aops */
2269 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2270 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2273 /*-----------------------------------------------------------------*/
2274 /* saveRegisters - will look for a call and save the registers */
2275 /*-----------------------------------------------------------------*/
2276 static void saveRegisters(iCode *lic)
2285 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2287 for (ic = lic ; ic ; ic = ic->next)
2288 if (ic->op == CALL || ic->op == PCALL)
2292 fprintf(stderr,"found parameter push with no function call\n");
2296 /* if the registers have been saved already then
2298 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2301 /* find the registers in use at this time
2302 and push them away to safety */
2303 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2307 if (options.useXstack) {
2308 if (bitVectBitValue(rsave,R0_IDX))
2309 pic14_emitcode("mov","b,r0");
2310 pic14_emitcode("mov","r0,%s",spname);
2311 for (i = 0 ; i < pic14_nRegs ; i++) {
2312 if (bitVectBitValue(rsave,i)) {
2314 pic14_emitcode("mov","a,b");
2316 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2317 pic14_emitcode("movx","@r0,a");
2318 pic14_emitcode("inc","r0");
2321 pic14_emitcode("mov","%s,r0",spname);
2322 if (bitVectBitValue(rsave,R0_IDX))
2323 pic14_emitcode("mov","r0,b");
2325 //for (i = 0 ; i < pic14_nRegs ; i++) {
2326 // if (bitVectBitValue(rsave,i))
2327 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2330 dtype = operandType(IC_LEFT(ic));
2331 if (currFunc && dtype &&
2332 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2333 IFFUNC_ISISR(currFunc->type) &&
2336 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2339 /*-----------------------------------------------------------------*/
2340 /* unsaveRegisters - pop the pushed registers */
2341 /*-----------------------------------------------------------------*/
2342 static void unsaveRegisters (iCode *ic)
2349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2350 /* find the registers in use at this time
2351 and push them away to safety */
2352 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2355 if (options.useXstack) {
2356 pic14_emitcode("mov","r0,%s",spname);
2357 for (i = pic14_nRegs ; i >= 0 ; i--) {
2358 if (bitVectBitValue(rsave,i)) {
2359 pic14_emitcode("dec","r0");
2360 pic14_emitcode("movx","a,@r0");
2362 pic14_emitcode("mov","b,a");
2364 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2368 pic14_emitcode("mov","%s,r0",spname);
2369 if (bitVectBitValue(rsave,R0_IDX))
2370 pic14_emitcode("mov","r0,b");
2372 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2373 // if (bitVectBitValue(rsave,i))
2374 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2380 /*-----------------------------------------------------------------*/
2382 /*-----------------------------------------------------------------*/
2383 static void pushSide(operand * oper, int size)
2387 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2389 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2390 if (AOP_TYPE(oper) != AOP_REG &&
2391 AOP_TYPE(oper) != AOP_DIR &&
2393 pic14_emitcode("mov","a,%s",l);
2394 pic14_emitcode("push","acc");
2396 pic14_emitcode("push","%s",l);
2401 /*-----------------------------------------------------------------*/
2402 /* assignResultValue - */
2403 /*-----------------------------------------------------------------*/
2404 static void assignResultValue(operand * oper)
2406 int size = AOP_SIZE(oper);
2411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2413 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2415 /* assign MSB first (passed via WREG) */
2417 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2423 /*-----------------------------------------------------------------*/
2424 /* genIpush - genrate code for pushing this gets a little complex */
2425 /*-----------------------------------------------------------------*/
2426 static void genIpush (iCode *ic)
2430 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2432 int size, offset = 0 ;
2436 /* if this is not a parm push : ie. it is spill push
2437 and spill push is always done on the local stack */
2438 if (!ic->parmPush) {
2440 /* and the item is spilt then do nothing */
2441 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2444 aopOp(IC_LEFT(ic),ic,FALSE);
2445 size = AOP_SIZE(IC_LEFT(ic));
2446 /* push it on the stack */
2448 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2453 pic14_emitcode("push","%s",l);
2458 /* this is a paramter push: in this case we call
2459 the routine to find the call and save those
2460 registers that need to be saved */
2463 /* then do the push */
2464 aopOp(IC_LEFT(ic),ic,FALSE);
2467 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2468 size = AOP_SIZE(IC_LEFT(ic));
2471 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2472 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2473 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2475 pic14_emitcode("mov","a,%s",l);
2476 pic14_emitcode("push","acc");
2478 pic14_emitcode("push","%s",l);
2481 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2485 /*-----------------------------------------------------------------*/
2486 /* genIpop - recover the registers: can happen only for spilling */
2487 /*-----------------------------------------------------------------*/
2488 static void genIpop (iCode *ic)
2492 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2493 assert (!"genIpop -- unimplemented");
2498 /* if the temp was not pushed then */
2499 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2502 aopOp(IC_LEFT(ic),ic,FALSE);
2503 size = AOP_SIZE(IC_LEFT(ic));
2506 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2509 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2513 /*-----------------------------------------------------------------*/
2514 /* unsaverbank - restores the resgister bank from stack */
2515 /*-----------------------------------------------------------------*/
2516 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2520 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2526 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2528 if (options.useXstack) {
2530 r = getFreePtr(ic,&aop,FALSE);
2533 pic14_emitcode("mov","%s,_spx",r->name);
2534 pic14_emitcode("movx","a,@%s",r->name);
2535 pic14_emitcode("mov","psw,a");
2536 pic14_emitcode("dec","%s",r->name);
2539 pic14_emitcode ("pop","psw");
2542 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2543 if (options.useXstack) {
2544 pic14_emitcode("movx","a,@%s",r->name);
2545 //pic14_emitcode("mov","(%s+%d),a",
2546 // regspic14[i].base,8*bank+regspic14[i].offset);
2547 pic14_emitcode("dec","%s",r->name);
2550 pic14_emitcode("pop",""); //"(%s+%d)",
2551 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2554 if (options.useXstack) {
2556 pic14_emitcode("mov","_spx,%s",r->name);
2557 freeAsmop(NULL,aop,ic,TRUE);
2563 /*-----------------------------------------------------------------*/
2564 /* saverbank - saves an entire register bank on the stack */
2565 /*-----------------------------------------------------------------*/
2566 static void saverbank (int bank, iCode *ic, bool pushPsw)
2570 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2576 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2577 if (options.useXstack) {
2580 r = getFreePtr(ic,&aop,FALSE);
2581 pic14_emitcode("mov","%s,_spx",r->name);
2585 for (i = 0 ; i < pic14_nRegs ;i++) {
2586 if (options.useXstack) {
2587 pic14_emitcode("inc","%s",r->name);
2588 //pic14_emitcode("mov","a,(%s+%d)",
2589 // regspic14[i].base,8*bank+regspic14[i].offset);
2590 pic14_emitcode("movx","@%s,a",r->name);
2592 pic14_emitcode("push","");// "(%s+%d)",
2593 //regspic14[i].base,8*bank+regspic14[i].offset);
2597 if (options.useXstack) {
2598 pic14_emitcode("mov","a,psw");
2599 pic14_emitcode("movx","@%s,a",r->name);
2600 pic14_emitcode("inc","%s",r->name);
2601 pic14_emitcode("mov","_spx,%s",r->name);
2602 freeAsmop (NULL,aop,ic,TRUE);
2605 pic14_emitcode("push","psw");
2607 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2613 /*-----------------------------------------------------------------*/
2614 /* genCall - generates a call statement */
2615 /*-----------------------------------------------------------------*/
2616 static void genCall (iCode *ic)
2625 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2627 /* if caller saves & we have not saved then */
2631 /* if we are calling a function that is not using
2632 the same register bank then we need to save the
2633 destination registers on the stack */
2634 dtype = operandType(IC_LEFT(ic));
2635 if (currFunc && dtype &&
2636 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2637 IFFUNC_ISISR(currFunc->type) &&
2640 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2642 /* if send set is not empty the assign */
2645 /* For the Pic port, there is no data stack.
2646 * So parameters passed to functions are stored
2647 * in registers. (The pCode optimizer will get
2648 * rid of most of these :).
2650 int psuedoStkPtr=-1;
2651 int firstTimeThruLoop = 1;
2653 _G.sendSet = reverseSet(_G.sendSet);
2655 /* First figure how many parameters are getting passed */
2656 for (sic = setFirstItem(_G.sendSet) ; sic ;
2657 sic = setNextItem(_G.sendSet)) {
2659 aopOp(IC_LEFT(sic),sic,FALSE);
2660 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2661 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2664 for (sic = setFirstItem(_G.sendSet) ; sic ;
2665 sic = setNextItem(_G.sendSet)) {
2666 int size, offset = 0;
2668 aopOp(IC_LEFT(sic),sic,FALSE);
2669 size = AOP_SIZE(IC_LEFT(sic));
2672 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2673 AopType(AOP_TYPE(IC_LEFT(sic))));
2675 if(!firstTimeThruLoop) {
2676 /* If this is not the first time we've been through the loop
2677 * then we need to save the parameter in a temporary
2678 * register. The last byte of the last parameter is
2680 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2683 firstTimeThruLoop=0;
2685 mov2w_op (IC_LEFT(sic), offset);
2688 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2693 sym = OP_SYMBOL(IC_LEFT(ic));
2694 name = sym->rname[0] ? sym->rname : sym->name;
2695 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2697 /* Extern functions and ISRs maybe on a different page;
2698 * must call pagesel */
2699 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2701 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2703 /* May have returned from a different page;
2704 * must use pagesel to restore PCLATH before next
2705 * goto or call instruction */
2706 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2709 /* if we need assign a result value */
2710 if ((IS_ITEMP(IC_RESULT(ic)) &&
2711 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2712 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2713 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2716 aopOp(IC_RESULT(ic),ic,FALSE);
2719 assignResultValue(IC_RESULT(ic));
2721 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2722 AopType(AOP_TYPE(IC_RESULT(ic))));
2724 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2727 /* if register bank was saved then pop them */
2729 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2731 /* if we hade saved some registers then unsave them */
2732 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2733 unsaveRegisters (ic);
2738 /*-----------------------------------------------------------------*/
2739 /* genPcall - generates a call by pointer statement */
2740 /*-----------------------------------------------------------------*/
2741 static void genPcall (iCode *ic)
2744 symbol *albl = newiTempLabel(NULL);
2745 symbol *blbl = newiTempLabel(NULL);
2752 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2753 /* if caller saves & we have not saved then */
2757 /* if we are calling a function that is not using
2758 the same register bank then we need to save the
2759 destination registers on the stack */
2760 dtype = operandType(IC_LEFT(ic));
2761 if (currFunc && dtype &&
2762 IFFUNC_ISISR(currFunc->type) &&
2763 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2764 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2767 aopOp(left,ic,FALSE);
2768 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2770 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2772 pushSide(IC_LEFT(ic), FPTRSIZE);
2774 /* if send set is not empty, assign parameters */
2777 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2778 /* no way to pass args - W always gets used to make the call */
2780 /* first idea - factor out a common helper function and call it.
2781 But don't know how to get it generated only once in its own block
2783 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2786 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2787 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2788 buffer = Safe_calloc(1,strlen(rname)+16);
2789 sprintf(buffer, "%s_goto_helper", rname);
2790 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2794 emitpcode(POC_CALL,popGetLabel(albl->key));
2795 pcop = popGetLabel(blbl->key);
2796 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2797 emitpcode(POC_GOTO,pcop);
2798 emitpLabel(albl->key);
2800 emitpcode(poc,popGetAddr(AOP(left),1,0));
2801 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2802 emitpcode(poc,popGetAddr(AOP(left),0,0));
2803 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2805 emitpLabel(blbl->key);
2807 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2809 /* if we need to assign a result value */
2810 if ((IS_ITEMP(IC_RESULT(ic)) &&
2811 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2812 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2813 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2816 aopOp(IC_RESULT(ic),ic,FALSE);
2821 assignResultValue(IC_RESULT(ic));
2823 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2826 /* if register bank was saved then unsave them */
2827 if (currFunc && dtype &&
2828 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2829 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2831 /* if we hade saved some registers then
2834 unsaveRegisters (ic);
2838 /*-----------------------------------------------------------------*/
2839 /* resultRemat - result is rematerializable */
2840 /*-----------------------------------------------------------------*/
2841 static int resultRemat (iCode *ic)
2843 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2846 if (SKIP_IC(ic) || ic->op == IFX)
2849 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2850 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2851 if (sym->remat && !POINTER_SET(ic))
2858 #if defined(__BORLANDC__) || defined(_MSC_VER)
2859 #define STRCASECMP stricmp
2861 #define STRCASECMP strcasecmp
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list */
2867 /*-----------------------------------------------------------------*/
2868 static bool inExcludeList(char *s)
2870 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2873 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2874 if (options.excludeRegs[i] &&
2875 STRCASECMP(options.excludeRegs[i],"none") == 0)
2878 for ( i = 0 ; options.excludeRegs[i]; i++) {
2879 if (options.excludeRegs[i] &&
2880 STRCASECMP(s,options.excludeRegs[i]) == 0)
2887 /*-----------------------------------------------------------------*/
2888 /* genFunction - generated code for function entry */
2889 /*-----------------------------------------------------------------*/
2890 static void genFunction (iCode *ic)
2897 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2899 labelOffset += (max_key+4);
2903 /* create the function header */
2904 pic14_emitcode(";","-----------------------------------------");
2905 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2906 pic14_emitcode(";","-----------------------------------------");
2908 /* prevent this symbol from being emitted as 'extern' */
2909 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2911 pic14_emitcode("","%s:",sym->rname);
2912 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2914 ftype = operandType(IC_LEFT(ic));
2916 /* if critical function then turn interrupts off */
2917 if (IFFUNC_ISCRITICAL(ftype))
2918 pic14_emitcode("clr","ea");
2920 /* here we need to generate the equates for the
2921 register bank if required */
2923 if (FUNC_REGBANK(ftype) != rbank) {
2926 rbank = FUNC_REGBANK(ftype);
2927 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2928 if (strcmp(regspic14[i].base,"0") == 0)
2929 pic14_emitcode("","%s = 0x%02x",
2931 8*rbank+regspic14[i].offset);
2933 pic14_emitcode ("","%s = %s + 0x%02x",
2936 8*rbank+regspic14[i].offset);
2941 /* if this is an interrupt service routine */
2943 if (IFFUNC_ISISR(sym->type)) {
2945 /* already done in pic14createInterruptVect() - delete me
2946 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2947 emitpcodeNULLop(POC_NOP);
2948 emitpcodeNULLop(POC_NOP);
2949 emitpcodeNULLop(POC_NOP);
2951 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2952 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2953 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2954 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2955 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2956 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2957 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2959 pBlockConvert2ISR(pb);
2960 pic14_hasInterrupt = 1;
2962 if (!inExcludeList("acc"))
2963 pic14_emitcode ("push","acc");
2964 if (!inExcludeList("b"))
2965 pic14_emitcode ("push","b");
2966 if (!inExcludeList("dpl"))
2967 pic14_emitcode ("push","dpl");
2968 if (!inExcludeList("dph"))
2969 pic14_emitcode ("push","dph");
2970 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2972 pic14_emitcode ("push", "dpx");
2973 /* Make sure we're using standard DPTR */
2974 pic14_emitcode ("push", "dps");
2975 pic14_emitcode ("mov", "dps, #0x00");
2976 if (options.stack10bit)
2978 /* This ISR could conceivably use DPTR2. Better save it. */
2979 pic14_emitcode ("push", "dpl1");
2980 pic14_emitcode ("push", "dph1");
2981 pic14_emitcode ("push", "dpx1");
2984 /* if this isr has no bank i.e. is going to
2985 run with bank 0 , then we need to save more
2987 if (!FUNC_REGBANK(sym->type)) {
2989 /* if this function does not call any other
2990 function then we can be economical and
2991 save only those registers that are used */
2992 if (! IFFUNC_HASFCALL(sym->type)) {
2995 /* if any registers used */
2996 if (sym->regsUsed) {
2997 /* save the registers used */
2998 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2999 if (bitVectBitValue(sym->regsUsed,i) ||
3000 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3001 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
3006 /* this function has a function call cannot
3007 determines register usage so we will have the
3009 saverbank(0,ic,FALSE);
3014 /* if callee-save to be used for this function
3015 then save the registers being used in this function */
3016 if (IFFUNC_CALLEESAVES(sym->type)) {
3019 /* if any registers used */
3020 if (sym->regsUsed) {
3021 /* save the registers used */
3022 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3023 if (bitVectBitValue(sym->regsUsed,i) ||
3024 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3025 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3033 /* set the register bank to the desired value */
3034 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3035 pic14_emitcode("push","psw");
3036 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
3039 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3041 if (options.useXstack) {
3042 pic14_emitcode("mov","r0,%s",spname);
3043 pic14_emitcode("mov","a,_bp");
3044 pic14_emitcode("movx","@r0,a");
3045 pic14_emitcode("inc","%s",spname);
3049 /* set up the stack */
3050 pic14_emitcode ("push","_bp"); /* save the callers stack */
3052 pic14_emitcode ("mov","_bp,%s",spname);
3055 /* adjust the stack for the function */
3060 werror(W_STACK_OVERFLOW,sym->name);
3062 if (i > 3 && sym->recvSize < 4) {
3064 pic14_emitcode ("mov","a,sp");
3065 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3066 pic14_emitcode ("mov","sp,a");
3071 pic14_emitcode("inc","sp");
3076 pic14_emitcode ("mov","a,_spx");
3077 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3078 pic14_emitcode ("mov","_spx,a");
3083 /*-----------------------------------------------------------------*/
3084 /* genEndFunction - generates epilogue for functions */
3085 /*-----------------------------------------------------------------*/
3086 static void genEndFunction (iCode *ic)
3088 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3092 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3094 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3096 pic14_emitcode ("mov","%s,_bp",spname);
3099 /* if use external stack but some variables were
3100 added to the local stack then decrement the
3102 if (options.useXstack && sym->stack) {
3103 pic14_emitcode("mov","a,sp");
3104 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3105 pic14_emitcode("mov","sp,a");
3109 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3110 if (options.useXstack) {
3111 pic14_emitcode("mov","r0,%s",spname);
3112 pic14_emitcode("movx","a,@r0");
3113 pic14_emitcode("mov","_bp,a");
3114 pic14_emitcode("dec","%s",spname);
3118 pic14_emitcode ("pop","_bp");
3122 /* restore the register bank */
3123 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3124 pic14_emitcode ("pop","psw");
3126 if (IFFUNC_ISISR(sym->type)) {
3128 /* now we need to restore the registers */
3129 /* if this isr has no bank i.e. is going to
3130 run with bank 0 , then we need to save more
3132 if (!FUNC_REGBANK(sym->type)) {
3134 /* if this function does not call any other
3135 function then we can be economical and
3136 save only those registers that are used */
3137 if (! IFFUNC_HASFCALL(sym->type)) {
3140 /* if any registers used */
3141 if (sym->regsUsed) {
3142 /* save the registers used */
3143 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3144 if (bitVectBitValue(sym->regsUsed,i) ||
3145 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3146 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3151 /* this function has a function call cannot
3152 determines register usage so we will have the
3154 unsaverbank(0,ic,FALSE);
3158 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3160 if (options.stack10bit)
3162 pic14_emitcode ("pop", "dpx1");
3163 pic14_emitcode ("pop", "dph1");
3164 pic14_emitcode ("pop", "dpl1");
3166 pic14_emitcode ("pop", "dps");
3167 pic14_emitcode ("pop", "dpx");
3169 if (!inExcludeList("dph"))
3170 pic14_emitcode ("pop","dph");
3171 if (!inExcludeList("dpl"))
3172 pic14_emitcode ("pop","dpl");
3173 if (!inExcludeList("b"))
3174 pic14_emitcode ("pop","b");
3175 if (!inExcludeList("acc"))
3176 pic14_emitcode ("pop","acc");
3178 if (IFFUNC_ISCRITICAL(sym->type))
3179 pic14_emitcode("setb","ea");
3182 /* if debug then send end of function */
3183 /* if (options.debug && currFunc) { */
3185 debugFile->writeEndFunction (currFunc, ic, 1);
3188 pic14_emitcode ("reti","");
3189 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3190 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3191 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3192 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3193 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3194 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3195 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3196 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3197 emitpcodeNULLop(POC_RETFIE);
3200 if (IFFUNC_ISCRITICAL(sym->type))
3201 pic14_emitcode("setb","ea");
3203 if (IFFUNC_CALLEESAVES(sym->type)) {
3206 /* if any registers used */
3207 if (sym->regsUsed) {
3208 /* save the registers used */
3209 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3210 if (bitVectBitValue(sym->regsUsed,i) ||
3211 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3212 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3218 /* if debug then send end of function */
3220 debugFile->writeEndFunction (currFunc, ic, 1);
3223 pic14_emitcode ("return","");
3224 emitpcodeNULLop(POC_RETURN);
3226 /* Mark the end of a function */
3227 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3232 /*-----------------------------------------------------------------*/
3233 /* genRet - generate code for return statement */
3234 /*-----------------------------------------------------------------*/
3235 static void genRet (iCode *ic)
3237 int size,offset = 0;
3241 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3242 /* if we have no return value then
3243 just generate the "ret" */
3247 /* we have something to return then
3248 move the return value into place */
3249 aopOp(IC_LEFT(ic),ic,FALSE);
3250 size = AOP_SIZE(IC_LEFT(ic));
3252 for (offset = 0; offset < size; offset++)
3254 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3257 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3260 /* generate a jump to the return label
3261 if the next is not the return statement */
3262 if (!(ic->next && ic->next->op == LABEL &&
3263 IC_LABEL(ic->next) == returnLabel)) {
3265 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label */
3272 /*-----------------------------------------------------------------*/
3273 static void genLabel (iCode *ic)
3277 /* special case never generate */
3278 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3279 if (IC_LABEL(ic) == entryLabel)
3282 emitpLabel(IC_LABEL(ic)->key);
3283 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a goto */
3288 /*-----------------------------------------------------------------*/
3290 static void genGoto (iCode *ic)
3294 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3295 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3299 /*-----------------------------------------------------------------*/
3300 /* genMultbits :- multiplication of bits */
3301 /*-----------------------------------------------------------------*/
3302 static void genMultbits (operand *left,
3307 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3309 if(!pic14_sameRegs(AOP(result),AOP(right)))
3310 emitpcode(POC_BSF, popGet(AOP(result),0));
3312 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3313 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3314 emitpcode(POC_BCF, popGet(AOP(result),0));
3319 /*-----------------------------------------------------------------*/
3320 /* genMultOneByte : 8 bit multiplication & division */
3321 /*-----------------------------------------------------------------*/
3322 static void genMultOneByte (operand *left,
3326 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3334 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3335 DEBUGpic14_AopType(__LINE__,left,right,result);
3336 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3338 /* (if two literals, the value is computed before) */
3339 /* if one literal, literal on the right */
3340 if (AOP_TYPE(left) == AOP_LIT){
3346 assert (AOP_SIZE(left) == AOP_SIZE(right));
3348 size = min(AOP_SIZE(result),AOP_SIZE(left));
3349 offset = Gstack_base_addr - (2*size - 1);
3351 /* pass right operand as argument */
3352 for (i=0; i < size; i++)
3354 mov2w (AOP(right), i);
3355 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3358 /* pass left operand as argument */
3359 for (i=0; i < size; i++)
3361 mov2w (AOP(left), i);
3362 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3364 assert (offset == Gstack_base_addr);
3366 /* call library routine */
3367 assert (size > 0 && size <= 4);
3368 call_libraryfunc (func[size]);
3371 movwf (AOP(result), size-1);
3372 for (i=0; i < size - 1; i++)
3374 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3375 movwf (AOP(result), size - 2 - i);
3378 /* now (zero-/sign) extend the result to its size */
3379 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3382 /*-----------------------------------------------------------------*/
3383 /* genMult - generates code for multiplication */
3384 /*-----------------------------------------------------------------*/
3385 static void genMult (iCode *ic)
3387 operand *left = IC_LEFT(ic);
3388 operand *right = IC_RIGHT(ic);
3389 operand *result= IC_RESULT(ic);
3393 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3394 /* assign the amsops */
3395 aopOp (left,ic,FALSE);
3396 aopOp (right,ic,FALSE);
3397 aopOp (result,ic,TRUE);
3399 DEBUGpic14_AopType(__LINE__,left,right,result);
3401 /* special cases first */
3403 if (AOP_TYPE(left) == AOP_CRY &&
3404 AOP_TYPE(right)== AOP_CRY) {
3405 genMultbits(left,right,result);
3409 /* if both are of size == 1 */
3410 if (AOP_SIZE(left) == 1 &&
3411 AOP_SIZE(right) == 1 ) {
3412 genMultOneByte(left,right,result);
3416 /* should have been converted to function call */
3420 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3421 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3422 freeAsmop(result,NULL,ic,TRUE);
3425 /*-----------------------------------------------------------------*/
3426 /* genDivbits :- division of bits */
3427 /*-----------------------------------------------------------------*/
3428 static void genDivbits (operand *left,
3437 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3438 /* the result must be bit */
3439 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3440 l = aopGet(AOP(left),0,FALSE,FALSE);
3444 pic14_emitcode("div","ab");
3445 pic14_emitcode("rrc","a");
3446 aopPut(AOP(result),"c",0);
3449 /*-----------------------------------------------------------------*/
3450 /* genDivOneByte : 8 bit division */
3451 /*-----------------------------------------------------------------*/
3452 static void genDivOneByte (operand *left,
3459 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3461 assert (AOP_SIZE(result) == 1);
3462 assert (AOP_SIZE(right) == 1);
3463 assert (AOP_SIZE(left) == 1);
3465 size = min(AOP_SIZE(result),AOP_SIZE(left));
3467 if (AOP_TYPE(right) == AOP_LIT)
3469 /* XXX: might add specialized code */
3472 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3474 /* unsigned division */
3476 mov2w(AOP(right),0);
3477 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3479 call_libraryfunc("__divuchar");
3480 movwf(AOP(result),0);
3485 temp = popGetTempReg();
3486 lbl = newiTempLabel(NULL);
3488 /* XXX: improve this naive approach:
3489 [result] = [a] / [b]
3490 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3494 movwf temp // temp <-- left
3495 movf right,W // W <-- right
3499 subwf temp,F // temp <-- temp - W
3500 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3502 decf result // we just subtract once too often
3505 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3506 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3509 emitpcode(POC_MOVWF, temp);
3510 mov2w(AOP(right),0);
3511 emitpcode(POC_CLRF, popGet(AOP(result),0));
3513 emitpLabel(lbl->key);
3514 emitpcode(POC_INCF, popGet(AOP(result),0));
3515 emitpcode(POC_SUBWF, temp);
3517 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3518 emitpcode(POC_DECF, popGet(AOP(result),0));
3523 /* signed division */
3524 mov2w(AOP(right),0);
3525 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3527 call_libraryfunc("__divschar");
3528 movwf(AOP(result),0);
3531 /* now performed the signed/unsigned division -- extend result */
3532 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3535 /*-----------------------------------------------------------------*/
3536 /* genDiv - generates code for division */
3537 /*-----------------------------------------------------------------*/
3538 static void genDiv (iCode *ic)
3540 operand *left = IC_LEFT(ic);
3541 operand *right = IC_RIGHT(ic);
3542 operand *result= IC_RESULT(ic);
3545 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3546 /* assign the amsops */
3547 aopOp (left,ic,FALSE);
3548 aopOp (right,ic,FALSE);
3549 aopOp (result,ic,TRUE);
3551 /* special cases first */
3553 if (AOP_TYPE(left) == AOP_CRY &&
3554 AOP_TYPE(right)== AOP_CRY) {
3555 genDivbits(left,right,result);
3559 /* if both are of size == 1 */
3560 if (AOP_SIZE(left) == 1 &&
3561 AOP_SIZE(right) == 1 ) {
3562 genDivOneByte(left,right,result);
3566 /* should have been converted to function call */
3569 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3570 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3571 freeAsmop(result,NULL,ic,TRUE);
3574 /*-----------------------------------------------------------------*/
3575 /* genModbits :- modulus of bits */
3576 /*-----------------------------------------------------------------*/
3577 static void genModbits (operand *left,
3585 /* the result must be bit */
3586 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3587 l = aopGet(AOP(left),0,FALSE,FALSE);
3591 pic14_emitcode("div","ab");
3592 pic14_emitcode("mov","a,b");
3593 pic14_emitcode("rrc","a");
3594 aopPut(AOP(result),"c",0);
3597 /*-----------------------------------------------------------------*/
3598 /* genModOneByte : 8 bit modulus */
3599 /*-----------------------------------------------------------------*/
3600 static void genModOneByte (operand *left,
3607 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3609 assert (AOP_SIZE(result) == 1);
3610 assert (AOP_SIZE(right) == 1);
3611 assert (AOP_SIZE(left) == 1);
3613 size = min(AOP_SIZE(result),AOP_SIZE(left));
3615 if (AOP_TYPE(right) == AOP_LIT)
3617 /* XXX: might add specialized code */
3620 if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3622 /* unsigned division */
3624 mov2w(AOP(right),0);
3625 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3627 call_libraryfunc("__moduchar");
3628 movwf(AOP(result),0);
3633 lbl = newiTempLabel(NULL);
3635 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3637 /* XXX: improve this naive approach:
3638 [result] = [a] % [b]
3639 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3643 movwf result // result <-- left
3644 movf right,W // W <-- right
3646 subwf result,F // result <-- result - W
3647 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3649 addwf result, F // we just subtract once too often
3652 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3653 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3655 if (!pic14_sameRegs(AOP(left), AOP(result)))
3658 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3660 mov2w(AOP(right),0);
3662 emitpLabel(lbl->key);
3663 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3665 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3666 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3671 /* signed division */
3672 mov2w(AOP(right),0);
3673 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3675 call_libraryfunc("__modschar");
3676 movwf(AOP(result),0);
3679 /* now we performed the signed/unsigned modulus -- extend result */
3680 addSign(result, 1, !SPEC_USIGN(operandType(result)));
3683 /*-----------------------------------------------------------------*/
3684 /* genMod - generates code for division */
3685 /*-----------------------------------------------------------------*/
3686 static void genMod (iCode *ic)
3688 operand *left = IC_LEFT(ic);
3689 operand *right = IC_RIGHT(ic);
3690 operand *result= IC_RESULT(ic);
3693 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3694 /* assign the amsops */
3695 aopOp (left,ic,FALSE);
3696 aopOp (right,ic,FALSE);
3697 aopOp (result,ic,TRUE);
3699 /* special cases first */
3701 if (AOP_TYPE(left) == AOP_CRY &&
3702 AOP_TYPE(right)== AOP_CRY) {
3703 genModbits(left,right,result);
3707 /* if both are of size == 1 */
3708 if (AOP_SIZE(left) == 1 &&
3709 AOP_SIZE(right) == 1 ) {
3710 genModOneByte(left,right,result);
3714 /* should have been converted to function call */
3718 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3719 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3720 freeAsmop(result,NULL,ic,TRUE);
3723 /*-----------------------------------------------------------------*/
3724 /* genIfxJump :- will create a jump depending on the ifx */
3725 /*-----------------------------------------------------------------*/
3727 note: May need to add parameter to indicate when a variable is in bit space.
3729 static void genIfxJump (iCode *ic, char *jval)
3733 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3734 /* if true label then we jump if condition
3736 if ( IC_TRUE(ic) ) {
3738 if(strcmp(jval,"a") == 0)
3740 else if (strcmp(jval,"c") == 0)
3743 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3744 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3747 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3748 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3752 /* false label is present */
3753 if(strcmp(jval,"a") == 0)
3755 else if (strcmp(jval,"c") == 0)
3758 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3759 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3762 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3763 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3768 /* mark the icode as generated */
3773 /*-----------------------------------------------------------------*/
3775 /*-----------------------------------------------------------------*/
3776 static void genSkip(iCode *ifx,int status_bit)
3782 if ( IC_TRUE(ifx) ) {
3783 switch(status_bit) {
3798 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3799 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3803 switch(status_bit) {
3817 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3818 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3825 /*-----------------------------------------------------------------*/
3827 /*-----------------------------------------------------------------*/
3828 static void genSkipc(resolvedIfx *rifx)
3839 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3840 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3841 rifx->generated = 1;
3845 /*-----------------------------------------------------------------*/
3847 /*-----------------------------------------------------------------*/
3848 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3854 if( (rifx->condition ^ invert_condition) & 1)
3859 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3860 rifx->generated = 1;
3865 /*-----------------------------------------------------------------*/
3867 /*-----------------------------------------------------------------*/
3868 static void genSkipz(iCode *ifx, int condition)
3871 assert (ifx != NULL);
3879 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3881 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3884 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3886 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3892 /*-----------------------------------------------------------------*/
3894 /*-----------------------------------------------------------------*/
3895 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3902 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3904 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3907 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3908 rifx->generated = 1;
3913 /*-----------------------------------------------------------------*/
3914 /* genChkZeroes :- greater or less than comparison */
3915 /* For each byte in a literal that is zero, inclusive or the */
3916 /* the corresponding byte in the operand with W */
3917 /* returns true if any of the bytes are zero */
3918 /*-----------------------------------------------------------------*/
3919 static int genChkZeroes(operand *op, int lit, int size)
3926 i = (lit >> (size*8)) & 0xff;
3930 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3932 emitpcode(POC_IORFW, popGet(AOP(op),size));
3942 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3943 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3944 #define DEBUGpc emitpComment
3946 /*-----------------------------------------------------------------*/
3947 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3948 /* aop (if it's NOT a literal) or from lit (if */
3949 /* aop is a literal) */
3950 /*-----------------------------------------------------------------*/
3951 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3952 if (aop->type == AOP_LIT) {
3953 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3955 emitpcode (POC_MOVFW, popGet (aop, offset));
3959 /* genCmp performs a left < right comparison, stores
3960 * the outcome in result (if != NULL) and generates
3961 * control flow code for the ifx (if != NULL).
3963 * This version leaves in sequences like
3964 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3965 * which should be optmized by the peephole
3966 * optimizer - RN 2005-01-01 */
3967 static void genCmp (operand *left,operand *right,
3968 operand *result, iCode *ifx, int sign)
3978 int invert_result = 0;
3982 assert (AOP_SIZE(left) == AOP_SIZE(right));
3983 assert (left && right);
3985 size = AOP_SIZE(right) - 1;
3986 mask = (0x100UL << (size*8)) - 1;
3987 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3992 resolveIfx (&rIfx, ifx);
3994 /**********************************************************************
3995 * handle bits - bit compares are promoted to int compares seemingly! *
3996 **********************************************************************/
3998 // THIS IS COMPLETELY UNTESTED!
3999 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4000 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4001 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4002 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4005 // 1 < {0,1} is false --> clear C by skipping the next instruction
4006 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4007 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4008 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4009 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4010 emitCLRC; // only skipped for left=0 && right=1
4012 goto correct_result_in_carry;
4016 /*************************************************
4017 * make sure that left is register (or the like) *
4018 *************************************************/
4019 if (!isAOP_REGlike(left)) {
4020 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4021 assert (isAOP_LIT(left));
4022 assert (isAOP_REGlike(right));
4023 // swap left and right
4024 // left < right <==> right > left <==> (right >= left + 1)
4025 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4027 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4028 // MAXVALUE < right? always false
4029 if (performedLt) emitCLRC; else emitSETC;
4030 goto correct_result_in_carry;
4033 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4034 // that's why we handled it above.
4041 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4042 } else if (isAOP_LIT(right)) {
4043 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4046 assert (isAOP_REGlike(left)); // left must be register or the like
4047 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4049 /*************************************************
4050 * special cases go here *
4051 *************************************************/
4053 if (isAOP_LIT(right)) {
4055 // unsigned comparison to a literal
4056 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4058 // unsigned left < 0? always false
4059 if (performedLt) emitCLRC; else emitSETC;
4060 goto correct_result_in_carry;
4063 // signed comparison to a literal
4064 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4065 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4066 // signed left < 0x80000000? always false
4067 if (performedLt) emitCLRC; else emitSETC;
4068 goto correct_result_in_carry;
4069 } else if (lit == 0) {
4070 // compare left < 0; set CARRY if SIGNBIT(left) is set
4071 if (performedLt) emitSETC; else emitCLRC;
4072 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4073 if (performedLt) emitCLRC; else emitSETC;
4074 goto correct_result_in_carry;
4077 } // right is literal
4079 /*************************************************
4080 * perform a general case comparison *
4081 * make sure we get CARRY==1 <==> left >= right *
4082 *************************************************/
4083 // compare most significant bytes
4084 //DEBUGpc ("comparing bytes at offset %d", size);
4086 // unsigned comparison
4087 pic14_mov2w_regOrLit (AOP(right), lit, size);
4088 emitpcode (POC_SUBFW, popGet (AOP(left), size));
4090 // signed comparison
4091 // (add 2^n to both operands then perform an unsigned comparison)
4092 if (isAOP_LIT(right)) {
4093 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4094 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4096 if (litbyte == 0x80) {
4097 // left >= 0x80 -- always true, but more bytes to come
4098 mov2w (AOP(left), size);
4099 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4102 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4103 mov2w (AOP(left), size);
4104 emitpcode (POC_ADDLW, popGetLit (0x80));
4105 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4108 pCodeOp *pctemp = popGetTempReg();
4109 mov2w (AOP(left), size);
4110 emitpcode (POC_ADDLW, popGetLit (0x80));
4111 emitpcode (POC_MOVWF, pctemp);
4112 mov2w (AOP(right), size);
4113 emitpcode (POC_ADDLW, popGetLit (0x80));
4114 emitpcode (POC_SUBFW, pctemp);
4115 popReleaseTempReg(pctemp);
4119 // compare remaining bytes (treat as unsigned case from above)
4120 templbl = newiTempLabel ( NULL );
4123 //DEBUGpc ("comparing bytes at offset %d", offs);
4125 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4126 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4127 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4129 emitpLabel (templbl->key);
4130 goto result_in_carry;
4134 /****************************************************
4135 * now CARRY contains the result of the comparison: *
4136 * SUBWF sets CARRY iff *
4137 * F-W >= 0 <==> F >= W <==> !(F < W) *
4138 * (F=left, W=right) *
4139 ****************************************************/
4143 // value will be used in the following genSkipc()
4144 rIfx.condition ^= 1;
4147 correct_result_in_carry:
4149 // assign result to variable (if neccessary)
4150 if (result && AOP_TYPE(result) != AOP_CRY) {
4151 //DEBUGpc ("assign result");
4152 size = AOP_SIZE(result);
4154 emitpcode (POC_CLRF, popGet (AOP(result), size));
4156 if (invert_result) {
4158 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4160 emitpcode (POC_RLF, popGet (AOP(result), 0));
4164 // perform conditional jump
4166 //DEBUGpc ("generate control flow");
4174 /* OLD VERSION -- BUGGY, DO NOT USE */
4176 /*-----------------------------------------------------------------*/
4177 /* genCmp :- greater or less than comparison */
4178 /*-----------------------------------------------------------------*/
4179 static void genCmp (operand *left,operand *right,
4180 operand *result, iCode *ifx, int sign)
4182 int size; //, offset = 0 ;
4183 unsigned long lit = 0L,i = 0;
4184 resolvedIfx rFalseIfx;
4185 // resolvedIfx rTrueIfx;
4189 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4192 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4193 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4197 resolveIfx(&rFalseIfx,ifx);
4198 truelbl = newiTempLabel(NULL);
4199 size = max(AOP_SIZE(left),AOP_SIZE(right));
4201 DEBUGpic14_AopType(__LINE__,left,right,result);
4205 /* if literal is on the right then swap with left */
4206 if ((AOP_TYPE(right) == AOP_LIT)) {
4207 operand *tmp = right ;
4208 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4209 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4212 lit = (lit - 1) & mask;
4215 rFalseIfx.condition ^= 1;
4218 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4219 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4223 //if(IC_TRUE(ifx) == NULL)
4224 /* if left & right are bit variables */
4225 if (AOP_TYPE(left) == AOP_CRY &&
4226 AOP_TYPE(right) == AOP_CRY ) {
4227 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4228 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4230 /* subtract right from left if at the
4231 end the carry flag is set then we know that
4232 left is greater than right */
4234 symbol *lbl = newiTempLabel(NULL);
4237 if(AOP_TYPE(right) == AOP_LIT) {
4239 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4241 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4248 genSkipCond(&rFalseIfx,left,size-1,7);
4250 /* no need to compare to 0...*/
4251 /* NOTE: this is a de-generate compare that most certainly
4252 * creates some dead code. */
4253 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4255 if(ifx) ifx->generated = 1;
4262 //i = (lit >> (size*8)) & 0xff;
4263 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4265 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4267 i = ((0-lit) & 0xff);
4270 /* lit is 0x7f, all signed chars are less than
4271 * this except for 0x7f itself */
4272 emitpcode(POC_XORLW, popGetLit(0x7f));
4273 genSkipz2(&rFalseIfx,0);
4275 emitpcode(POC_ADDLW, popGetLit(0x80));
4276 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4277 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4282 genSkipz2(&rFalseIfx,1);
4284 emitpcode(POC_ADDLW, popGetLit(i));
4285 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4289 if(ifx) ifx->generated = 1;
4293 /* chars are out of the way. now do ints and longs */
4296 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4303 genSkipCond(&rFalseIfx,left,size,7);
4304 if(ifx) ifx->generated = 1;
4309 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4311 //rFalseIfx.condition ^= 1;
4312 //genSkipCond(&rFalseIfx,left,size,7);
4313 //rFalseIfx.condition ^= 1;
4315 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4316 if(rFalseIfx.condition)
4317 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4319 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4321 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4322 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4323 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4326 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4328 if(rFalseIfx.condition) {
4330 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4336 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4337 emitpLabel(truelbl->key);
4338 if(ifx) ifx->generated = 1;
4345 if( (lit & 0xff) == 0) {
4346 /* lower byte is zero */
4347 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4348 i = ((lit >> 8) & 0xff) ^0x80;
4349 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4350 emitpcode(POC_ADDLW, popGetLit( 0x80));
4351 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4352 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4355 if(ifx) ifx->generated = 1;
4360 /* Special cases for signed longs */
4361 if( (lit & 0xffffff) == 0) {
4362 /* lower byte is zero */
4363 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4364 i = ((lit >> 8*3) & 0xff) ^0x80;
4365 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4366 emitpcode(POC_ADDLW, popGetLit( 0x80));
4367 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4368 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4371 if(ifx) ifx->generated = 1;
4379 if(lit & (0x80 << (size*8))) {
4380 /* lit is negative */
4381 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4383 //genSkipCond(&rFalseIfx,left,size,7);
4385 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4387 if(rFalseIfx.condition)
4388 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4390 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4394 /* lit is positive */
4395 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4396 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4397 if(rFalseIfx.condition)
4398 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4400 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4404 /* There are no more special cases, so perform a general compare */
4406 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4407 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4411 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4413 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4415 //rFalseIfx.condition ^= 1;
4416 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4418 emitpLabel(truelbl->key);
4420 if(ifx) ifx->generated = 1;
4427 /* sign is out of the way. So now do an unsigned compare */
4428 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4431 /* General case - compare to an unsigned literal on the right.*/
4433 i = (lit >> (size*8)) & 0xff;
4434 emitpcode(POC_MOVLW, popGetLit(i));
4435 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4437 i = (lit >> (size*8)) & 0xff;
4440 emitpcode(POC_MOVLW, popGetLit(i));
4442 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4444 /* this byte of the lit is zero,
4445 *if it's not the last then OR in the variable */
4447 emitpcode(POC_IORFW, popGet(AOP(left),size));
4452 emitpLabel(lbl->key);
4453 //if(emitFinalCheck)
4454 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4456 emitpLabel(truelbl->key);
4458 if(ifx) ifx->generated = 1;
4465 if(AOP_TYPE(left) == AOP_LIT) {
4466 //symbol *lbl = newiTempLabel(NULL);
4468 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4471 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4474 if((lit == 0) && (sign == 0)){
4477 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4479 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4481 genSkipz2(&rFalseIfx,0);
4482 if(ifx) ifx->generated = 1;
4489 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4490 /* degenerate compare can never be true */
4491 if(rFalseIfx.condition == 0)
4492 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4494 if(ifx) ifx->generated = 1;
4499 /* signed comparisons to a literal byte */
4501 int lp1 = (lit+1) & 0xff;
4503 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4506 rFalseIfx.condition ^= 1;
4507 genSkipCond(&rFalseIfx,right,0,7);
4510 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4511 emitpcode(POC_XORLW, popGetLit(0x7f));
4512 genSkipz2(&rFalseIfx,1);
4515 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4516 emitpcode(POC_ADDLW, popGetLit(0x80));
4517 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4518 rFalseIfx.condition ^= 1;
4519 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4522 if(ifx) ifx->generated = 1;
4524 /* unsigned comparisons to a literal byte */
4526 switch(lit & 0xff ) {
4528 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4529 genSkipz2(&rFalseIfx,0);
4530 if(ifx) ifx->generated = 1;
4533 genSkipCond(&rFalseIfx,right,0,7);
4534 if(ifx) ifx->generated = 1;
4538 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4539 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4540 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4541 rFalseIfx.condition ^= 1;
4542 if (AOP_TYPE(result) == AOP_CRY) {
4543 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4544 if(ifx) ifx->generated = 1;
4546 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4547 emitpcode(POC_CLRF, popGet(AOP(result),0));
4548 emitpcode(POC_RLF, popGet(AOP(result),0));
4549 emitpcode(POC_MOVLW, popGetLit(0x01));
4550 emitpcode(POC_XORWF, popGet(AOP(result),0));
4561 /* Size is greater than 1 */
4569 /* this means lit = 0xffffffff, or -1 */
4572 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4573 rFalseIfx.condition ^= 1;
4574 genSkipCond(&rFalseIfx,right,size,7);
4575 if(ifx) ifx->generated = 1;
4582 if(rFalseIfx.condition) {
4583 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4584 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4587 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4589 emitpcode(POC_IORFW, popGet(AOP(right),size));
4593 if(rFalseIfx.condition) {
4594 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4595 emitpLabel(truelbl->key);
4597 rFalseIfx.condition ^= 1;
4598 genSkipCond(&rFalseIfx,right,s,7);
4601 if(ifx) ifx->generated = 1;
4605 if((size == 1) && (0 == (lp1&0xff))) {
4606 /* lower byte of signed word is zero */
4607 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4608 i = ((lp1 >> 8) & 0xff) ^0x80;
4609 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4610 emitpcode(POC_ADDLW, popGetLit( 0x80));
4611 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4612 rFalseIfx.condition ^= 1;
4613 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4616 if(ifx) ifx->generated = 1;
4620 if(lit & (0x80 << (size*8))) {
4621 /* Lit is less than zero */
4622 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4623 //rFalseIfx.condition ^= 1;
4624 //genSkipCond(&rFalseIfx,left,size,7);
4625 //rFalseIfx.condition ^= 1;
4626 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4627 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4629 if(rFalseIfx.condition)
4630 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4632 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4636 /* Lit is greater than or equal to zero */
4637 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4638 //rFalseIfx.condition ^= 1;
4639 //genSkipCond(&rFalseIfx,right,size,7);
4640 //rFalseIfx.condition ^= 1;
4642 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4643 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4645 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4646 if(rFalseIfx.condition)
4647 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4649 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4654 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4655 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4659 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4661 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4663 rFalseIfx.condition ^= 1;
4664 //rFalseIfx.condition = 1;
4665 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4667 emitpLabel(truelbl->key);
4669 if(ifx) ifx->generated = 1;
4674 /* compare word or long to an unsigned literal on the right.*/
4679 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4682 break; /* handled above */
4685 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4687 emitpcode(POC_IORFW, popGet(AOP(right),size));
4688 genSkipz2(&rFalseIfx,0);
4692 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4694 emitpcode(POC_IORFW, popGet(AOP(right),size));
4697 if(rFalseIfx.condition)
4698 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4700 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4703 emitpcode(POC_MOVLW, popGetLit(lit+1));
4704 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4706 rFalseIfx.condition ^= 1;
4707 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4710 emitpLabel(truelbl->key);
4712 if(ifx) ifx->generated = 1;
4718 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4719 i = (lit >> (size*8)) & 0xff;
4721 emitpcode(POC_MOVLW, popGetLit(i));
4722 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4725 i = (lit >> (size*8)) & 0xff;
4728 emitpcode(POC_MOVLW, popGetLit(i));
4730 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4732 /* this byte of the lit is zero,
4733 *if it's not the last then OR in the variable */
4735 emitpcode(POC_IORFW, popGet(AOP(right),size));
4740 emitpLabel(lbl->key);
4742 rFalseIfx.condition ^= 1;
4743 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4747 emitpLabel(truelbl->key);
4748 if(ifx) ifx->generated = 1;
4752 /* Compare two variables */
4754 DEBUGpic14_emitcode(";sign","%d",sign);
4758 /* Sigh. thus sucks... */
4760 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4761 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4762 emitpcode(POC_MOVLW, popGetLit(0x80));
4763 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4764 emitpcode(POC_XORFW, popGet(AOP(right),size));
4765 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4767 /* Signed char comparison */
4768 /* Special thanks to Nikolai Golovchenko for this snippet */
4769 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4770 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4771 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4772 emitpcode(POC_XORFW, popGet(AOP(left),0));
4773 emitpcode(POC_XORFW, popGet(AOP(right),0));
4774 emitpcode(POC_ADDLW, popGetLit(0x80));
4776 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4777 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4779 if(ifx) ifx->generated = 1;
4785 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4786 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4790 /* The rest of the bytes of a multi-byte compare */
4794 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4797 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4798 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4803 emitpLabel(lbl->key);
4805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4806 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4807 (AOP_TYPE(result) == AOP_REG)) {
4808 emitpcode(POC_CLRF, popGet(AOP(result),0));
4809 emitpcode(POC_RLF, popGet(AOP(result),0));
4811 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4813 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4814 if(ifx) ifx->generated = 1;
4821 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4822 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4823 pic14_outBitC(result);
4825 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4826 /* if the result is used in the next
4827 ifx conditional branch then generate
4828 code a little differently */
4830 genIfxJump (ifx,"c");
4832 pic14_outBitC(result);
4833 /* leave the result in acc */
4839 /*-----------------------------------------------------------------*/
4840 /* genCmpGt :- greater than comparison */
4841 /*-----------------------------------------------------------------*/
4842 static void genCmpGt (iCode *ic, iCode *ifx)
4844 operand *left, *right, *result;
4845 sym_link *letype , *retype;
4849 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4851 right= IC_RIGHT(ic);
4852 result = IC_RESULT(ic);
4854 letype = getSpec(operandType(left));
4855 retype =getSpec(operandType(right));
4856 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4857 /* assign the amsops */
4858 aopOp (left,ic,FALSE);
4859 aopOp (right,ic,FALSE);
4860 aopOp (result,ic,TRUE);
4862 genCmp(right, left, result, ifx, sign);
4864 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4866 freeAsmop(result,NULL,ic,TRUE);
4869 /*-----------------------------------------------------------------*/
4870 /* genCmpLt - less than comparisons */
4871 /*-----------------------------------------------------------------*/
4872 static void genCmpLt (iCode *ic, iCode *ifx)
4874 operand *left, *right, *result;
4875 sym_link *letype , *retype;
4879 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4881 right= IC_RIGHT(ic);
4882 result = IC_RESULT(ic);
4884 letype = getSpec(operandType(left));
4885 retype =getSpec(operandType(right));
4886 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4888 /* assign the amsops */
4889 aopOp (left,ic,FALSE);
4890 aopOp (right,ic,FALSE);
4891 aopOp (result,ic,TRUE);
4893 genCmp(left, right, result, ifx, sign);
4895 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4896 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4897 freeAsmop(result,NULL,ic,TRUE);
4901 /*-----------------------------------------------------------------*/
4902 /* genc16bit2lit - compare a 16 bit value to a literal */
4903 /*-----------------------------------------------------------------*/
4904 static void genc16bit2lit(operand *op, int lit, int offset)
4909 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4910 if( (lit&0xff) == 0)
4915 switch( BYTEofLONG(lit,i)) {
4917 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4920 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4923 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4926 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4927 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4932 switch( BYTEofLONG(lit,i)) {
4934 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4938 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4942 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4945 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4947 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4955 /*-----------------------------------------------------------------*/
4956 /* gencjneshort - compare and jump if not equal */
4957 /*-----------------------------------------------------------------*/
4958 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4960 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4965 //unsigned long lit = 0L;
4967 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4968 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4971 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4972 DEBUGpic14_AopType(__LINE__,left,right,result);
4974 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4975 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4976 if (AOP_SIZE(result)) {
4977 for (offset = 0; offset < AOP_SIZE(result); offset++)
4978 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4981 assert (AOP_SIZE(left) == AOP_SIZE(right));
4982 //resolveIfx(&rIfx,ifx);
4983 lbl = newiTempLabel (NULL);
4986 mov2w (AOP(right),size);
4987 emitpcode (POC_XORFW, popGet (AOP(left), size));
4991 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4994 emitpLabel (lbl->key);
4995 if (AOP_SIZE(result)) {
4997 emitpcode (POC_INCF, popGet (AOP(result), 0));
5000 genSkipz (ifx, NULL != IC_TRUE(ifx));
5007 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5008 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5009 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5010 for (offset=0; offset < AOP_SIZE(result); offset++)
5012 emitpcode (POC_CLRF, popGet (AOP(result), offset));
5017 /* if the left side is a literal or
5018 if the right is in a pointer register and left
5020 if ((AOP_TYPE(left) == AOP_LIT) ||
5021 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5026 if(AOP_TYPE(right) == AOP_LIT)
5027 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5029 /* if the right side is a literal then anything goes */
5030 if (AOP_TYPE(right) == AOP_LIT &&
5031 AOP_TYPE(left) != AOP_DIR ) {
5034 genc16bit2lit(left, lit, 0);
5036 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5042 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5043 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5045 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5049 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5057 /* if the right side is in a register or in direct space or
5058 if the left is a pointer register & right is not */
5059 else if (AOP_TYPE(right) == AOP_REG ||
5060 AOP_TYPE(right) == AOP_DIR ||
5061 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5062 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5063 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5064 int lbl_key = lbl->key;
5067 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5068 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5069 __FUNCTION__,__LINE__);
5073 /* switch(size) { */
5075 /* genc16bit2lit(left, lit, 0); */
5077 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5083 if((AOP_TYPE(left) == AOP_DIR) &&
5084 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5086 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5087 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5089 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5091 switch (lit & 0xff) {
5093 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5096 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5097 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5098 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5102 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5103 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5104 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5105 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5109 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5110 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5115 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5118 if(AOP_TYPE(result) == AOP_CRY) {
5119 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5124 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5126 /* fix me. probably need to check result size too */
5127 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5132 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5142 } else if(AOP_TYPE(right) == AOP_REG &&
5143 AOP_TYPE(left) != AOP_DIR){
5147 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5148 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5149 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5154 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5159 /* right is a pointer reg need both a & b */
5162 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5164 pic14_emitcode("mov","b,%s",l);
5165 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5166 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5171 emitpcode(POC_INCF,popGet(AOP(result),0));
5173 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5175 emitpLabel(lbl->key);
5177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5186 /*-----------------------------------------------------------------*/
5187 /* gencjne - compare and jump if not equal */
5188 /*-----------------------------------------------------------------*/
5189 static void gencjne(operand *left, operand *right, iCode *ifx)
5191 symbol *tlbl = newiTempLabel(NULL);
5193 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5194 gencjneshort(left, right, lbl);
5196 pic14_emitcode("mov","a,%s",one);
5197 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5198 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5199 pic14_emitcode("clr","a");
5200 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5202 emitpLabel(lbl->key);
5203 emitpLabel(tlbl->key);
5208 /*-----------------------------------------------------------------*/
5209 /* genCmpEq - generates code for equal to */
5210 /*-----------------------------------------------------------------*/
5211 static void genCmpEq (iCode *ic, iCode *ifx)
5213 operand *left, *right, *result;
5215 symbol *false_label;
5218 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5221 DEBUGpic14_emitcode ("; ifx is non-null","");
5223 DEBUGpic14_emitcode ("; ifx is null","");
5225 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5226 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5227 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5229 DEBUGpic14_AopType(__LINE__,left,right,result);
5231 /* if literal, move literal to right */
5232 if (op_isLitLike (IC_LEFT(ic))) {
5233 operand *tmp = right ;
5239 if (ifx && !IC_TRUE(ifx))
5241 assert (IC_FALSE(ifx));
5242 false_label = IC_FALSE(ifx);
5245 size = min(AOP_SIZE(left),AOP_SIZE(right));
5246 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5247 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5249 /* assume left != right */
5252 for (i=0; i < AOP_SIZE(result); i++)
5254 emitpcode(POC_CLRF, popGet(AOP(result),i));
5258 if (AOP_TYPE(right) == AOP_LIT)
5260 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5262 size = AOP_SIZE(left);
5263 assert(!op_isLitLike(left));
5268 mov2w(AOP(left), 0);
5269 for (i=1; i < size; i++)
5270 emitpcode(POC_IORFW,popGet(AOP(left),i));
5271 /* now Z is set iff `left == right' */
5273 if (!false_label) false_label = newiTempLabel(NULL);
5274 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5278 for (i=0; i < size; i++)
5281 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5282 /* now Z is cleared if `left != right' */
5284 if (!false_label) false_label = newiTempLabel(NULL);
5285 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5292 /* right is no literal */
5295 for (i=0; i < size; i++)
5297 mov2w(AOP(right),i);
5298 emitpcode(POC_XORFW,popGet(AOP(left),i));
5299 /* now Z is cleared if `left != right' */
5301 if (!false_label) false_label = newiTempLabel(NULL);
5302 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5306 /* if we reach here, left == right */
5308 if (AOP_SIZE(result) > 0)
5310 emitpcode(POC_INCF, popGet(AOP(result),0));
5313 if (ifx && IC_TRUE(ifx))
5315 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5318 if (false_label && (!ifx || IC_TRUE(ifx)))
5319 emitpLabel(false_label->key);
5321 if (ifx) ifx->generated = 1;
5323 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5324 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5325 freeAsmop(result,NULL,ic,TRUE);
5328 /*-----------------------------------------------------------------*/
5329 /* ifxForOp - returns the icode containing the ifx for operand */
5330 /*-----------------------------------------------------------------*/
5331 static iCode *ifxForOp ( operand *op, iCode *ic )
5334 /* if true symbol then needs to be assigned */
5335 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5336 if (IS_TRUE_SYMOP(op))
5339 /* if this has register type condition and
5340 the next instruction is ifx with the same operand
5341 and live to of the operand is upto the ifx only then */
5343 ic->next->op == IFX &&
5344 IC_COND(ic->next)->key == op->key &&
5345 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5349 ic->next->op == IFX &&
5350 IC_COND(ic->next)->key == op->key) {
5351 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5355 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5357 ic->next->op == IFX)
5358 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5361 ic->next->op == IFX &&
5362 IC_COND(ic->next)->key == op->key) {
5363 DEBUGpic14_emitcode ("; "," key is okay");
5364 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5365 OP_SYMBOL(op)->liveTo,
5372 /*-----------------------------------------------------------------*/
5373 /* genAndOp - for && operation */
5374 /*-----------------------------------------------------------------*/
5375 static void genAndOp (iCode *ic)
5377 operand *left,*right, *result;
5381 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5382 /* note here that && operations that are in an
5383 if statement are taken away by backPatchLabels
5384 only those used in arthmetic operations remain */
5385 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5386 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5387 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5389 DEBUGpic14_AopType(__LINE__,left,right,result);
5391 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5392 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5393 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5395 /* if both are bit variables */
5396 /* if (AOP_TYPE(left) == AOP_CRY && */
5397 /* AOP_TYPE(right) == AOP_CRY ) { */
5398 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5399 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5400 /* pic14_outBitC(result); */
5402 /* tlbl = newiTempLabel(NULL); */
5403 /* pic14_toBoolean(left); */
5404 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5405 /* pic14_toBoolean(right); */
5406 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5407 /* pic14_outBitAcc(result); */
5410 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5411 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5412 freeAsmop(result,NULL,ic,TRUE);
5416 /*-----------------------------------------------------------------*/
5417 /* genOrOp - for || operation */
5418 /*-----------------------------------------------------------------*/
5421 modified this code, but it doesn't appear to ever get called
5424 static void genOrOp (iCode *ic)
5426 operand *left,*right, *result;
5430 /* note here that || operations that are in an
5431 if statement are taken away by backPatchLabels
5432 only those used in arthmetic operations remain */
5434 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5435 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5436 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5437 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5439 DEBUGpic14_AopType(__LINE__,left,right,result);
5441 for (i=0; i < AOP_SIZE(result); i++)
5443 emitpcode(POC_CLRF, popGet(AOP(result), i));
5446 tlbl = newiTempLabel(NULL);
5447 pic14_toBoolean(left);
5449 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5450 pic14_toBoolean(right);
5451 emitpLabel(tlbl->key);
5452 /* here Z is clear IFF `left || right' */
5454 emitpcode(POC_INCF, popGet(AOP(result), 0));
5456 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5457 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5458 freeAsmop(result,NULL,ic,TRUE);
5461 /*-----------------------------------------------------------------*/
5462 /* isLiteralBit - test if lit == 2^n */
5463 /*-----------------------------------------------------------------*/
5464 static int isLiteralBit(unsigned long lit)
5466 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5467 0x100L,0x200L,0x400L,0x800L,
5468 0x1000L,0x2000L,0x4000L,0x8000L,
5469 0x10000L,0x20000L,0x40000L,0x80000L,
5470 0x100000L,0x200000L,0x400000L,0x800000L,
5471 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5472 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5476 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5477 for(idx = 0; idx < 32; idx++)
5483 /*-----------------------------------------------------------------*/
5484 /* continueIfTrue - */
5485 /*-----------------------------------------------------------------*/
5486 static void continueIfTrue (iCode *ic)
5489 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5493 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5494 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5499 /*-----------------------------------------------------------------*/
5501 /*-----------------------------------------------------------------*/
5502 static void jumpIfTrue (iCode *ic)
5505 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5509 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5510 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5515 /*-----------------------------------------------------------------*/
5516 /* jmpTrueOrFalse - */
5517 /*-----------------------------------------------------------------*/
5518 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5521 // ugly but optimized by peephole
5522 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5524 symbol *nlbl = newiTempLabel(NULL);
5525 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5526 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5527 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5528 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5531 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5532 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5537 /*-----------------------------------------------------------------*/
5538 /* genAnd - code for and */
5539 /*-----------------------------------------------------------------*/
5540 static void genAnd (iCode *ic, iCode *ifx)
5542 operand *left, *right, *result;
5544 unsigned long lit = 0L;
5549 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5550 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5551 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5552 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5554 resolveIfx(&rIfx,ifx);
5556 /* if left is a literal & right is not then exchange them */
5557 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5558 AOP_NEEDSACC(left)) {
5559 operand *tmp = right ;
5564 /* if result = right then exchange them */
5565 if(pic14_sameRegs(AOP(result),AOP(right))){
5566 operand *tmp = right ;
5571 /* if right is bit then exchange them */
5572 if (AOP_TYPE(right) == AOP_CRY &&
5573 AOP_TYPE(left) != AOP_CRY){
5574 operand *tmp = right ;
5578 if(AOP_TYPE(right) == AOP_LIT)
5579 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5581 size = AOP_SIZE(result);
5583 DEBUGpic14_AopType(__LINE__,left,right,result);
5586 // result = bit & yy;
5587 if (AOP_TYPE(left) == AOP_CRY){
5588 // c = bit & literal;
5589 if(AOP_TYPE(right) == AOP_LIT){
5591 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5594 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5597 if(size && (AOP_TYPE(result) == AOP_CRY)){
5598 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5601 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5605 pic14_emitcode("clr","c");
5608 if (AOP_TYPE(right) == AOP_CRY){
5610 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5611 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5614 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5616 pic14_emitcode("rrc","a");
5617 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5623 pic14_outBitC(result);
5625 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5626 genIfxJump(ifx, "c");
5630 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5631 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5632 if((AOP_TYPE(right) == AOP_LIT) &&
5633 (AOP_TYPE(result) == AOP_CRY) &&
5634 (AOP_TYPE(left) != AOP_CRY)){
5635 int posbit = isLiteralBit(lit);
5639 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5642 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5647 while (posbit > 7) {
5651 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5652 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5653 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5660 symbol *tlbl = newiTempLabel(NULL);
5661 int sizel = AOP_SIZE(left);
5663 pic14_emitcode("setb","c");
5665 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5666 mov2w( AOP(left), offset);
5668 if((posbit = isLiteralBit(bytelit)) != 0) {
5669 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5670 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5671 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5674 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5675 if (rIfx.condition) emitSKPZ;
5678 if(bytelit != 0x0FFL)
5680 pic14_emitcode("anl","a,%s",
5681 aopGet(AOP(right),offset,FALSE,TRUE));
5683 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5686 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5692 // bit = left & literal
5694 pic14_emitcode("clr","c");
5695 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5697 // if(left & literal)
5700 jmpTrueOrFalse(ifx, tlbl);
5704 pic14_outBitC(result);
5708 /* if left is same as result */
5709 if(pic14_sameRegs(AOP(result),AOP(left))){
5711 for(;size--; offset++,lit>>=8) {
5712 if(AOP_TYPE(right) == AOP_LIT){
5713 switch(lit & 0xff) {
5715 /* and'ing with 0 has clears the result */
5716 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5719 /* and'ing with 0xff is a nop when the result and left are the same */
5724 int p = my_powof2( (~lit) & 0xff );
5726 /* only one bit is set in the literal, so use a bcf instruction */
5727 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5730 if(know_W != (int)(lit&0xff))
5731 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5733 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5738 if (AOP_TYPE(left) == AOP_ACC) {
5739 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5741 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5742 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5749 // left & result in different registers
5750 if(AOP_TYPE(result) == AOP_CRY){
5752 // if(size), result in bit
5753 // if(!size && ifx), conditional oper: if(left & right)
5754 symbol *tlbl = newiTempLabel(NULL);
5755 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5757 pic14_emitcode("setb","c");
5759 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5760 pic14_emitcode("anl","a,%s",
5761 aopGet(AOP(left),offset,FALSE,FALSE));
5762 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5767 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5768 pic14_outBitC(result);
5770 jmpTrueOrFalse(ifx, tlbl);
5772 for(;(size--);offset++) {
5774 // result = left & right
5775 if(AOP_TYPE(right) == AOP_LIT){
5776 int t = (lit >> (offset*8)) & 0x0FFL;
5779 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5782 if(AOP_TYPE(left) != AOP_ACC) {
5783 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5785 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5788 if(AOP_TYPE(left) == AOP_ACC) {
5789 emitpcode(POC_ANDLW, popGetLit(t));
5791 emitpcode(POC_MOVLW, popGetLit(t));
5792 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5794 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5799 if (AOP_TYPE(left) == AOP_ACC) {
5800 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5802 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5803 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5805 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5811 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5812 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5813 freeAsmop(result,NULL,ic,TRUE);
5816 /*-----------------------------------------------------------------*/
5817 /* genOr - code for or */
5818 /*-----------------------------------------------------------------*/
5819 static void genOr (iCode *ic, iCode *ifx)
5821 operand *left, *right, *result;
5823 unsigned long lit = 0L;
5826 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5828 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5829 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5830 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5832 DEBUGpic14_AopType(__LINE__,left,right,result);
5834 /* if left is a literal & right is not then exchange them */
5835 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5836 AOP_NEEDSACC(left)) {
5837 operand *tmp = right ;
5842 /* if result = right then exchange them */
5843 if(pic14_sameRegs(AOP(result),AOP(right))){
5844 operand *tmp = right ;
5849 /* if right is bit then exchange them */
5850 if (AOP_TYPE(right) == AOP_CRY &&
5851 AOP_TYPE(left) != AOP_CRY){
5852 operand *tmp = right ;
5857 DEBUGpic14_AopType(__LINE__,left,right,result);
5859 if(AOP_TYPE(right) == AOP_LIT)
5860 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5862 size = AOP_SIZE(result);
5866 if (AOP_TYPE(left) == AOP_CRY){
5867 if(AOP_TYPE(right) == AOP_LIT){
5868 // c = bit & literal;
5870 // lit != 0 => result = 1
5871 if(AOP_TYPE(result) == AOP_CRY){
5873 emitpcode(POC_BSF, popGet(AOP(result),0));
5874 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5875 // AOP(result)->aopu.aop_dir,
5876 // AOP(result)->aopu.aop_dir);
5878 continueIfTrue(ifx);
5882 // lit == 0 => result = left
5883 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5885 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5888 if (AOP_TYPE(right) == AOP_CRY){
5889 if(pic14_sameRegs(AOP(result),AOP(left))){
5891 emitpcode(POC_BCF, popGet(AOP(result),0));
5892 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5893 emitpcode(POC_BSF, popGet(AOP(result),0));
5895 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5896 AOP(result)->aopu.aop_dir,
5897 AOP(result)->aopu.aop_dir);
5898 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5899 AOP(right)->aopu.aop_dir,
5900 AOP(right)->aopu.aop_dir);
5901 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5902 AOP(result)->aopu.aop_dir,
5903 AOP(result)->aopu.aop_dir);
5905 if( AOP_TYPE(result) == AOP_ACC) {
5906 emitpcode(POC_MOVLW, popGetLit(0));
5907 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5908 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5909 emitpcode(POC_MOVLW, popGetLit(1));
5913 emitpcode(POC_BCF, popGet(AOP(result),0));
5914 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5915 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5916 emitpcode(POC_BSF, popGet(AOP(result),0));
5918 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5919 AOP(result)->aopu.aop_dir,
5920 AOP(result)->aopu.aop_dir);
5921 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5922 AOP(right)->aopu.aop_dir,
5923 AOP(right)->aopu.aop_dir);
5924 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5925 AOP(left)->aopu.aop_dir,
5926 AOP(left)->aopu.aop_dir);
5927 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5928 AOP(result)->aopu.aop_dir,
5929 AOP(result)->aopu.aop_dir);
5934 symbol *tlbl = newiTempLabel(NULL);
5935 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5938 emitpcode(POC_BCF, popGet(AOP(result),0));
5939 if( AOP_TYPE(right) == AOP_ACC) {
5940 emitpcode(POC_IORLW, popGetLit(0));
5942 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5943 emitpcode(POC_BSF, popGet(AOP(result),0));
5948 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5949 pic14_emitcode(";XXX setb","c");
5950 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5951 AOP(left)->aopu.aop_dir,tlbl->key+100);
5952 pic14_toBoolean(right);
5953 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5954 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5955 jmpTrueOrFalse(ifx, tlbl);
5959 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5966 pic14_outBitC(result);
5968 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5969 genIfxJump(ifx, "c");
5973 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5974 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5975 if((AOP_TYPE(right) == AOP_LIT) &&
5976 (AOP_TYPE(result) == AOP_CRY) &&
5977 (AOP_TYPE(left) != AOP_CRY)){
5979 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5982 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5984 continueIfTrue(ifx);
5987 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5988 // lit = 0, result = boolean(left)
5990 pic14_emitcode(";XXX setb","c");
5991 pic14_toBoolean(right);
5993 symbol *tlbl = newiTempLabel(NULL);
5994 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5996 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5998 genIfxJump (ifx,"a");
6002 pic14_outBitC(result);
6006 /* if left is same as result */
6007 if(pic14_sameRegs(AOP(result),AOP(left))){
6009 for(;size--; offset++,lit>>=8) {
6010 if(AOP_TYPE(right) == AOP_LIT){
6011 if((lit & 0xff) == 0)
6012 /* or'ing with 0 has no effect */
6015 int p = my_powof2(lit & 0xff);
6017 /* only one bit is set in the literal, so use a bsf instruction */
6019 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6021 if(know_W != (int)(lit & 0xff))
6022 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6023 know_W = lit & 0xff;
6024 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6029 if (AOP_TYPE(left) == AOP_ACC) {
6030 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6031 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6033 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6034 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6036 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6037 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6043 // left & result in different registers
6044 if(AOP_TYPE(result) == AOP_CRY){
6046 // if(size), result in bit
6047 // if(!size && ifx), conditional oper: if(left | right)
6048 symbol *tlbl = newiTempLabel(NULL);
6049 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6050 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6054 pic14_emitcode(";XXX setb","c");
6056 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6057 pic14_emitcode(";XXX orl","a,%s",
6058 aopGet(AOP(left),offset,FALSE,FALSE));
6059 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6064 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6065 pic14_outBitC(result);
6067 jmpTrueOrFalse(ifx, tlbl);
6068 } else for(;(size--);offset++){
6070 // result = left | right
6071 if(AOP_TYPE(right) == AOP_LIT){
6072 int t = (lit >> (offset*8)) & 0x0FFL;
6075 if (AOP_TYPE(left) != AOP_ACC) {
6076 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6078 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6082 if (AOP_TYPE(left) == AOP_ACC) {
6083 emitpcode(POC_IORLW, popGetLit(t));
6085 emitpcode(POC_MOVLW, popGetLit(t));
6086 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6088 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6093 // faster than result <- left, anl result,right
6094 // and better if result is SFR
6095 if (AOP_TYPE(left) == AOP_ACC) {
6096 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6098 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6099 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6101 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6106 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6108 freeAsmop(result,NULL,ic,TRUE);
6111 /*-----------------------------------------------------------------*/
6112 /* genXor - code for xclusive or */
6113 /*-----------------------------------------------------------------*/
6114 static void genXor (iCode *ic, iCode *ifx)
6116 operand *left, *right, *result;
6118 unsigned long lit = 0L;
6121 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6123 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6124 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6125 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6127 /* if left is a literal & right is not ||
6128 if left needs acc & right does not */
6129 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6130 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6131 operand *tmp = right ;
6136 /* if result = right then exchange them */
6137 if(pic14_sameRegs(AOP(result),AOP(right))){
6138 operand *tmp = right ;
6143 /* if right is bit then exchange them */
6144 if (AOP_TYPE(right) == AOP_CRY &&
6145 AOP_TYPE(left) != AOP_CRY){
6146 operand *tmp = right ;
6150 if(AOP_TYPE(right) == AOP_LIT)
6151 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6153 size = AOP_SIZE(result);
6157 if (AOP_TYPE(left) == AOP_CRY){
6158 if(AOP_TYPE(right) == AOP_LIT){
6159 // c = bit & literal;
6161 // lit>>1 != 0 => result = 1
6162 if(AOP_TYPE(result) == AOP_CRY){
6164 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6165 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6167 continueIfTrue(ifx);
6170 pic14_emitcode("setb","c");
6174 // lit == 0, result = left
6175 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6177 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6179 // lit == 1, result = not(left)
6180 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6181 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6182 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6183 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6186 assert ( !"incomplete genXor" );
6187 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6188 pic14_emitcode("cpl","c");
6195 symbol *tlbl = newiTempLabel(NULL);
6196 if (AOP_TYPE(right) == AOP_CRY){
6198 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6201 int sizer = AOP_SIZE(right);
6203 // if val>>1 != 0, result = 1
6204 pic14_emitcode("setb","c");
6206 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6208 // test the msb of the lsb
6209 pic14_emitcode("anl","a,#0xfe");
6210 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6214 pic14_emitcode("rrc","a");
6216 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6217 pic14_emitcode("cpl","c");
6218 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6223 pic14_outBitC(result);
6225 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6226 genIfxJump(ifx, "c");
6230 if(pic14_sameRegs(AOP(result),AOP(left))){
6231 /* if left is same as result */
6232 for(;size--; offset++) {
6233 if(AOP_TYPE(right) == AOP_LIT){
6234 int t = (lit >> (offset*8)) & 0x0FFL;
6238 if (IS_AOP_PREG(left)) {
6239 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6240 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6241 aopPut(AOP(result),"a",offset);
6243 emitpcode(POC_MOVLW, popGetLit(t));
6244 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6245 pic14_emitcode("xrl","%s,%s",
6246 aopGet(AOP(left),offset,FALSE,TRUE),
6247 aopGet(AOP(right),offset,FALSE,FALSE));
6250 if (AOP_TYPE(left) == AOP_ACC)
6251 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6253 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6254 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6256 if (IS_AOP_PREG(left)) {
6257 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6258 aopPut(AOP(result),"a",offset);
6260 pic14_emitcode("xrl","%s,a",
6261 aopGet(AOP(left),offset,FALSE,TRUE));
6267 // left & result in different registers
6268 if(AOP_TYPE(result) == AOP_CRY){
6270 // if(size), result in bit
6271 // if(!size && ifx), conditional oper: if(left ^ right)
6272 symbol *tlbl = newiTempLabel(NULL);
6273 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6275 pic14_emitcode("setb","c");
6277 if((AOP_TYPE(right) == AOP_LIT) &&
6278 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6279 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6281 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6282 pic14_emitcode("xrl","a,%s",
6283 aopGet(AOP(left),offset,FALSE,FALSE));
6285 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6290 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6291 pic14_outBitC(result);
6293 jmpTrueOrFalse(ifx, tlbl);
6294 } else for(;(size--);offset++){
6296 // result = left & right
6297 if(AOP_TYPE(right) == AOP_LIT){
6298 int t = (lit >> (offset*8)) & 0x0FFL;
6301 if (AOP_TYPE(left) != AOP_ACC) {
6302 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6304 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6305 pic14_emitcode("movf","%s,w",
6306 aopGet(AOP(left),offset,FALSE,FALSE));
6307 pic14_emitcode("movwf","%s",
6308 aopGet(AOP(result),offset,FALSE,FALSE));
6311 if (AOP_TYPE(left) == AOP_ACC) {
6312 emitpcode(POC_XORLW, popGetLit(t));
6314 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6316 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6319 if (AOP_TYPE(left) == AOP_ACC) {
6320 emitpcode(POC_XORLW, popGetLit(t));
6322 emitpcode(POC_MOVLW, popGetLit(t));
6323 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6325 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6326 pic14_emitcode("movlw","0x%x",t);
6327 pic14_emitcode("xorwf","%s,w",
6328 aopGet(AOP(left),offset,FALSE,FALSE));
6329 pic14_emitcode("movwf","%s",
6330 aopGet(AOP(result),offset,FALSE,FALSE));
6336 // faster than result <- left, anl result,right
6337 // and better if result is SFR
6338 if (AOP_TYPE(left) == AOP_ACC) {
6339 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6341 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6342 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6344 if ( AOP_TYPE(result) != AOP_ACC){
6345 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6351 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6352 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6353 freeAsmop(result,NULL,ic,TRUE);
6356 /*-----------------------------------------------------------------*/
6357 /* genInline - write the inline code out */
6358 /*-----------------------------------------------------------------*/
6359 static void genInline (iCode *ic)
6361 char *buffer, *bp, *bp1;
6364 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6366 _G.inLine += (!options.asmpeep);
6368 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6369 strcpy(buffer,IC_INLINE(ic));
6371 /* emit each line as a code */
6377 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6385 /* print label, use this special format with NULL directive
6386 * to denote that the argument should not be indented with tab */
6387 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6394 if ((bp1 != bp) && *bp1)
6395 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6399 _G.inLine -= (!options.asmpeep);
6402 /*-----------------------------------------------------------------*/
6403 /* genRRC - rotate right with carry */
6404 /*-----------------------------------------------------------------*/
6405 static void genRRC (iCode *ic)
6407 operand *left , *result ;
6408 int size, offset = 0, same;
6411 /* rotate right with carry */
6413 result=IC_RESULT(ic);
6414 aopOp (left,ic,FALSE);
6415 aopOp (result,ic,FALSE);
6417 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6419 same = pic14_sameRegs(AOP(result),AOP(left));
6421 size = AOP_SIZE(result);
6423 /* get the lsb and put it into the carry */
6424 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6431 emitpcode(POC_RRF, popGet(AOP(left),offset));
6433 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6434 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6440 freeAsmop(left,NULL,ic,TRUE);
6441 freeAsmop(result,NULL,ic,TRUE);
6444 /*-----------------------------------------------------------------*/
6445 /* genRLC - generate code for rotate left with carry */
6446 /*-----------------------------------------------------------------*/
6447 static void genRLC (iCode *ic)
6449 operand *left , *result ;
6450 int size, offset = 0;
6454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6455 /* rotate right with carry */
6457 result=IC_RESULT(ic);
6458 aopOp (left,ic,FALSE);
6459 aopOp (result,ic,FALSE);
6461 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6463 same = pic14_sameRegs(AOP(result),AOP(left));
6465 /* move it to the result */
6466 size = AOP_SIZE(result);
6468 /* get the msb and put it into the carry */
6469 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6476 emitpcode(POC_RLF, popGet(AOP(left),offset));
6478 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6479 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6486 freeAsmop(left,NULL,ic,TRUE);
6487 freeAsmop(result,NULL,ic,TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* genGetHbit - generates code get highest order bit */
6492 /*-----------------------------------------------------------------*/
6493 static void genGetHbit (iCode *ic)
6495 operand *left, *result;
6497 result=IC_RESULT(ic);
6498 aopOp (left,ic,FALSE);
6499 aopOp (result,ic,FALSE);
6502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6503 /* get the highest order byte into a */
6504 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6505 if(AOP_TYPE(result) == AOP_CRY){
6506 pic14_emitcode("rlc","a");
6507 pic14_outBitC(result);
6510 pic14_emitcode("rl","a");
6511 pic14_emitcode("anl","a,#0x01");
6512 pic14_outAcc(result);
6516 freeAsmop(left,NULL,ic,TRUE);
6517 freeAsmop(result,NULL,ic,TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* AccLsh - shift left accumulator by known count */
6522 /* MARK: pic14 always rotates through CARRY! */
6523 /*-----------------------------------------------------------------*/
6524 static void AccLsh (pCodeOp *pcop,int shCount)
6527 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6528 shCount &= 0x0007; // shCount : 0..7
6535 emitpcode(POC_RLF,pcop);
6539 emitpcode(POC_RLF,pcop);
6540 emitpcode(POC_RLF,pcop);
6543 emitpcode(POC_RLF,pcop);
6544 emitpcode(POC_RLF,pcop);
6545 emitpcode(POC_RLF,pcop);
6548 emitpcode(POC_SWAPF,pcop);
6551 emitpcode(POC_SWAPF,pcop);
6552 emitpcode(POC_RLF,pcop);
6555 emitpcode(POC_SWAPF,pcop);
6556 emitpcode(POC_RLF,pcop);
6557 emitpcode(POC_RLF,pcop);
6560 emitpcode(POC_RRFW,pcop);
6561 emitpcode(POC_RRF,pcop);
6564 /* clear invalid bits */
6565 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6566 emitpcode(POC_ANDWF, pcop);
6569 /*-----------------------------------------------------------------*/
6570 /* AccRsh - shift right accumulator by known count */
6571 /* MARK: pic14 always rotates through CARRY! */
6572 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6573 /* 1: mask out invalid bits (zero-extend) */
6574 /* 2: sign-extend result (pretty slow) */
6575 /*-----------------------------------------------------------------*/
6576 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6579 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6580 shCount &= 0x0007; // shCount : 0..7
6586 /* load sign if needed */
6587 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6588 else if (mask_mode == 1) emitCLRC;
6589 emitpcode(POC_RRF,pcop);
6593 /* load sign if needed */
6594 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6595 emitpcode(POC_RRF,pcop);
6596 /* load sign if needed */
6597 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6598 emitpcode(POC_RRF,pcop);
6599 if (mask_mode == 2) return;
6602 /* load sign if needed */
6603 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6604 emitpcode(POC_RRF,pcop);
6605 /* load sign if needed */
6606 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6607 emitpcode(POC_RRF,pcop);
6608 /* load sign if needed */
6609 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6610 emitpcode(POC_RRF,pcop);
6611 if (mask_mode == 2) return;
6614 emitpcode(POC_SWAPF,pcop);
6617 emitpcode(POC_SWAPF,pcop);
6618 emitpcode(POC_RRF,pcop);
6621 emitpcode(POC_SWAPF,pcop);
6622 emitpcode(POC_RRF,pcop);
6623 emitpcode(POC_RRF,pcop);
6629 emitpcode(POC_RLFW,pcop);
6630 emitpcode(POC_CLRF,pcop);
6632 emitpcode(POC_COMF,pcop);
6635 emitpcode(POC_RLFW,pcop);
6636 emitpcode(POC_RLF,pcop);
6643 /* leave invalid bits undefined */
6647 /* clear invalid bits -- zero-extend */
6648 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6649 emitpcode(POC_ANDWF, pcop);
6651 if (mask_mode == 2) {
6653 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6654 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6655 emitpcode(POC_IORWF, pcop);
6660 /*-----------------------------------------------------------------*/
6661 /* AccSRsh - signed right shift accumulator by known count */
6662 /*-----------------------------------------------------------------*/
6663 static void AccSRsh (int shCount)
6666 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6669 pic14_emitcode("mov","c,acc.7");
6670 pic14_emitcode("rrc","a");
6671 } else if(shCount == 2){
6672 pic14_emitcode("mov","c,acc.7");
6673 pic14_emitcode("rrc","a");
6674 pic14_emitcode("mov","c,acc.7");
6675 pic14_emitcode("rrc","a");
6677 tlbl = newiTempLabel(NULL);
6678 /* rotate right accumulator */
6679 AccRol(8 - shCount);
6680 /* and kill the higher order bits */
6681 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6682 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6683 pic14_emitcode("orl","a,#0x%02x",
6684 (unsigned char)~SRMask[shCount]);
6685 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6690 /*-----------------------------------------------------------------*/
6691 /* shiftR1Left2Result - shift right one byte from left to result */
6692 /*-----------------------------------------------------------------*/
6693 static void shiftR1Left2ResultSigned (operand *left, int offl,
6694 operand *result, int offr,
6700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6702 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6706 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6708 emitpcode(POC_RRF, popGet(AOP(result),offr));
6710 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6711 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6717 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6719 emitpcode(POC_RRF, popGet(AOP(result),offr));
6721 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6724 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6725 emitpcode(POC_RRF, popGet(AOP(result),offr));
6731 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6733 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6734 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6737 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6738 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6739 emitpcode(POC_ANDLW, popGetLit(0x1f));
6741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6742 emitpcode(POC_IORLW, popGetLit(0xe0));
6744 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6748 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6749 emitpcode(POC_ANDLW, popGetLit(0x0f));
6750 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6751 emitpcode(POC_IORLW, popGetLit(0xf0));
6752 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6756 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6758 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6759 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6761 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6762 emitpcode(POC_ANDLW, popGetLit(0x07));
6763 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6764 emitpcode(POC_IORLW, popGetLit(0xf8));
6765 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6770 emitpcode(POC_MOVLW, popGetLit(0x00));
6771 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6772 emitpcode(POC_MOVLW, popGetLit(0xfe));
6773 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6774 emitpcode(POC_IORLW, popGetLit(0x01));
6775 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6777 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6778 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6779 emitpcode(POC_DECF, popGet(AOP(result),offr));
6780 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6781 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6787 emitpcode(POC_MOVLW, popGetLit(0x00));
6788 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6789 emitpcode(POC_MOVLW, popGetLit(0xff));
6790 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6792 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6793 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6794 emitpcode(POC_DECF, popGet(AOP(result),offr));
6802 /*-----------------------------------------------------------------*/
6803 /* shiftR1Left2Result - shift right one byte from left to result */
6804 /*-----------------------------------------------------------------*/
6805 static void shiftR1Left2Result (operand *left, int offl,
6806 operand *result, int offr,
6807 int shCount, int sign)
6812 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6814 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6816 /* Copy the msb into the carry if signed. */
6818 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6828 emitpcode(POC_RRF, popGet(AOP(result),offr));
6830 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6831 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6837 emitpcode(POC_RRF, popGet(AOP(result),offr));
6839 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6840 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6843 emitpcode(POC_RRF, popGet(AOP(result),offr));
6848 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6850 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6851 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6854 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6855 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6856 emitpcode(POC_ANDLW, popGetLit(0x1f));
6857 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6861 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6862 emitpcode(POC_ANDLW, popGetLit(0x0f));
6863 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6867 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6868 emitpcode(POC_ANDLW, popGetLit(0x0f));
6869 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6871 emitpcode(POC_RRF, popGet(AOP(result),offr));
6876 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877 emitpcode(POC_ANDLW, popGetLit(0x80));
6878 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6879 emitpcode(POC_RLF, popGet(AOP(result),offr));
6880 emitpcode(POC_RLF, popGet(AOP(result),offr));
6885 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6886 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6887 emitpcode(POC_RLF, popGet(AOP(result),offr));
6896 /*-----------------------------------------------------------------*/
6897 /* shiftL1Left2Result - shift left one byte from left to result */
6898 /*-----------------------------------------------------------------*/
6899 static void shiftL1Left2Result (operand *left, int offl,
6900 operand *result, int offr, int shCount)
6906 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6908 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6909 DEBUGpic14_emitcode ("; ***","same = %d",same);
6910 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6912 /* shift left accumulator */
6913 //AccLsh(shCount); // don't comment out just yet...
6914 // aopPut(AOP(result),"a",offr);
6918 /* Shift left 1 bit position */
6919 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6921 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6923 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6924 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6928 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6929 emitpcode(POC_ANDLW,popGetLit(0x7e));
6930 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6931 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6934 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6935 emitpcode(POC_ANDLW,popGetLit(0x3e));
6936 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6937 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6938 emitpcode(POC_RLF, popGet(AOP(result),offr));
6941 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6942 emitpcode(POC_ANDLW, popGetLit(0xf0));
6943 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6946 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6947 emitpcode(POC_ANDLW, popGetLit(0xf0));
6948 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6949 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6952 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6953 emitpcode(POC_ANDLW, popGetLit(0x30));
6954 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6955 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6956 emitpcode(POC_RLF, popGet(AOP(result),offr));
6959 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6960 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6961 emitpcode(POC_RRF, popGet(AOP(result),offr));
6965 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6971 /*-----------------------------------------------------------------*/
6972 /* movLeft2Result - move byte from left to result */
6973 /*-----------------------------------------------------------------*/
6974 static void movLeft2Result (operand *left, int offl,
6975 operand *result, int offr)
6979 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6980 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6981 l = aopGet(AOP(left),offl,FALSE,FALSE);
6983 if (*l == '@' && (IS_AOP_PREG(result))) {
6984 pic14_emitcode("mov","a,%s",l);
6985 aopPut(AOP(result),"a",offr);
6987 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6988 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6993 /*-----------------------------------------------------------------*/
6994 /* shiftLeft_Left2ResultLit - shift left by known count */
6995 /*-----------------------------------------------------------------*/
6997 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6999 int size, same, offr, i;
7001 size = AOP_SIZE(left);
7002 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7004 same = pic14_sameRegs (AOP(left), AOP(result));
7007 shCount = shCount & 0x07;
7013 case 0: /* takes 0 or 2N cycles (for offr==0) */
7014 if (!same || offr) {
7015 for (i=size-1; i >= 0; i--)
7016 movLeft2Result (left, i, result, offr + i);
7020 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7022 shiftLeft_Left2ResultLit (left, result, 8 * offr);
7023 shiftLeft_Left2ResultLit (result, result, shCount);
7024 return; /* prevent clearing result again */
7027 for (i=0; i < size; i++) {
7028 if (same && !offr) {
7029 emitpcode (POC_RLF, popGet (AOP(left), i));
7031 emitpcode (POC_RLFW, popGet (AOP(left), i));
7032 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7038 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7039 /* works in-place/with offr as well */
7040 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7041 emitpcode (POC_ANDLW, popGetLit (0xF0));
7042 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7044 for (i = size - 2; i >= 0; i--)
7046 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7047 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7048 emitpcode (POC_ANDLW, popGetLit (0x0F));
7049 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7050 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7054 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7055 /* works in-place/with offr as well */
7056 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7057 for (i = size-2; i >= 0; i--) {
7058 emitpcode (POC_RRFW, popGet (AOP(left), i));
7059 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7061 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7062 emitpcode (POC_RRF, popGet (AOP(result), offr));
7066 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7067 shiftLeft_Left2ResultLit (result, result, 1);
7068 return; /* prevent clearing result again */
7074 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7078 /*-----------------------------------------------------------------*/
7079 /* shiftRight_Left2ResultLit - shift right by known count */
7080 /*-----------------------------------------------------------------*/
7082 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7084 int size, same, offr, i;
7086 size = AOP_SIZE(left);
7087 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7089 same = pic14_sameRegs (AOP(left), AOP(result));
7092 shCount = shCount & 0x07;
7100 case 0: /* takes 0 or 2N cycles (for offr==0) */
7101 if (!same || offr) {
7102 for (i=0; i < size; i++)
7103 movLeft2Result (left, i + offr, result, i);
7107 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7108 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7110 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7111 shiftRight_Left2ResultLit (result, result, shCount, sign);
7112 return; /* prevent sign-extending result again */
7116 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7119 for (i = size-1; i >= 0; i--) {
7120 if (same && !offr) {
7121 emitpcode (POC_RRF, popGet (AOP(left), i));
7123 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7124 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7130 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7131 /* works in-place/with offr as well */
7132 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7133 emitpcode (POC_ANDLW, popGetLit (0x0F));
7134 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7136 for (i = 1; i < size; i++)
7138 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7139 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7140 emitpcode (POC_ANDLW, popGetLit (0xF0));
7141 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7142 emitpcode (POC_XORWF, popGet (AOP(result), i));
7147 emitpcode (POC_MOVLW, popGetLit (0xF0));
7148 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7149 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7153 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7154 /* works in-place/with offr as well */
7155 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7156 for (i = 0; i < size-1; i++) {
7157 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7158 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7160 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7162 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7165 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7170 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7171 shiftRight_Left2ResultLit (result, result, 1, sign);
7172 return; /* prevent sign extending result again */
7177 addSign (result, size, sign);
7181 /*-----------------------------------------------------------------*/
7182 /* shiftL2Left2Result - shift left two bytes from left to result */
7183 /*-----------------------------------------------------------------*/
7184 static void shiftL2Left2Result (operand *left, int offl,
7185 operand *result, int offr, int shCount)
7189 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7191 if(pic14_sameRegs(AOP(result), AOP(left))) {
7199 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7200 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7201 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7205 emitpcode(POC_RLF, popGet(AOP(result),offr));
7206 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7212 emitpcode(POC_MOVLW, popGetLit(0x0f));
7213 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7214 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7215 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7216 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7217 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7218 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7220 emitpcode(POC_RLF, popGet(AOP(result),offr));
7221 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7225 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7226 emitpcode(POC_RRF, popGet(AOP(result),offr));
7227 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7228 emitpcode(POC_RRF, popGet(AOP(result),offr));
7229 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7230 emitpcode(POC_ANDLW,popGetLit(0xc0));
7231 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7232 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7233 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7234 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7237 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7238 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7239 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7240 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7241 emitpcode(POC_RRF, popGet(AOP(result),offr));
7251 /* note, use a mov/add for the shift since the mov has a
7252 chance of getting optimized out */
7253 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7254 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7255 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7256 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7257 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7261 emitpcode(POC_RLF, popGet(AOP(result),offr));
7262 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7268 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7269 emitpcode(POC_ANDLW, popGetLit(0xF0));
7270 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7271 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7272 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7273 emitpcode(POC_ANDLW, popGetLit(0xF0));
7274 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7275 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7279 emitpcode(POC_RLF, popGet(AOP(result),offr));
7280 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7284 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7285 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7286 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7287 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7289 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7290 emitpcode(POC_RRF, popGet(AOP(result),offr));
7291 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7292 emitpcode(POC_ANDLW,popGetLit(0xc0));
7293 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7294 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7295 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7296 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7299 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7300 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7301 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7302 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7303 emitpcode(POC_RRF, popGet(AOP(result),offr));
7309 /*-----------------------------------------------------------------*/
7310 /* shiftR2Left2Result - shift right two bytes from left to result */
7311 /*-----------------------------------------------------------------*/
7312 static void shiftR2Left2Result (operand *left, int offl,
7313 operand *result, int offr,
7314 int shCount, int sign)
7319 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7320 same = pic14_sameRegs(AOP(result), AOP(left));
7322 if(same && ((offl + MSB16) == offr)){
7324 /* don't crash result[offr] */
7325 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7326 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7329 movLeft2Result(left,offl, result, offr);
7330 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7333 /* a:x >> shCount (x = lsb(result))*/
7336 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7338 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7347 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7352 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7353 emitpcode(POC_RRF,popGet(AOP(result),offr));
7355 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7356 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7357 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7358 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7363 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7366 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7367 emitpcode(POC_RRF,popGet(AOP(result),offr));
7374 emitpcode(POC_MOVLW, popGetLit(0xf0));
7375 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7376 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7378 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7380 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7381 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7383 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7384 emitpcode(POC_ANDLW, popGetLit(0x0f));
7385 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7387 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7388 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7389 emitpcode(POC_ANDLW, popGetLit(0xf0));
7390 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7391 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7395 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7396 emitpcode(POC_RRF, popGet(AOP(result),offr));
7400 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7401 emitpcode(POC_BTFSC,
7402 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7403 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7411 emitpcode(POC_RLF, popGet(AOP(result),offr));
7412 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7414 emitpcode(POC_RLF, popGet(AOP(result),offr));
7415 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7416 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7417 emitpcode(POC_ANDLW,popGetLit(0x03));
7419 emitpcode(POC_BTFSC,
7420 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7421 emitpcode(POC_IORLW,popGetLit(0xfc));
7423 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7424 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7425 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7426 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7428 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7429 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7430 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7431 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7432 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7433 emitpcode(POC_RLF, popGet(AOP(result),offr));
7434 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7435 emitpcode(POC_ANDLW,popGetLit(0x03));
7437 emitpcode(POC_BTFSC,
7438 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7439 emitpcode(POC_IORLW,popGetLit(0xfc));
7441 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7442 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7449 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7450 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7451 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7452 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7455 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7457 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7461 /*-----------------------------------------------------------------*/
7462 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7463 /*-----------------------------------------------------------------*/
7464 static void shiftLLeftOrResult (operand *left, int offl,
7465 operand *result, int offr, int shCount)
7468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7470 /* shift left accumulator */
7471 AccLsh(left,offl,shCount);
7472 /* or with result */
7473 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7474 assert ( !"broken (modifies left, fails for left==result))" );
7477 /*-----------------------------------------------------------------*/
7478 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7479 /*-----------------------------------------------------------------*/
7480 static void shiftRLeftOrResult (operand *left, int offl,
7481 operand *result, int offr, int shCount)
7484 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7486 /* shift right accumulator */
7487 AccRsh(left,offl,shCount);
7488 /* or with result */
7489 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7490 assert ( !"broken (modifies left, fails for left==result))" );
7493 /*-----------------------------------------------------------------*/
7494 /* genlshOne - left shift a one byte quantity by known count */
7495 /*-----------------------------------------------------------------*/
7496 static void genlshOne (operand *result, operand *left, int shCount)
7499 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7500 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7503 /*-----------------------------------------------------------------*/
7504 /* genlshTwo - left shift two bytes by known amount != 0 */
7505 /*-----------------------------------------------------------------*/
7506 static void genlshTwo (operand *result,operand *left, int shCount)
7511 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7512 size = pic14_getDataSize(result);
7514 /* if shCount >= 8 */
7520 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7522 movLeft2Result(left, LSB, result, MSB16);
7524 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7527 /* 1 <= shCount <= 7 */
7530 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7532 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7536 /*-----------------------------------------------------------------*/
7537 /* shiftLLong - shift left one long from left to result */
7538 /* offl = LSB or MSB16 */
7539 /*-----------------------------------------------------------------*/
7540 static void shiftLLong (operand *left, operand *result, int offr )
7543 int size = AOP_SIZE(result);
7546 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7547 if(size >= LSB+offr){
7548 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7550 pic14_emitcode("add","a,acc");
7551 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7552 size >= MSB16+offr && offr != LSB )
7553 pic14_emitcode("xch","a,%s",
7554 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7556 aopPut(AOP(result),"a",LSB+offr);
7559 if(size >= MSB16+offr){
7560 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7561 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7564 pic14_emitcode("rlc","a");
7565 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7566 size >= MSB24+offr && offr != LSB)
7567 pic14_emitcode("xch","a,%s",
7568 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7570 aopPut(AOP(result),"a",MSB16+offr);
7573 if(size >= MSB24+offr){
7574 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7575 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7578 pic14_emitcode("rlc","a");
7579 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7580 size >= MSB32+offr && offr != LSB )
7581 pic14_emitcode("xch","a,%s",
7582 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7584 aopPut(AOP(result),"a",MSB24+offr);
7587 if(size > MSB32+offr){
7588 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7589 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7592 pic14_emitcode("rlc","a");
7593 aopPut(AOP(result),"a",MSB32+offr);
7596 aopPut(AOP(result),zero,LSB);
7599 /*-----------------------------------------------------------------*/
7600 /* genlshFour - shift four byte by a known amount != 0 */
7601 /*-----------------------------------------------------------------*/
7602 static void genlshFour (operand *result, operand *left, int shCount)
7607 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7608 size = AOP_SIZE(result);
7610 /* if shifting more that 3 bytes */
7611 if (shCount >= 24 ) {
7614 /* lowest order of left goes to the highest
7615 order of the destination */
7616 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7618 movLeft2Result(left, LSB, result, MSB32);
7619 aopPut(AOP(result),zero,LSB);
7620 aopPut(AOP(result),zero,MSB16);
7621 aopPut(AOP(result),zero,MSB32);
7625 /* more than two bytes */
7626 else if ( shCount >= 16 ) {
7627 /* lower order two bytes goes to higher order two bytes */
7629 /* if some more remaining */
7631 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7633 movLeft2Result(left, MSB16, result, MSB32);
7634 movLeft2Result(left, LSB, result, MSB24);
7636 aopPut(AOP(result),zero,MSB16);
7637 aopPut(AOP(result),zero,LSB);
7641 /* if more than 1 byte */
7642 else if ( shCount >= 8 ) {
7643 /* lower order three bytes goes to higher order three bytes */
7647 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7649 movLeft2Result(left, LSB, result, MSB16);
7651 else{ /* size = 4 */
7653 movLeft2Result(left, MSB24, result, MSB32);
7654 movLeft2Result(left, MSB16, result, MSB24);
7655 movLeft2Result(left, LSB, result, MSB16);
7656 aopPut(AOP(result),zero,LSB);
7658 else if(shCount == 1)
7659 shiftLLong(left, result, MSB16);
7661 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7662 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7663 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7664 aopPut(AOP(result),zero,LSB);
7669 /* 1 <= shCount <= 7 */
7670 else if(shCount <= 2){
7671 shiftLLong(left, result, LSB);
7673 shiftLLong(result, result, LSB);
7675 /* 3 <= shCount <= 7, optimize */
7677 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7678 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7679 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7685 /*-----------------------------------------------------------------*/
7686 /* genLeftShiftLiteral - left shifting by known count */
7687 /*-----------------------------------------------------------------*/
7688 static void genLeftShiftLiteral (operand *left,
7693 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7697 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7698 freeAsmop(right,NULL,ic,TRUE);
7700 aopOp(left,ic,FALSE);
7701 aopOp(result,ic,FALSE);
7703 size = getSize(operandType(result));
7706 pic14_emitcode("; shift left ","result %d, left %d",size,
7710 /* I suppose that the left size >= result size */
7713 movLeft2Result(left, size, result, size);
7717 else if(shCount >= (size * 8))
7719 aopPut(AOP(result),zero,size);
7723 genlshOne (result,left,shCount);
7728 genlshTwo (result,left,shCount);
7732 genlshFour (result,left,shCount);
7736 freeAsmop(left,NULL,ic,TRUE);
7737 freeAsmop(result,NULL,ic,TRUE);
7741 /*-----------------------------------------------------------------*
7742 * genMultiAsm - repeat assembly instruction for size of register.
7743 * if endian == 1, then the high byte (i.e base address + size of
7744 * register) is used first else the low byte is used first;
7745 *-----------------------------------------------------------------*/
7746 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7752 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7765 emitpcode(poc, popGet(AOP(reg),offset));
7772 /*-----------------------------------------------------------------*/
7773 /* genLeftShift - generates code for left shifting */
7774 /*-----------------------------------------------------------------*/
7775 static void genLeftShift (iCode *ic)
7777 operand *left,*right, *result;
7779 unsigned long lit = 0L;
7781 symbol *tlbl , *tlbl1;
7785 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7787 right = IC_RIGHT(ic);
7789 result = IC_RESULT(ic);
7791 aopOp(right,ic,FALSE);
7792 aopOp(left,ic,FALSE);
7793 aopOp(result,ic,FALSE);
7796 /* if the shift count is known then do it
7797 as efficiently as possible */
7798 if (AOP_TYPE(right) == AOP_LIT) {
7799 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7803 /* shift count is unknown then we have to form
7804 a loop get the loop count in B : Note: we take
7805 only the lower order byte since shifting
7806 more that 32 bits make no sense anyway, ( the
7807 largest size of an object can be only 32 bits ) */
7809 /* this code fails for RIGHT == RESULT */
7810 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7812 /* now move the left to the result if they are not the
7814 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7815 AOP_SIZE(result) > 1) {
7817 size = AOP_SIZE(result);
7820 l = aopGet(AOP(left),offset,FALSE,TRUE);
7821 if (*l == '@' && (IS_AOP_PREG(result))) {
7823 pic14_emitcode("mov","a,%s",l);
7824 aopPut(AOP(result),"a",offset);
7826 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7827 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7828 //aopPut(AOP(result),l,offset);
7834 if(AOP_TYPE(left) == AOP_LIT)
7835 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7837 size = AOP_SIZE(result);
7839 /* if it is only one byte then */
7841 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7842 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7843 emitpcode(POC_ANDLW, popGetLit(0xf0));
7844 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7845 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7846 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7847 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7848 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7849 emitpcode(POC_RLFW, popGet(AOP(result),0));
7850 emitpcode(POC_ANDLW, popGetLit(0xfe));
7851 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7852 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7853 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7856 tlbl = newiTempLabel(NULL);
7857 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7858 mov2w (AOP(left), 0);
7859 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7862 emitpcode(POC_COMFW, popGet(AOP(right),0));
7863 emitpcode(POC_RRF, popGet(AOP(result),0));
7864 emitpLabel(tlbl->key);
7865 emitpcode(POC_RLF, popGet(AOP(result),0));
7866 emitpcode(POC_ADDLW, popGetLit(1));
7868 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7873 if (pic14_sameRegs(AOP(left),AOP(result))) {
7875 tlbl = newiTempLabel(NULL);
7876 emitpcode(POC_COMFW, popGet(AOP(right),0));
7877 genMultiAsm(POC_RRF, result, size,1);
7878 emitpLabel(tlbl->key);
7879 genMultiAsm(POC_RLF, result, size,0);
7880 emitpcode(POC_ADDLW, popGetLit(1));
7882 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7886 //tlbl = newiTempLabel(NULL);
7888 //tlbl1 = newiTempLabel(NULL);
7890 //reAdjustPreg(AOP(result));
7892 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7893 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7894 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7896 //pic14_emitcode("add","a,acc");
7897 //aopPut(AOP(result),"a",offset++);
7899 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7901 // pic14_emitcode("rlc","a");
7902 // aopPut(AOP(result),"a",offset++);
7904 //reAdjustPreg(AOP(result));
7906 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7907 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7910 tlbl = newiTempLabel(NULL);
7911 tlbl1= newiTempLabel(NULL);
7913 size = AOP_SIZE(result);
7916 pctemp = popGetTempReg(); /* grab a temporary working register. */
7918 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7920 /* offset should be 0, 1 or 3 */
7921 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7923 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7925 emitpcode(POC_MOVWF, pctemp);
7928 emitpLabel(tlbl->key);
7931 emitpcode(POC_RLF, popGet(AOP(result),0));
7933 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7935 emitpcode(POC_DECFSZ, pctemp);
7936 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7937 emitpLabel(tlbl1->key);
7939 popReleaseTempReg(pctemp);
7943 freeAsmop (right,NULL,ic,TRUE);
7944 freeAsmop(left,NULL,ic,TRUE);
7945 freeAsmop(result,NULL,ic,TRUE);
7950 /*-----------------------------------------------------------------*/
7951 /* genrshOne - right shift a one byte quantity by known count */
7952 /*-----------------------------------------------------------------*/
7953 static void genrshOne (operand *result, operand *left,
7954 int shCount, int sign)
7957 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7958 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7961 /*-----------------------------------------------------------------*/
7962 /* genrshTwo - right shift two bytes by known amount != 0 */
7963 /*-----------------------------------------------------------------*/
7964 static void genrshTwo (operand *result,operand *left,
7965 int shCount, int sign)
7968 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7969 /* if shCount >= 8 */
7973 shiftR1Left2Result(left, MSB16, result, LSB,
7976 movLeft2Result(left, MSB16, result, LSB);
7978 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7981 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7982 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7986 /* 1 <= shCount <= 7 */
7988 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7991 /*-----------------------------------------------------------------*/
7992 /* shiftRLong - shift right one long from left to result */
7993 /* offl = LSB or MSB16 */
7994 /*-----------------------------------------------------------------*/
7995 static void shiftRLong (operand *left, int offl,
7996 operand *result, int sign)
8001 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8003 size = AOP_SIZE(left);
8004 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
8007 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
8011 assert (offl >= 0 && offl < size);
8013 same = pic14_sameRegs (AOP(left), AOP(result));
8015 /* perform the shift */
8018 if (same && !offl) {
8019 emitpcode (POC_RRF, popGet (AOP(result), size));
8021 emitpcode (POC_RRFW, popGet (AOP(left), size));
8022 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8026 addSign (result, AOP_SIZE(left) - offl, sign);
8029 /*-----------------------------------------------------------------*/
8030 /* genrshFour - shift four byte by a known amount != 0 */
8031 /*-----------------------------------------------------------------*/
8032 static void genrshFour (operand *result, operand *left,
8033 int shCount, int sign)
8036 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8037 /* if shifting more that 3 bytes */
8038 if(shCount >= 24 ) {
8041 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8043 movLeft2Result(left, MSB32, result, LSB);
8045 addSign(result, MSB16, sign);
8047 else if(shCount >= 16){
8050 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8052 movLeft2Result(left, MSB24, result, LSB);
8053 movLeft2Result(left, MSB32, result, MSB16);
8055 addSign(result, MSB24, sign);
8057 else if(shCount >= 8){
8060 shiftRLong(left, MSB16, result, sign);
8061 else if(shCount == 0){
8062 movLeft2Result(left, MSB16, result, LSB);
8063 movLeft2Result(left, MSB24, result, MSB16);
8064 movLeft2Result(left, MSB32, result, MSB24);
8065 addSign(result, MSB32, sign);
8068 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8069 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8070 /* the last shift is signed */
8071 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8072 addSign(result, MSB32, sign);
8075 else{ /* 1 <= shCount <= 7 */
8077 shiftRLong(left, LSB, result, sign);
8079 shiftRLong(result, LSB, result, sign);
8082 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8083 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8084 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8089 /*-----------------------------------------------------------------*/
8090 /* genRightShiftLiteral - right shifting by known count */
8091 /*-----------------------------------------------------------------*/
8092 static void genRightShiftLiteral (operand *left,
8098 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8102 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8103 freeAsmop(right,NULL,ic,TRUE);
8105 aopOp(left,ic,FALSE);
8106 aopOp(result,ic,FALSE);
8109 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8113 lsize = pic14_getDataSize(left);
8114 res_size = pic14_getDataSize(result);
8115 /* test the LEFT size !!! */
8117 /* I suppose that the left size >= result size */
8120 movLeft2Result(left, res_size, result, res_size);
8123 else if(shCount >= (lsize * 8)){
8126 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8128 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8129 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8134 emitpcode(POC_MOVLW, popGetLit(0));
8135 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8136 emitpcode(POC_MOVLW, popGetLit(0xff));
8138 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8143 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8150 genrshOne (result,left,shCount,sign);
8154 genrshTwo (result,left,shCount,sign);
8158 genrshFour (result,left,shCount,sign);
8166 freeAsmop(left,NULL,ic,TRUE);
8167 freeAsmop(result,NULL,ic,TRUE);
8172 /*-----------------------------------------------------------------*/
8173 /* genSignedRightShift - right shift of signed number */
8174 /*-----------------------------------------------------------------*/
8175 static void genSignedRightShift (iCode *ic)
8177 operand *right, *left, *result;
8180 symbol *tlbl, *tlbl1 ;
8183 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8185 /* we do it the hard way put the shift count in b
8186 and loop thru preserving the sign */
8188 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8190 right = IC_RIGHT(ic);
8192 result = IC_RESULT(ic);
8194 aopOp(right,ic,FALSE);
8195 aopOp(left,ic,FALSE);
8196 aopOp(result,ic,FALSE);
8199 if ( AOP_TYPE(right) == AOP_LIT) {
8200 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8201 //genRightShiftLiteral (left,right,result,ic,1);
8204 /* shift count is unknown then we have to form
8205 a loop get the loop count in B : Note: we take
8206 only the lower order byte since shifting
8207 more that 32 bits make no sense anyway, ( the
8208 largest size of an object can be only 32 bits ) */
8210 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8211 //pic14_emitcode("inc","b");
8212 //freeAsmop (right,NULL,ic,TRUE);
8213 //aopOp(left,ic,FALSE);
8214 //aopOp(result,ic,FALSE);
8216 /* now move the left to the result if they are not the
8218 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8219 AOP_SIZE(result) > 1) {
8221 size = AOP_SIZE(result);
8225 l = aopGet(AOP(left),offset,FALSE,TRUE);
8226 if (*l == '@' && IS_AOP_PREG(result)) {
8227 pic14_emitcode("mov","a,%s",l);
8228 aopPut(AOP(result),"a",offset);
8230 aopPut(AOP(result),l,offset);
8232 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8233 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8239 /* mov the highest order bit to OVR */
8240 tlbl = newiTempLabel(NULL);
8241 tlbl1= newiTempLabel(NULL);
8243 size = AOP_SIZE(result);
8246 pctemp = popGetTempReg(); /* grab a temporary working register. */
8248 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8250 /* offset should be 0, 1 or 3 */
8251 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8253 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8255 emitpcode(POC_MOVWF, pctemp);
8258 emitpLabel(tlbl->key);
8260 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8261 emitpcode(POC_RRF, popGet(AOP(result),offset));
8264 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8267 emitpcode(POC_DECFSZ, pctemp);
8268 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8269 emitpLabel(tlbl1->key);
8271 popReleaseTempReg(pctemp);
8273 size = AOP_SIZE(result);
8275 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8276 pic14_emitcode("rlc","a");
8277 pic14_emitcode("mov","ov,c");
8278 /* if it is only one byte then */
8280 l = aopGet(AOP(left),0,FALSE,FALSE);
8282 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8283 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8284 pic14_emitcode("mov","c,ov");
8285 pic14_emitcode("rrc","a");
8286 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8287 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8288 aopPut(AOP(result),"a",0);
8292 reAdjustPreg(AOP(result));
8293 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8294 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8295 pic14_emitcode("mov","c,ov");
8297 l = aopGet(AOP(result),offset,FALSE,FALSE);
8299 pic14_emitcode("rrc","a");
8300 aopPut(AOP(result),"a",offset--);
8302 reAdjustPreg(AOP(result));
8303 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8304 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8309 freeAsmop(left,NULL,ic,TRUE);
8310 freeAsmop(result,NULL,ic,TRUE);
8311 freeAsmop(right,NULL,ic,TRUE);
8315 /*-----------------------------------------------------------------*/
8316 /* loadSignToC - load the operand's sign bit into CARRY */
8317 /*-----------------------------------------------------------------*/
8319 static void loadSignToC (operand *op)
8322 assert (op && AOP(op) && AOP_SIZE(op));
8325 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8329 /*-----------------------------------------------------------------*/
8330 /* genRightShift - generate code for right shifting */
8331 /*-----------------------------------------------------------------*/
8332 static void genGenericShift (iCode *ic, int shiftRight)
8334 operand *right, *left, *result;
8337 symbol *tlbl, *tlbl1, *inverselbl;
8340 /* if signed then we do it the hard way preserve the
8341 sign bit moving it inwards */
8342 retype = getSpec(operandType(IC_RESULT(ic)));
8343 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8345 /* signed & unsigned types are treated the same : i.e. the
8346 signed is NOT propagated inwards : quoting from the
8347 ANSI - standard : "for E1 >> E2, is equivalent to division
8348 by 2**E2 if unsigned or if it has a non-negative value,
8349 otherwise the result is implementation defined ", MY definition
8350 is that the sign does not get propagated */
8352 right = IC_RIGHT(ic);
8354 result = IC_RESULT(ic);
8356 aopOp(right,ic,FALSE);
8357 aopOp(left,ic,FALSE);
8358 aopOp(result,ic,FALSE);
8360 /* if the shift count is known then do it
8361 as efficiently as possible */
8362 if (AOP_TYPE(right) == AOP_LIT) {
8363 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8367 shiftRight = !shiftRight;
8371 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8373 shiftLeft_Left2ResultLit (left, result, lit);
8374 //genRightShiftLiteral (left,right,result,ic, 0);
8378 /* shift count is unknown then we have to form
8379 a loop get the loop count in B : Note: we take
8380 only the lower order byte since shifting
8381 more that 32 bits make no sense anyway, ( the
8382 largest size of an object can be only 32 bits ) */
8384 /* we must not overwrite the shift counter */
8385 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8387 /* now move the left to the result if they are not the
8389 if (!pic14_sameRegs(AOP(left),AOP(result)))
8391 size = min(AOP_SIZE(result), AOP_SIZE(left));
8393 mov2w(AOP(left), size);
8394 movwf(AOP(result), size);
8396 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8399 tlbl = newiTempLabel(NULL);
8400 tlbl1= newiTempLabel(NULL);
8402 size = AOP_SIZE(result);
8404 mov2w(AOP(right),0);
8405 if (!SPEC_USIGN(operandType(right)))
8407 inverselbl = newiTempLabel(NULL);
8408 /* signed shift count -- invert shift direction for c<0 */
8409 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8410 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8412 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8413 /* check for `a = b >> c' with `-c == 0' */
8415 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8416 emitpLabel(tlbl->key);
8417 /* propagate the sign bit inwards for SIGNED result */
8418 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8419 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8420 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8422 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8424 if (!SPEC_USIGN(operandType(right)))
8426 symbol *inv_loop = newiTempLabel(NULL);
8428 shiftRight = !shiftRight; /* invert shift direction */
8430 /* we came here from the code above -- we are done */
8431 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8433 /* emit code for shifting N<0 steps, count is already in W */
8434 emitpLabel(inverselbl->key);
8435 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8436 emitpLabel(inv_loop->key);
8437 /* propagate the sign bit inwards for SIGNED result */
8438 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8439 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8440 emitpcode(POC_ADDLW, popGetLit(1));
8442 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8445 emitpLabel(tlbl1->key);
8447 freeAsmop(left,NULL,ic,TRUE);
8448 freeAsmop (right,NULL,ic,TRUE);
8449 freeAsmop(result,NULL,ic,TRUE);
8452 static void genRightShift (iCode *ic)
8454 genGenericShift(ic, 1);
8457 static void genLeftShift (iCode *ic)
8459 genGenericShift(ic, 0);
8462 /*-----------------------------------------------------------------*/
8463 /* SetIrp - Set IRP bit */
8464 /*-----------------------------------------------------------------*/
8465 void SetIrp(operand *result) {
8467 if (AOP_TYPE(result) == AOP_LIT) {
8468 unsigned lit = (unsigned)operandLitValue(result);
8474 if (PCOP(AOP(result))->type == PO_LITERAL) {
8475 int addrs = PCOL(AOP(result))->lit;
8481 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8482 if(AOP_SIZE(result) > 1) {
8483 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8491 setup_fsr (operand *ptr)
8494 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8496 /* also setup-up IRP */
8500 /*-----------------------------------------------------------------*/
8501 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8502 /* arbitrary pointer (__code, __data, generic) */
8503 /*-----------------------------------------------------------------*/
8505 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8512 if (!alreadyAddressed) setup_fsr (src);
8513 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8517 assert( AOP_SIZE(src) == 2 );
8519 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8521 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8522 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8523 call_libraryfunc ("__gptrget1");
8527 assert( AOP_SIZE(src) == 3 );
8529 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8531 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8533 call_libraryfunc ("__gptrget1");
8537 assert( !"unhandled pointer type" );
8542 /*-----------------------------------------------------------------*/
8543 /* emitPtrByteSet - emits code to set a byte from src through a */
8544 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8545 /*-----------------------------------------------------------------*/
8547 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8554 if (!alreadyAddressed) setup_fsr (dst);
8555 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8559 assert( !"trying to assign to __code pointer" );
8563 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8565 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8567 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8569 call_libraryfunc ("__gptrput1");
8573 assert( !"unhandled pointer type" );
8578 /*-----------------------------------------------------------------*/
8579 /* genUnpackBits - generates code for unpacking bits */
8580 /*-----------------------------------------------------------------*/
8581 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8583 int rsize; /* result size */
8584 sym_link *etype; /* bitfield type information */
8585 int blen; /* bitfield length */
8586 int bstr; /* bitfield starting bit within byte */
8589 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8590 etype = getSpec(operandType(result));
8591 rsize = getSize (operandType (result));
8592 blen = SPEC_BLEN (etype);
8593 bstr = SPEC_BSTR (etype);
8595 /* single bit field case */
8597 if (ifx) { /* that is for an if statement */
8600 resolveIfx(&rIfx,ifx);
8601 if (ptype == -1) /* direct */
8602 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8604 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8605 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8606 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8610 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8611 for (i=0; i < AOP_SIZE(result); i++)
8612 emitpcode (POC_CLRF, popGet (AOP(result), i));
8617 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8618 /* adjust result below */
8625 emitPtrByteGet (left, ptype, FALSE);
8626 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8628 /* adjust result below */
8632 assert( !"unhandled pointer type" );
8635 /* move sign-/zero extended bit to result */
8636 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8637 emitpcode (POC_INCF, popGet (AOP(result), 0));
8639 emitpcode (POC_DECF, popGet (AOP(result), 0));
8641 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8645 else if (blen <= 8 && ((blen + bstr) <= 8))
8650 for (i=0; i < AOP_SIZE(result); i++)
8651 emitpcode (POC_CLRF, popGet (AOP(result), i));
8656 mov2w(AOP(left), 0);
8663 emitPtrByteGet (left, ptype, FALSE);
8667 assert( !"unhandled pointer type" );
8671 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8672 movwf(AOP(result), 0);
8673 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8675 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8677 /* signed bitfield */
8678 assert (bstr + blen > 0);
8679 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8680 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8681 emitpcode(POC_IORWF, popGet(AOP(result),0));
8683 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8687 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8691 /*-----------------------------------------------------------------*/
8692 /* genDataPointerGet - generates code when ptr offset is known */
8693 /*-----------------------------------------------------------------*/
8694 static void genDataPointerGet (operand *left,
8698 int size , offset = 0;
8701 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8704 /* optimization - most of the time, left and result are the same
8705 * address, but different types. for the pic code, we could omit
8708 aopOp(result,ic,TRUE);
8710 if (pic14_sameRegs (AOP(left), AOP(result)))
8713 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8715 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8717 size = AOP_SIZE(result);
8718 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8722 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8723 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8727 freeAsmop(left,NULL,ic,TRUE);
8728 freeAsmop(result,NULL,ic,TRUE);
8732 /*-----------------------------------------------------------------*/
8733 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8734 /*-----------------------------------------------------------------*/
8735 static void genNearPointerGet (operand *left,
8740 sym_link *ltype = operandType(left);
8741 sym_link *rtype = operandType(result);
8742 sym_link *retype= getSpec(rtype); /* bitfield type information */
8746 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8749 aopOp(left,ic,FALSE);
8751 /* if left is rematerialisable and
8752 result is not bit variable type and
8753 the left is pointer to data space i.e
8754 lower 128 bytes of space */
8755 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8756 !IS_BITVAR(retype) &&
8757 PIC_IS_DATA_PTR(ltype)) {
8758 genDataPointerGet (left,result,ic);
8762 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8763 aopOp (result,ic,FALSE);
8765 /* Check if can access directly instead of via a pointer */
8766 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8767 && AOP_SIZE(result) == 1)
8772 if (IS_BITFIELD(getSpec(operandType(result))))
8774 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8778 /* If the pointer value is not in a the FSR then need to put it in */
8779 /* Must set/reset IRP bit for use with FSR. */
8784 /* if bitfield then unpack the bits */
8786 /* we have can just get the values */
8787 int size = AOP_SIZE(result);
8790 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8794 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8796 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8797 if (AOP_TYPE(result) == AOP_LIT) {
8798 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8800 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8802 if (size && !direct)
8803 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8808 /* now some housekeeping stuff */
8810 /* we had to allocate for this iCode */
8811 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8812 freeAsmop(NULL,aop,ic,TRUE);
8814 /* we did not allocate which means left
8815 already in a pointer register, then
8816 if size > 0 && this could be used again
8817 we have to point it back to where it
8819 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8820 if (AOP_SIZE(result) > 1 &&
8821 !OP_SYMBOL(left)->remat &&
8822 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8824 int size = AOP_SIZE(result) - 1;
8826 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8832 freeAsmop(left,NULL,ic,TRUE);
8833 freeAsmop(result,NULL,ic,TRUE);
8838 /*-----------------------------------------------------------------*/
8839 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8840 /*-----------------------------------------------------------------*/
8841 static void genPagedPointerGet (operand *left,
8848 sym_link *rtype, *retype;
8851 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8853 rtype = operandType(result);
8854 retype= getSpec(rtype);
8856 aopOp(left,ic,FALSE);
8858 /* if the value is already in a pointer register
8859 then don't need anything more */
8860 if (!AOP_INPREG(AOP(left))) {
8861 /* otherwise get a free pointer register */
8863 preg = getFreePtr(ic,&aop,FALSE);
8864 pic14_emitcode("mov","%s,%s",
8866 aopGet(AOP(left),0,FALSE,TRUE));
8867 rname = preg->name ;
8869 rname = aopGet(AOP(left),0,FALSE,FALSE);
8871 freeAsmop(left,NULL,ic,TRUE);
8872 aopOp (result,ic,FALSE);
8874 /* if bitfield then unpack the bits */
8875 if (IS_BITFIELD(retype))
8876 genUnpackBits (result,left,rname,PPOINTER,0);
8878 /* we have can just get the values */
8879 int size = AOP_SIZE(result);
8884 pic14_emitcode("movx","a,@%s",rname);
8885 aopPut(AOP(result),"a",offset);
8890 pic14_emitcode("inc","%s",rname);
8894 /* now some housekeeping stuff */
8896 /* we had to allocate for this iCode */
8897 freeAsmop(NULL,aop,ic,TRUE);
8899 /* we did not allocate which means left
8900 already in a pointer register, then
8901 if size > 0 && this could be used again
8902 we have to point it back to where it
8904 if (AOP_SIZE(result) > 1 &&
8905 !OP_SYMBOL(left)->remat &&
8906 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8908 int size = AOP_SIZE(result) - 1;
8910 pic14_emitcode("dec","%s",rname);
8915 freeAsmop(result,NULL,ic,TRUE);
8920 /*-----------------------------------------------------------------*/
8921 /* genFarPointerGet - gget value from far space */
8922 /*-----------------------------------------------------------------*/
8923 static void genFarPointerGet (operand *left,
8924 operand *result, iCode *ic)
8927 sym_link *retype = getSpec(operandType(result));
8930 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8932 aopOp(left,ic,FALSE);
8934 /* if the operand is already in dptr
8935 then we do nothing else we move the value to dptr */
8936 if (AOP_TYPE(left) != AOP_STR) {
8937 /* if this is remateriazable */
8938 if (AOP_TYPE(left) == AOP_IMMD)
8939 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8940 else { /* we need to get it byte by byte */
8941 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8942 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8943 if (options.model == MODEL_FLAT24)
8945 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8949 /* so dptr know contains the address */
8950 freeAsmop(left,NULL,ic,TRUE);
8951 aopOp(result,ic,FALSE);
8953 /* if bit then unpack */
8954 if (IS_BITFIELD(retype))
8955 genUnpackBits(result,left,"dptr",FPOINTER,0);
8957 size = AOP_SIZE(result);
8961 pic14_emitcode("movx","a,@dptr");
8962 aopPut(AOP(result),"a",offset++);
8964 pic14_emitcode("inc","dptr");
8968 freeAsmop(result,NULL,ic,TRUE);
8973 /*-----------------------------------------------------------------*/
8974 /* genCodePointerGet - get value from code space */
8975 /*-----------------------------------------------------------------*/
8976 static void genCodePointerGet (operand *left,
8977 operand *result, iCode *ic)
8980 sym_link *retype = getSpec(operandType(result));
8982 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8984 aopOp(left,ic,FALSE);
8986 /* if the operand is already in dptr
8987 then we do nothing else we move the value to dptr */
8988 if (AOP_TYPE(left) != AOP_STR) {
8989 /* if this is remateriazable */
8990 if (AOP_TYPE(left) == AOP_IMMD)
8991 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8992 else { /* we need to get it byte by byte */
8993 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8994 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8995 if (options.model == MODEL_FLAT24)
8997 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
9001 /* so dptr know contains the address */
9002 freeAsmop(left,NULL,ic,TRUE);
9003 aopOp(result,ic,FALSE);
9005 /* if bit then unpack */
9006 if (IS_BITFIELD(retype))
9007 genUnpackBits(result,left,"dptr",CPOINTER,0);
9009 size = AOP_SIZE(result);
9013 pic14_emitcode("clr","a");
9014 pic14_emitcode("movc","a,@a+dptr");
9015 aopPut(AOP(result),"a",offset++);
9017 pic14_emitcode("inc","dptr");
9021 freeAsmop(result,NULL,ic,TRUE);
9024 /*-----------------------------------------------------------------*/
9025 /* genGenPointerGet - gget value from generic pointer space */
9026 /*-----------------------------------------------------------------*/
9027 static void genGenPointerGet (operand *left,
9028 operand *result, iCode *ic)
9031 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9032 aopOp(left,ic,FALSE);
9033 aopOp(result,ic,FALSE);
9036 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9038 if (IS_BITFIELD(getSpec(operandType(result))))
9040 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9045 /* emit call to __gptrget */
9046 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9047 int size = AOP_SIZE(result);
9050 assert (size > 0 && size <= 4);
9052 /* pass arguments */
9053 assert (AOP_SIZE(left) == 3);
9054 mov2w(AOP(left), 0);
9055 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9056 mov2w(AOP(left), 1);
9057 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9058 mov2w(AOP(left), 2);
9059 call_libraryfunc (func[size]);
9062 movwf (AOP(result), --size);
9064 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9065 movwf (AOP(result), size);
9069 freeAsmop(left,NULL,ic,TRUE);
9070 freeAsmop(result,NULL,ic,TRUE);
9074 /*-----------------------------------------------------------------*/
9075 /* genConstPointerGet - get value from const generic pointer space */
9076 /*-----------------------------------------------------------------*/
9077 static void genConstPointerGet (operand *left,
9078 operand *result, iCode *ic)
9080 //sym_link *retype = getSpec(operandType(result));
9082 symbol *albl, *blbl;//, *clbl;
9089 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9090 aopOp(left,ic,FALSE);
9091 aopOp(result,ic,FALSE);
9093 size = AOP_SIZE(result);
9095 DEBUGpic14_AopType(__LINE__,left,NULL,result);
9097 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9099 lit = op_isLitLike (left);
9100 poc = lit ? POC_MOVLW : POC_MOVFW;
9102 if (IS_BITFIELD(getSpec(operandType(result))))
9104 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9109 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9110 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9111 assert (size > 0 && size <= 4);
9114 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9116 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9117 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9118 call_libraryfunc (func[size]);
9120 movwf(AOP(result),size-1);
9121 for (i = 1; i < size; i++)
9123 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9124 movwf(AOP(result),size - 1 - i);
9129 freeAsmop(left,NULL,ic,TRUE);
9130 freeAsmop(result,NULL,ic,TRUE);
9133 /*-----------------------------------------------------------------*/
9134 /* genPointerGet - generate code for pointer get */
9135 /*-----------------------------------------------------------------*/
9136 static void genPointerGet (iCode *ic)
9138 operand *left, *result ;
9139 sym_link *type, *etype;
9143 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9146 result = IC_RESULT(ic) ;
9148 /* depending on the type of pointer we need to
9149 move it to the correct pointer register */
9150 type = operandType(left);
9151 etype = getSpec(type);
9153 if (IS_PTR_CONST(type))
9154 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9156 /* if left is of type of pointer then it is simple */
9157 if (IS_PTR(type) && !IS_FUNC(type->next))
9158 p_type = DCL_TYPE(type);
9160 /* we have to go by the storage class */
9161 p_type = PTR_TYPE(SPEC_OCLS(etype));
9163 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9165 if (SPEC_OCLS(etype)->codesp ) {
9166 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9167 //p_type = CPOINTER ;
9170 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9171 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9172 /*p_type = FPOINTER ;*/
9174 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9175 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9176 /* p_type = PPOINTER; */
9178 if (SPEC_OCLS(etype) == idata )
9179 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9180 /* p_type = IPOINTER; */
9182 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9183 /* p_type = POINTER ; */
9186 /* now that we have the pointer type we assign
9187 the pointer values */
9193 genNearPointerGet (left,result,ic);
9197 genPagedPointerGet(left,result,ic);
9201 genFarPointerGet (left,result,ic);
9205 genConstPointerGet (left,result,ic);
9209 genGenPointerGet (left,result,ic);
9212 assert ( !"unhandled pointer type" );
9218 /*-----------------------------------------------------------------*/
9219 /* genPackBits - generates code for packed bit storage */
9220 /*-----------------------------------------------------------------*/
9221 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9223 int blen; /* bitfield length */
9224 int bstr; /* bitfield starting bit within byte */
9225 int litval; /* source literal value (if AOP_LIT) */
9226 unsigned char mask; /* bitmask within current byte */
9229 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9231 blen = SPEC_BLEN (etype);
9232 bstr = SPEC_BSTR (etype);
9234 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9235 if ((blen <= 8) && ((bstr + blen) <= 8))
9237 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9238 (unsigned char) (0xFF >> (8 - bstr)));
9240 if (AOP_TYPE (right) == AOP_LIT)
9242 /* Case with a bitfield length <8 and literal source */
9243 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9250 if (AOP(result)->type == AOP_PCODE)
9251 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9253 pcop = popGet(AOP(result),0);
9254 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9260 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9264 assert( !"trying to assign to bitfield via pointer to __code space" );
9268 emitPtrByteGet(result, p_type, FALSE);
9270 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9272 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9274 emitPtrByteSet(result, p_type, TRUE);
9278 assert( !"unhandled pointer type" );
9280 } // switch (p_type)
9283 litval = lit << bstr;
9284 litval &= (~mask) & 0x00ff;
9289 mov2w (AOP(result), 0);
9290 if ((litval|mask) != 0x00ff)
9291 emitpcode(POC_ANDLW, popGetLit (mask));
9293 emitpcode(POC_IORLW, popGetLit (litval));
9294 movwf (AOP(result), 0);
9300 emitPtrByteGet(result, p_type, FALSE);
9301 if ((litval|mask) != 0x00ff)
9302 emitpcode(POC_ANDLW, popGetLit (mask));
9304 emitpcode(POC_IORLW, popGetLit (litval));
9305 emitPtrByteSet(result, p_type, TRUE);
9309 assert( !"trying to assign to bitfield via pointer to __code space" );
9313 assert( !"unhandled pointer type" );
9320 /* right is no literal */
9325 /* Note more efficient code, of pre clearing bit then only setting it if required,
9326 * can only be done if it is known that the result is not a SFR */
9327 emitpcode(POC_RRFW,popGet(AOP(right),0));
9329 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9331 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9337 emitPtrByteGet (result, p_type, FALSE);
9338 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9339 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9340 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9341 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9342 emitPtrByteSet (result, p_type, TRUE);
9346 assert( !"trying to assign to bitfield via pointer to __code space" );
9350 assert( !"unhandled pointer type" );
9355 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9356 pCodeOp *temp = popGetTempReg ();
9358 mov2w (AOP(right), 0);
9360 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9362 emitpcode(POC_MOVWF, temp);
9364 AccLsh (temp, bstr);
9370 mov2w (AOP(result), 0);
9371 emitpcode(POC_ANDLW, popGetLit (mask));
9372 emitpcode(POC_IORFW, temp);
9373 movwf (AOP(result), 0);
9379 emitPtrByteGet (result, p_type, FALSE);
9380 emitpcode(POC_ANDLW, popGetLit (mask));
9381 emitpcode(POC_IORFW, temp);
9382 emitPtrByteSet (result, p_type, TRUE);
9386 assert( !"trying to assign to bitfield via pointer to __code space" );
9390 assert( !"unhandled pointer type" );
9394 popReleaseTempReg (temp);
9396 } // if (AOP(right)->type != AOP_LIT)
9398 } // if (blen <= 8 && ((blen + bstr) <= 8))
9400 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9403 /*-----------------------------------------------------------------*/
9404 /* genDataPointerSet - remat pointer to data space */
9405 /*-----------------------------------------------------------------*/
9406 static void genDataPointerSet(operand *right,
9410 int size, offset = 0 ;
9414 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9415 aopOp(right,ic,FALSE);
9416 aopOp(result,ic,FALSE);
9418 assert (IS_SYMOP(result));
9419 assert (IS_PTR(OP_SYM_TYPE(result)));
9421 if (AOP_TYPE(right) == AOP_LIT)
9424 size = AOP_SIZE(right);
9425 ressize = getSize(OP_SYM_ETYPE(result));
9426 if (size > ressize) size = ressize;
9427 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9429 //assert( !"what's going on here?" );
9432 if ( AOP_TYPE(result) == AOP_PCODE) {
9433 fprintf(stderr,"genDataPointerSet %s, %d\n",
9434 AOP(result)->aopu.pcop->name,
9435 PCOI(AOP(result)->aopu.pcop)->offset);
9439 // tsd, was l+1 - the underline `_' prefix was being stripped
9441 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9443 if (AOP_TYPE(right) == AOP_LIT) {
9444 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9445 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9447 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9448 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9450 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9453 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9454 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9455 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9461 freeAsmop(right,NULL,ic,TRUE);
9462 freeAsmop(result,NULL,ic,TRUE);
9465 /*-----------------------------------------------------------------*/
9466 /* genNearPointerSet - pic14_emitcode for near pointer put */
9467 /*-----------------------------------------------------------------*/
9468 static void genNearPointerSet (operand *right,
9473 sym_link *ptype = operandType(result);
9474 sym_link *retype = getSpec(operandType(right));
9475 sym_link *letype = getSpec(ptype);
9480 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9481 aopOp(result,ic,FALSE);
9484 /* if the result is rematerializable &
9485 in data space & not a bit variable */
9486 //if (AOP_TYPE(result) == AOP_IMMD &&
9487 if (AOP_TYPE(result) == AOP_PCODE &&
9488 PIC_IS_DATA_PTR(ptype) &&
9489 !IS_BITVAR (retype) &&
9490 !IS_BITVAR (letype)) {
9491 genDataPointerSet (right,result,ic);
9492 freeAsmop(result,NULL,ic,TRUE);
9497 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 aopOp(right,ic,FALSE);
9499 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9501 /* Check if can access directly instead of via a pointer */
9502 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9506 if (IS_BITFIELD (letype))
9508 genPackBits (letype, result, right, direct?-1:POINTER);
9512 /* If the pointer value is not in a the FSR then need to put it in */
9513 /* Must set/reset IRP bit for use with FSR. */
9514 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9519 /* we have can just get the values */
9520 int size = AOP_SIZE(right);
9523 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9525 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9527 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9529 if (AOP_TYPE(right) == AOP_LIT) {
9530 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9532 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9535 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9537 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9539 if (size && !direct)
9540 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9545 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9546 /* now some housekeeping stuff */
9548 /* we had to allocate for this iCode */
9549 freeAsmop(NULL,aop,ic,TRUE);
9551 /* we did not allocate which means left
9552 already in a pointer register, then
9553 if size > 0 && this could be used again
9554 we have to point it back to where it
9556 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9557 if (AOP_SIZE(right) > 1 &&
9558 !OP_SYMBOL(result)->remat &&
9559 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9561 int size = AOP_SIZE(right) - 1;
9563 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9567 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9570 freeAsmop(right,NULL,ic,TRUE);
9571 freeAsmop(result,NULL,ic,TRUE);
9575 /*-----------------------------------------------------------------*/
9576 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9577 /*-----------------------------------------------------------------*/
9578 static void genPagedPointerSet (operand *right,
9588 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9590 retype= getSpec(operandType(right));
9592 aopOp(result,ic,FALSE);
9594 /* if the value is already in a pointer register
9595 then don't need anything more */
9596 if (!AOP_INPREG(AOP(result))) {
9597 /* otherwise get a free pointer register */
9599 preg = getFreePtr(ic,&aop,FALSE);
9600 pic14_emitcode("mov","%s,%s",
9602 aopGet(AOP(result),0,FALSE,TRUE));
9603 rname = preg->name ;
9605 rname = aopGet(AOP(result),0,FALSE,FALSE);
9607 freeAsmop(result,NULL,ic,TRUE);
9608 aopOp (right,ic,FALSE);
9610 /* if bitfield then unpack the bits */
9611 if (IS_BITFIELD(retype))
9612 genPackBits (retype,result,right,rname,PPOINTER);
9614 /* we have can just get the values */
9615 int size = AOP_SIZE(right);
9619 l = aopGet(AOP(right),offset,FALSE,TRUE);
9622 pic14_emitcode("movx","@%s,a",rname);
9625 pic14_emitcode("inc","%s",rname);
9631 /* now some housekeeping stuff */
9633 /* we had to allocate for this iCode */
9634 freeAsmop(NULL,aop,ic,TRUE);
9636 /* we did not allocate which means left
9637 already in a pointer register, then
9638 if size > 0 && this could be used again
9639 we have to point it back to where it
9641 if (AOP_SIZE(right) > 1 &&
9642 !OP_SYMBOL(result)->remat &&
9643 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9645 int size = AOP_SIZE(right) - 1;
9647 pic14_emitcode("dec","%s",rname);
9652 freeAsmop(right,NULL,ic,TRUE);
9657 /*-----------------------------------------------------------------*/
9658 /* genFarPointerSet - set value from far space */
9659 /*-----------------------------------------------------------------*/
9660 static void genFarPointerSet (operand *right,
9661 operand *result, iCode *ic)
9664 sym_link *retype = getSpec(operandType(right));
9667 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9668 aopOp(result,ic,FALSE);
9670 /* if the operand is already in dptr
9671 then we do nothing else we move the value to dptr */
9672 if (AOP_TYPE(result) != AOP_STR) {
9673 /* if this is remateriazable */
9674 if (AOP_TYPE(result) == AOP_IMMD)
9675 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9676 else { /* we need to get it byte by byte */
9677 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9678 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9679 if (options.model == MODEL_FLAT24)
9681 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9685 /* so dptr know contains the address */
9686 freeAsmop(result,NULL,ic,TRUE);
9687 aopOp(right,ic,FALSE);
9689 /* if bit then unpack */
9690 if (IS_BITFIELD(retype))
9691 genPackBits(retype,result,right,"dptr",FPOINTER);
9693 size = AOP_SIZE(right);
9697 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9699 pic14_emitcode("movx","@dptr,a");
9701 pic14_emitcode("inc","dptr");
9705 freeAsmop(right,NULL,ic,TRUE);
9709 /*-----------------------------------------------------------------*/
9710 /* genGenPointerSet - set value from generic pointer space */
9711 /*-----------------------------------------------------------------*/
9712 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9714 sym_link *retype = getSpec(operandType(result));
9717 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9718 aopOp(right,ic,FALSE);
9719 aopOp(result,ic,FALSE);
9722 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9724 if (IS_BITFIELD(retype))
9726 genPackBits (retype, result, right, GPOINTER);
9731 /* emit call to __gptrput */
9732 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9733 int size = AOP_SIZE(right);
9736 assert (size == getSize(OP_SYM_ETYPE(result)));
9737 assert (size > 0 && size <= 4);
9739 /* pass arguments */
9740 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9746 mov2w_op (right, off);
9747 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9752 assert (AOP_SIZE(result) == 3);
9753 mov2w(AOP(result), 0);
9754 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9755 mov2w(AOP(result), 1);
9756 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9757 mov2w(AOP(result), 2);
9758 call_libraryfunc (func[size]);
9761 freeAsmop(right,NULL,ic,TRUE);
9762 freeAsmop(result,NULL,ic,TRUE);
9765 /*-----------------------------------------------------------------*/
9766 /* genPointerSet - stores the value into a pointer location */
9767 /*-----------------------------------------------------------------*/
9768 static void genPointerSet (iCode *ic)
9770 operand *right, *result ;
9771 sym_link *type, *etype;
9775 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9777 right = IC_RIGHT(ic);
9778 result = IC_RESULT(ic) ;
9780 /* depending on the type of pointer we need to
9781 move it to the correct pointer register */
9782 type = operandType(result);
9783 etype = getSpec(type);
9784 /* if left is of type of pointer then it is simple */
9785 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9786 p_type = DCL_TYPE(type);
9789 /* we have to go by the storage class */
9790 p_type = PTR_TYPE(SPEC_OCLS(etype));
9792 /* if (SPEC_OCLS(etype)->codesp ) { */
9793 /* p_type = CPOINTER ; */
9796 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9797 /* p_type = FPOINTER ; */
9799 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9800 /* p_type = PPOINTER ; */
9802 /* if (SPEC_OCLS(etype) == idata ) */
9803 /* p_type = IPOINTER ; */
9805 /* p_type = POINTER ; */
9808 /* now that we have the pointer type we assign
9809 the pointer values */
9815 genNearPointerSet (right,result,ic);
9819 genPagedPointerSet (right,result,ic);
9823 genFarPointerSet (right,result,ic);
9827 genGenPointerSet (right,result,ic);
9831 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9832 "genPointerSet: illegal pointer type");
9836 /*-----------------------------------------------------------------*/
9837 /* genIfx - generate code for Ifx statement */
9838 /*-----------------------------------------------------------------*/
9839 static void genIfx (iCode *ic, iCode *popIc)
9841 operand *cond = IC_COND(ic);
9845 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9847 aopOp(cond,ic,FALSE);
9849 /* get the value into acc */
9850 if (AOP_TYPE(cond) != AOP_CRY)
9851 pic14_toBoolean(cond);
9855 /* if there was something to be popped then do it */
9861 /* This assumes that CARRY is set iff cond is true */
9864 assert (!IC_FALSE(ic));
9865 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9867 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9869 assert (IC_FALSE(ic));
9870 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9872 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9876 static int hasWarned = 0;
9879 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9886 /* now Z is set iff !cond */
9889 assert (!IC_FALSE(ic));
9891 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9894 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9900 /* the result is now in the accumulator */
9901 freeAsmop(cond,NULL,ic,TRUE);
9904 /*-----------------------------------------------------------------*/
9905 /* genAddrOf - generates code for address of */
9906 /*-----------------------------------------------------------------*/
9907 static void genAddrOf (iCode *ic)
9909 operand *right, *result, *left;
9913 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9916 //aopOp(IC_RESULT(ic),ic,FALSE);
9918 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9919 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9920 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9922 DEBUGpic14_AopType(__LINE__,left,right,result);
9923 assert (IS_SYMOP (left));
9925 /* sanity check: generic pointers to code space are not yet supported,
9926 * pionters to codespace must not be assigned addresses of __data values. */
9928 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9929 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)));
9930 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)));
9931 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)));
9932 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)));
9935 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9936 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9937 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9938 OP_SYMBOL(left)->name);
9939 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9940 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9941 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9942 OP_SYMBOL(left)->name);
9945 size = AOP_SIZE(IC_RESULT(ic));
9946 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9948 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9953 /* fixing bug #863624, reported from (errolv) */
9954 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9955 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9958 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9959 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9964 if (IS_GENPTR(OP_SYM_TYPE(result)))
9966 /* provide correct tag */
9967 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9968 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9969 movwf (AOP(result), 2);
9972 freeAsmop(left,NULL,ic,FALSE);
9973 freeAsmop(result,NULL,ic,TRUE);
9978 /*-----------------------------------------------------------------*/
9979 /* genFarFarAssign - assignment when both are in far space */
9980 /*-----------------------------------------------------------------*/
9981 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9983 int size = AOP_SIZE(right);
9986 /* first push the right side on to the stack */
9988 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9990 pic14_emitcode ("push","acc");
9993 freeAsmop(right,NULL,ic,FALSE);
9994 /* now assign DPTR to result */
9995 aopOp(result,ic,FALSE);
9996 size = AOP_SIZE(result);
9998 pic14_emitcode ("pop","acc");
9999 aopPut(AOP(result),"a",--offset);
10001 freeAsmop(result,NULL,ic,FALSE);
10006 /*-----------------------------------------------------------------*/
10007 /* genAssign - generate code for assignment */
10008 /*-----------------------------------------------------------------*/
10009 static void genAssign (iCode *ic)
10011 operand *result, *right;
10012 int size, offset,know_W;
10013 unsigned long lit = 0L;
10015 result = IC_RESULT(ic);
10016 right = IC_RIGHT(ic) ;
10019 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10021 /* if they are the same */
10022 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10025 aopOp(right,ic,FALSE);
10026 aopOp(result,ic,TRUE);
10028 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10030 /* if they are the same registers */
10031 if (pic14_sameRegs(AOP(right),AOP(result)))
10034 /* special case: assign from __code */
10035 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10036 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10037 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10038 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10039 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10041 emitpComment ("genAssign from CODESPACE");
10042 genConstPointerGet (right, result, ic);
10046 /* just for symmetry reasons... */
10047 if (!IS_ITEMP(result)
10048 && IS_SYMOP (result)
10049 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10051 assert ( !"cannot write to CODESPACE" );
10054 /* if the result is a bit */
10055 if (AOP_TYPE(result) == AOP_CRY) {
10057 /* if the right size is a literal then
10058 we know what the value is */
10059 if (AOP_TYPE(right) == AOP_LIT) {
10061 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10062 popGet(AOP(result),0));
10064 if (((int) operandLitValue(right)))
10065 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10066 AOP(result)->aopu.aop_dir,
10067 AOP(result)->aopu.aop_dir);
10069 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10070 AOP(result)->aopu.aop_dir,
10071 AOP(result)->aopu.aop_dir);
10075 /* the right is also a bit variable */
10076 if (AOP_TYPE(right) == AOP_CRY) {
10077 emitpcode(POC_BCF, popGet(AOP(result),0));
10078 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10079 emitpcode(POC_BSF, popGet(AOP(result),0));
10081 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10082 AOP(result)->aopu.aop_dir,
10083 AOP(result)->aopu.aop_dir);
10084 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10085 AOP(right)->aopu.aop_dir,
10086 AOP(right)->aopu.aop_dir);
10087 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10088 AOP(result)->aopu.aop_dir,
10089 AOP(result)->aopu.aop_dir);
10093 /* we need to or */
10094 emitpcode(POC_BCF, popGet(AOP(result),0));
10095 pic14_toBoolean(right);
10097 emitpcode(POC_BSF, popGet(AOP(result),0));
10098 //aopPut(AOP(result),"a",0);
10102 /* bit variables done */
10104 size = AOP_SIZE(result);
10106 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10107 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10108 if(aopIdx(AOP(result),0) == 4) {
10109 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10110 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10111 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10114 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10120 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10121 if(AOP_TYPE(right) == AOP_LIT) {
10122 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10124 if(know_W != (int)(lit&0xff))
10125 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10127 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10129 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10131 } else if (AOP_TYPE(right) == AOP_CRY) {
10132 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10134 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10135 emitpcode(POC_INCF, popGet(AOP(result),0));
10138 mov2w_op (right, offset);
10139 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10147 freeAsmop (right,NULL,ic,FALSE);
10148 freeAsmop (result,NULL,ic,TRUE);
10151 /*-----------------------------------------------------------------*/
10152 /* genJumpTab - genrates code for jump table */
10153 /*-----------------------------------------------------------------*/
10154 static void genJumpTab (iCode *ic)
10160 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10162 aopOp(IC_JTCOND(ic),ic,FALSE);
10163 /* get the condition into accumulator */
10164 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10166 /* multiply by three */
10167 pic14_emitcode("add","a,acc");
10168 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10170 jtab = newiTempLabel(NULL);
10171 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10172 pic14_emitcode("jmp","@a+dptr");
10173 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10175 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10176 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10177 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10178 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10180 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10181 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10182 emitpLabel(jtab->key);
10184 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10186 /* now generate the jump labels */
10187 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10188 jtab = setNextItem(IC_JTLABELS(ic))) {
10189 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10190 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10196 /*-----------------------------------------------------------------*/
10197 /* genMixedOperation - gen code for operators between mixed types */
10198 /*-----------------------------------------------------------------*/
10200 TSD - Written for the PIC port - but this unfortunately is buggy.
10201 This routine is good in that it is able to efficiently promote
10202 types to different (larger) sizes. Unfortunately, the temporary
10203 variables that are optimized out by this routine are sometimes
10204 used in other places. So until I know how to really parse the
10205 iCode tree, I'm going to not be using this routine :(.
10207 static int genMixedOperation (iCode *ic)
10211 operand *result = IC_RESULT(ic);
10212 sym_link *ctype = operandType(IC_LEFT(ic));
10213 operand *right = IC_RIGHT(ic);
10219 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10221 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10227 nextright = IC_RIGHT(nextic);
10228 nextleft = IC_LEFT(nextic);
10229 nextresult = IC_RESULT(nextic);
10231 aopOp(right,ic,FALSE);
10232 aopOp(result,ic,FALSE);
10233 aopOp(nextright, nextic, FALSE);
10234 aopOp(nextleft, nextic, FALSE);
10235 aopOp(nextresult, nextic, FALSE);
10237 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10239 operand *t = right;
10243 pic14_emitcode(";remove right +","");
10245 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10247 operand *t = right;
10251 pic14_emitcode(";remove left +","");
10255 big = AOP_SIZE(nextleft);
10256 small = AOP_SIZE(nextright);
10258 switch(nextic->op) {
10261 pic14_emitcode(";optimize a +","");
10262 /* if unsigned or not an integral type */
10263 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10264 pic14_emitcode(";add a bit to something","");
10267 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10269 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10270 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10271 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10273 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10281 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10282 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10283 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10286 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10288 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10289 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10290 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10291 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10292 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10295 pic14_emitcode("rlf","known_zero,w");
10302 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10303 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10304 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10306 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10316 freeAsmop(right,NULL,ic,TRUE);
10317 freeAsmop(result,NULL,ic,TRUE);
10318 freeAsmop(nextright,NULL,ic,TRUE);
10319 freeAsmop(nextleft,NULL,ic,TRUE);
10321 nextic->generated = 1;
10328 /*-----------------------------------------------------------------*/
10329 /* genCast - gen code for casting */
10330 /*-----------------------------------------------------------------*/
10331 static void genCast (iCode *ic)
10333 operand *result = IC_RESULT(ic);
10334 sym_link *restype = operandType(result);
10335 sym_link *rtype = operandType(IC_RIGHT(ic));
10336 operand *right = IC_RIGHT(ic);
10340 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10341 /* if they are equivalent then do nothing */
10342 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10345 aopOp(right,ic,FALSE) ;
10346 aopOp(result,ic,FALSE);
10348 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10350 /* if the result is a bit */
10351 if (AOP_TYPE(result) == AOP_CRY) {
10352 assert(!"assigning to bit variables is not supported");
10355 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10357 size = AOP_SIZE(result);
10359 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10361 emitpcode(POC_CLRF, popGet(AOP(result),0));
10362 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10363 emitpcode(POC_INCF, popGet(AOP(result),0));
10366 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10371 if (IS_PTR(restype))
10373 operand *result = IC_RESULT(ic);
10374 //operand *left = IC_LEFT(ic);
10375 operand *right = IC_RIGHT(ic);
10378 /* copy common part */
10379 int max, size = AOP_SIZE(result);
10380 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10381 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10383 /* warn if we discard generic opinter tag */
10384 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10386 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10392 mov2w_op (right, size);
10393 movwf (AOP(result), size);
10396 /* upcast into generic pointer type? */
10397 if (IS_GENPTR(restype)
10398 && (size < AOP_SIZE(result))
10399 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10401 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10404 switch (DCL_TYPE(rtype))
10406 case POINTER: /* __data */
10407 case FPOINTER: /* __data */
10408 assert (AOP_SIZE(right) == 2);
10409 tag = GPTRTAG_DATA;
10412 case CPOINTER: /* __code */
10413 assert (AOP_SIZE(right) == 2);
10414 tag = GPTRTAG_CODE;
10417 case GPOINTER: /* unknown destination, __data or __code */
10418 /* assume __data space (address of immediate) */
10419 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10420 if (AOP(right)->code)
10421 tag = GPTRTAG_CODE;
10423 tag = GPTRTAG_DATA;
10427 assert (!"unhandled pointer type");
10430 /* convert other values into pointers to __data space */
10431 tag = GPTRTAG_DATA;
10434 assert (AOP_SIZE(result) == 3);
10436 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10438 emitpcode(POC_MOVLW, popGetLit(tag));
10439 movwf(AOP(result), 2);
10442 addSign(result, max, 0);
10447 /* if they are the same size : or less */
10448 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10450 /* if they are in the same place */
10451 if (pic14_sameRegs(AOP(right),AOP(result)))
10454 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10455 if (IS_PTR_CONST(rtype))
10456 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10457 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10458 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10460 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10461 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10462 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10463 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10464 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10465 if(AOP_SIZE(result) <2)
10466 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10470 /* if they in different places then copy */
10471 size = AOP_SIZE(result);
10474 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10475 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10477 //aopPut(AOP(result),
10478 // aopGet(AOP(right),offset,FALSE,FALSE),
10487 /* so we now know that the size of destination is greater
10488 than the size of the source.
10489 Now, if the next iCode is an operator then we might be
10490 able to optimize the operation without performing a cast.
10492 if(0 && genMixedOperation(ic)) {
10493 /* XXX: cannot optimize: must copy regs! */
10497 /* we move to result for the size of source */
10498 size = AOP_SIZE(right);
10501 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10502 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10506 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10509 freeAsmop(right,NULL,ic,TRUE);
10510 freeAsmop(result,NULL,ic,TRUE);
10514 /*-----------------------------------------------------------------*/
10515 /* genDjnz - generate decrement & jump if not zero instrucion */
10516 /*-----------------------------------------------------------------*/
10517 static int genDjnz (iCode *ic, iCode *ifx)
10519 symbol *lbl, *lbl1;
10521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10526 /* if the if condition has a false label
10527 then we cannot save */
10531 /* if the minus is not of the form
10533 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10534 !IS_OP_LITERAL(IC_RIGHT(ic)))
10537 if (operandLitValue(IC_RIGHT(ic)) != 1)
10540 /* if the size of this greater than one then no
10542 if (getSize(operandType(IC_RESULT(ic))) > 1)
10545 /* otherwise we can save BIG */
10546 lbl = newiTempLabel(NULL);
10547 lbl1= newiTempLabel(NULL);
10549 aopOp(IC_RESULT(ic),ic,FALSE);
10551 if (IS_AOP_PREG(IC_RESULT(ic))) {
10552 pic14_emitcode("dec","%s",
10553 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10554 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10555 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10559 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10560 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10562 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10563 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10566 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10567 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10568 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10569 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10572 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10573 ifx->generated = 1;
10577 /*-----------------------------------------------------------------*/
10578 /* genReceive - generate code for a receive iCode */
10579 /*-----------------------------------------------------------------*/
10580 static void genReceive (iCode *ic)
10583 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10585 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10586 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10587 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10589 int size = getSize(operandType(IC_RESULT(ic)));
10590 int offset = fReturnSizePic - size;
10592 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10593 fReturn[fReturnSizePic - offset - 1] : "acc"));
10596 aopOp(IC_RESULT(ic),ic,FALSE);
10597 size = AOP_SIZE(IC_RESULT(ic));
10600 pic14_emitcode ("pop","acc");
10601 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10606 aopOp(IC_RESULT(ic),ic,FALSE);
10608 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10609 assignResultValue(IC_RESULT(ic));
10612 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10615 /*-----------------------------------------------------------------*/
10616 /* genDummyRead - generate code for dummy read of volatiles */
10617 /*-----------------------------------------------------------------*/
10619 genDummyRead (iCode * ic)
10622 pic14_emitcode ("; genDummyRead","");
10623 pic14_emitcode ("; not implemented","");
10628 /*-----------------------------------------------------------------*/
10629 /* genpic14Code - generate code for pic14 based controllers */
10630 /*-----------------------------------------------------------------*/
10632 * At this point, ralloc.c has gone through the iCode and attempted
10633 * to optimize in a way suitable for a PIC. Now we've got to generate
10634 * PIC instructions that correspond to the iCode.
10636 * Once the instructions are generated, we'll pass through both the
10637 * peep hole optimizer and the pCode optimizer.
10638 *-----------------------------------------------------------------*/
10640 void genpic14Code (iCode *lic)
10647 lineHead = lineCurr = NULL;
10649 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10652 /* if debug information required */
10653 if (options.debug && currFunc) {
10655 debugFile->writeFunction (currFunc, lic);
10660 for (ic = lic ; ic ; ic = ic->next ) {
10662 //DEBUGpic14_emitcode(";ic","");
10663 //fprintf (stderr, "in ic loop\n");
10664 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10665 //ic->lineno, printCLine(ic->filename, ic->lineno));
10667 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10669 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10670 cline = printCLine (ic->filename, ic->lineno);
10671 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10672 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10673 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10676 if (options.iCodeInAsm) {
10677 char *iLine = printILine(ic);
10678 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10681 /* if the result is marked as
10682 spilt and rematerializable or code for
10683 this has already been generated then
10685 if (resultRemat(ic) || ic->generated )
10688 /* depending on the operation */
10707 /* IPOP happens only when trying to restore a
10708 spilt live range, if there is an ifx statement
10709 following this pop then the if statement might
10710 be using some of the registers being popped which
10711 would destory the contents of the register so
10712 we need to check for this condition and handle it */
10714 ic->next->op == IFX &&
10715 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10716 genIfx (ic->next,ic);
10734 genEndFunction (ic);
10754 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10771 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10775 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10782 /* note these two are xlated by algebraic equivalence
10783 during parsing SDCC.y */
10784 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10785 "got '>=' or '<=' shouldn't have come here");
10789 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10801 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10805 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10809 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10833 genRightShift (ic);
10836 case GET_VALUE_AT_ADDRESS:
10841 if (POINTER_SET(ic))
10868 addSet(&_G.sendSet,ic);
10871 case DUMMY_READ_VOLATILE:
10876 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10883 /* now we are ready to call the
10884 peep hole optimizer */
10885 if (!options.nopeep) {
10886 peepHole (&lineHead);
10888 /* now do the actual printing */
10889 printLine (lineHead,codeOutBuf);
10892 DFPRINTF((stderr,"printing pBlock\n\n"));
10893 printpBlock(stdout,pb);
10899 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10900 * (meaning: representing its own address) or not (referencing its contents).
10901 * This can only be decided based on the operand's type. */
10903 aop_isLitLike (asmop *aop)
10906 if (aop->type == AOP_LIT) return 1;
10907 if (aop->type == AOP_IMMD) return 1;
10908 if ((aop->type == AOP_PCODE) &&
10909 ((aop->aopu.pcop->type == PO_LITERAL)))
10911 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10912 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10919 op_isLitLike (operand *op)
10922 if (aop_isLitLike (AOP(op))) return 1;
10923 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10924 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;