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)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
40 #include "SDCCpeeph.h"
45 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
46 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 void genMult8X8_8 (operand *, operand *,operand *);
48 extern void printpBlock(FILE *of, pBlock *pb);
50 static int labelOffset=0;
51 extern int debug_verbose;
52 static int optimized_for_speed = 0;
54 /* max_key keeps track of the largest label number used in
55 a function. This is then used to adjust the label offset
56 for the next function.
59 static int GpsuedoStkPtr=0;
61 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
62 unsigned int pic14aopLiteral (value *val, int offset);
63 const char *AopType(short type);
65 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
67 /* this is the down and dirty file with all kinds of
68 kludgy & hacky stuff. This is what it is all about
69 CODE GENERATION for a specific MCU . some of the
70 routines may be reusable, will have to see */
72 static char *zero = "#0x00";
73 static char *one = "#0x01";
74 static char *spname = "sp";
76 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
77 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
78 static char **fReturn = fReturnpic14;
80 //static char *accUse[] = {"a","b"};
82 //static short rbank = -1;
94 /* Resolved ifx structure. This structure stores information
95 about an iCode ifx that makes it easier to generate code.
97 typedef struct resolvedIfx {
98 symbol *lbl; /* pointer to a label */
99 int condition; /* true or false ifx */
100 int generated; /* set true when the code associated with the ifx
104 extern int pic14_ptrRegReq ;
105 extern int pic14_nRegs;
106 extern FILE *codeOutFile;
107 static void saverbank (int, iCode *,bool);
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
112 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
119 /*-----------------------------------------------------------------*/
120 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
121 /* exponent of 2 is returned, otherwise -1 is */
123 /* note that this is similar to the function `powof2' in SDCCsymt */
127 /*-----------------------------------------------------------------*/
128 static int my_powof2 (unsigned long num)
131 if( (num & (num-1)) == 0) {
144 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
147 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
149 ((result) ? AopType(AOP_TYPE(result)) : "-"),
150 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
151 ((left) ? AopType(AOP_TYPE(left)) : "-"),
152 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
153 ((right) ? AopType(AOP_TYPE(right)) : "-"),
154 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
155 ((result) ? AOP_SIZE(result) : 0));
159 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
162 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
164 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
166 ((left) ? AopType(AOP_TYPE(left)) : "-"),
167 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
168 ((right) ? AopType(AOP_TYPE(right)) : "-"),
169 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
176 char lb[INITIAL_INLINEASM];
177 unsigned char *lbp = lb;
179 if(!debug_verbose && !options.debug)
186 sprintf(lb,"%s\t",inst);
188 sprintf(lb,"%s",inst);
189 vsprintf(lb+(strlen(lb)),fmt,ap);
193 while (isspace(*lbp)) lbp++;
196 lineCurr = (lineCurr ?
197 connectLine(lineCurr,newLineNode(lb)) :
198 (lineHead = newLineNode(lb)));
199 lineCurr->isInline = _G.inLine;
200 lineCurr->isDebug = _G.debugLine;
202 addpCode2pBlock(pb,newpCodeCharP(lb));
207 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
209 #if defined (HAVE_VSNPRINTF)
210 vsnprintf (buf, size, fmt, ap);
211 #elif defined (HAVE_VSPRINTF)
212 vsprintf (buf, size, fmt, ap);
213 if (strlen (buf) >= size)
215 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
217 #elif defined (HAVE_SNPRINTF)
218 snprintf (buf, size, "vs(n)printf required");
219 #elif defined (HAVE_SRINTF)
220 sprintf (buf, "vs(n)printf required");
221 if (strlen (buf) >= size)
223 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
226 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
230 void emitpComment (const char *fmt, ...)
237 Safe_vsnprintf (buffer, 4096, fmt, va);
238 //fprintf (stderr, "%s\n" ,buffer);
239 addpCode2pBlock (pb, newpCodeCharP (buffer));
244 void emitpLabel(int key)
246 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
249 /* gen.h defines a macro emitpcode that should be used to call emitpcode
250 * as this allows for easy debugging (ever asked the question: where was
251 * this instruction geenrated? Here is the answer... */
252 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
255 addpCode2pBlock(pb,newpCode(poc,pcop));
257 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
260 void emitpcodeNULLop(PIC_OPCODE poc)
263 addpCode2pBlock(pb,newpCode(poc,NULL));
268 /*-----------------------------------------------------------------*/
269 /* pic14_emitcode - writes the code into a file : for now it is simple */
270 /*-----------------------------------------------------------------*/
271 void pic14_emitcode (char *inst,char *fmt, ...)
274 char lb[INITIAL_INLINEASM];
275 unsigned char *lbp = lb;
281 sprintf(lb,"%s\t",inst);
283 sprintf(lb,"%s",inst);
284 vsprintf(lb+(strlen(lb)),fmt,ap);
288 while (isspace(*lbp)) lbp++;
291 lineCurr = (lineCurr ?
292 connectLine(lineCurr,newLineNode(lb)) :
293 (lineHead = newLineNode(lb)));
294 lineCurr->isInline = _G.inLine;
295 lineCurr->isDebug = _G.debugLine;
298 addpCode2pBlock(pb,newpCodeCharP(lb));
303 /*-----------------------------------------------------------------*/
304 /* pic14_emitDebuggerSymbol - associate the current code location */
305 /* with a debugger symbol */
306 /*-----------------------------------------------------------------*/
308 pic14_emitDebuggerSymbol (char * debugSym)
311 pic14_emitcode ("", ";%s ==.", debugSym);
316 /*-----------------------------------------------------------------*/
317 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
318 /*-----------------------------------------------------------------*/
319 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
321 bool r0iu = FALSE , r1iu = FALSE;
322 bool r0ou = FALSE , r1ou = FALSE;
324 /* the logic: if r0 & r1 used in the instruction
325 then we are in trouble otherwise */
327 /* first check if r0 & r1 are used by this
328 instruction, in which case we are in trouble */
329 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
330 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
335 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
336 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
338 /* if no usage of r0 then return it */
339 if (!r0iu && !r0ou) {
340 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
341 (*aopp)->type = AOP_R0;
343 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
346 /* if no usage of r1 then return it */
347 if (!r1iu && !r1ou) {
348 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
349 (*aopp)->type = AOP_R1;
351 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
354 /* now we know they both have usage */
355 /* if r0 not used in this instruction */
357 /* push it if not already pushed */
359 //pic14_emitcode ("push","%s",
360 // pic14_regWithIdx(R0_IDX)->dname);
364 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
365 (*aopp)->type = AOP_R0;
367 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
370 /* if r1 not used then */
373 /* push it if not already pushed */
375 //pic14_emitcode ("push","%s",
376 // pic14_regWithIdx(R1_IDX)->dname);
380 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
381 (*aopp)->type = AOP_R1;
382 return pic14_regWithIdx(R1_IDX);
386 /* I said end of world but not quite end of world yet */
387 /* if this is a result then we can push it on the stack*/
389 (*aopp)->type = AOP_STK;
393 /* other wise this is true end of the world */
394 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
395 "getFreePtr should never reach here");
399 /*-----------------------------------------------------------------*/
400 /* newAsmop - creates a new asmOp */
401 /*-----------------------------------------------------------------*/
402 asmop *newAsmop (short type)
406 aop = Safe_calloc(1,sizeof(asmop));
411 static void genSetDPTR(int n)
415 pic14_emitcode(";", "Select standard DPTR");
416 pic14_emitcode("mov", "dps, #0x00");
420 pic14_emitcode(";", "Select alternate DPTR");
421 pic14_emitcode("mov", "dps, #0x01");
425 /*-----------------------------------------------------------------*/
426 /* resolveIfx - converts an iCode ifx into a form more useful for */
427 /* generating code */
428 /*-----------------------------------------------------------------*/
429 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
434 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
436 resIfx->condition = 1; /* assume that the ifx is true */
437 resIfx->generated = 0; /* indicate that the ifx has not been used */
440 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
442 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
443 __FUNCTION__,__LINE__,resIfx->lbl->key);
447 resIfx->lbl = IC_TRUE(ifx);
449 resIfx->lbl = IC_FALSE(ifx);
450 resIfx->condition = 0;
454 DEBUGpic14_emitcode("; ***","ifx true is non-null");
456 DEBUGpic14_emitcode("; ***","ifx false is non-null");
460 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
463 /*-----------------------------------------------------------------*/
464 /* pointerCode - returns the code for a pointer type */
465 /*-----------------------------------------------------------------*/
466 static int pointerCode (sym_link *etype)
469 return PTR_TYPE(SPEC_OCLS(etype));
473 /*-----------------------------------------------------------------*/
474 /* aopForSym - for a true symbol */
475 /*-----------------------------------------------------------------*/
476 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
479 memmap *space= SPEC_OCLS(sym->etype);
481 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
482 /* if already has one */
486 /* assign depending on the storage class */
487 /* if it is on the stack or indirectly addressable */
488 /* space we need to assign either r0 or r1 to it */
489 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
490 sym->aop = aop = newAsmop(0);
491 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
492 aop->size = getSize(sym->type);
494 /* now assign the address of the variable to
495 the pointer register */
496 if (aop->type != AOP_STK) {
500 pic14_emitcode("push","acc");
502 pic14_emitcode("mov","a,_bp");
503 pic14_emitcode("add","a,#0x%02x",
505 ((char)(sym->stack - _G.nRegsSaved )) :
506 ((char)sym->stack)) & 0xff);
507 pic14_emitcode("mov","%s,a",
508 aop->aopu.aop_ptr->name);
511 pic14_emitcode("pop","acc");
513 pic14_emitcode("mov","%s,#%s",
514 aop->aopu.aop_ptr->name,
516 aop->paged = space->paged;
518 aop->aopu.aop_stk = sym->stack;
522 if (sym->onStack && options.stack10bit)
524 /* It's on the 10 bit stack, which is located in
528 //DEBUGpic14_emitcode(";","%d",__LINE__);
531 pic14_emitcode("push","acc");
533 pic14_emitcode("mov","a,_bp");
534 pic14_emitcode("add","a,#0x%02x",
536 ((char)(sym->stack - _G.nRegsSaved )) :
537 ((char)sym->stack)) & 0xff);
540 pic14_emitcode ("mov","dpx1,#0x40");
541 pic14_emitcode ("mov","dph1,#0x00");
542 pic14_emitcode ("mov","dpl1, a");
546 pic14_emitcode("pop","acc");
548 sym->aop = aop = newAsmop(AOP_DPTR2);
549 aop->size = getSize(sym->type);
553 //DEBUGpic14_emitcode(";","%d",__LINE__);
554 /* if in bit space */
555 if (IN_BITSPACE(space)) {
556 sym->aop = aop = newAsmop (AOP_CRY);
557 aop->aopu.aop_dir = sym->rname ;
558 aop->size = getSize(sym->type);
559 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
562 /* if it is in direct space */
563 if (IN_DIRSPACE(space)) {
564 sym->aop = aop = newAsmop (AOP_DIR);
565 aop->aopu.aop_dir = sym->rname ;
566 aop->size = getSize(sym->type);
567 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
571 /* special case for a function */
572 if (IS_FUNC(sym->type)) {
574 sym->aop = aop = newAsmop(AOP_PCODE);
575 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
576 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
577 PCOI(aop->aopu.pcop)->_function = 1;
578 PCOI(aop->aopu.pcop)->index = 0;
579 aop->size = FPTRSIZE;
581 sym->aop = aop = newAsmop(AOP_IMMD);
582 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
583 strcpy(aop->aopu.aop_immd,sym->rname);
584 aop->size = FPTRSIZE;
586 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
591 /* only remaining is far space */
592 /* in which case DPTR gets the address */
593 sym->aop = aop = newAsmop(AOP_PCODE);
595 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
596 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
597 PCOI(aop->aopu.pcop)->index = 0;
599 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
600 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
602 allocDirReg (IC_LEFT(ic));
604 aop->size = FPTRSIZE;
606 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
607 sym->aop = aop = newAsmop(AOP_DPTR);
608 pic14_emitcode ("mov","dptr,#%s", sym->rname);
609 aop->size = getSize(sym->type);
611 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
614 /* if it is in code space */
615 if (IN_CODESPACE(space))
621 /*-----------------------------------------------------------------*/
622 /* aopForRemat - rematerialzes an object */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForRemat (operand *op) // x symbol *sym)
626 symbol *sym = OP_SYMBOL(op);
628 asmop *aop = newAsmop(AOP_PCODE);
632 ic = sym->rematiCode;
634 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
635 if(IS_OP_POINTER(op)) {
636 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
640 val += (int) operandLitValue(IC_RIGHT(ic));
641 } else if (ic->op == '-') {
642 val -= (int) operandLitValue(IC_RIGHT(ic));
646 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
649 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
650 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
651 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
652 PCOI(aop->aopu.pcop)->index = val;
654 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
655 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
656 val, IS_PTR_CONST(operandType(op)));
658 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
660 allocDirReg (IC_LEFT(ic));
665 int aopIdx (asmop *aop, int offset)
670 if(aop->type != AOP_REG)
673 return aop->aopu.aop_reg[offset]->rIdx;
676 /*-----------------------------------------------------------------*/
677 /* regsInCommon - two operands have some registers in common */
678 /*-----------------------------------------------------------------*/
679 static bool regsInCommon (operand *op1, operand *op2)
684 /* if they have registers in common */
685 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
688 sym1 = OP_SYMBOL(op1);
689 sym2 = OP_SYMBOL(op2);
691 if (sym1->nRegs == 0 || sym2->nRegs == 0)
694 for (i = 0 ; i < sym1->nRegs ; i++) {
699 for (j = 0 ; j < sym2->nRegs ;j++ ) {
703 if (sym2->regs[j] == sym1->regs[i])
711 /*-----------------------------------------------------------------*/
712 /* operandsEqu - equivalent */
713 /*-----------------------------------------------------------------*/
714 static bool operandsEqu ( operand *op1, operand *op2)
718 /* if they not symbols */
719 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
722 sym1 = OP_SYMBOL(op1);
723 sym2 = OP_SYMBOL(op2);
725 /* if both are itemps & one is spilt
726 and the other is not then false */
727 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
728 sym1->isspilt != sym2->isspilt )
731 /* if they are the same */
735 if (sym1->rname[0] && sym2->rname[0]
736 && strcmp (sym1->rname, sym2->rname) == 0)
740 /* if left is a tmp & right is not */
744 (sym1->usl.spillLoc == sym2))
751 (sym2->usl.spillLoc == sym1))
757 /*-----------------------------------------------------------------*/
758 /* pic14_sameRegs - two asmops have the same registers */
759 /*-----------------------------------------------------------------*/
760 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
767 if (aop1->type != AOP_REG ||
768 aop2->type != AOP_REG )
771 if (aop1->size != aop2->size )
774 for (i = 0 ; i < aop1->size ; i++ )
775 if (aop1->aopu.aop_reg[i] !=
776 aop2->aopu.aop_reg[i] )
782 /*-----------------------------------------------------------------*/
783 /* aopOp - allocates an asmop for an operand : */
784 /*-----------------------------------------------------------------*/
785 void aopOp (operand *op, iCode *ic, bool result)
794 /* if this a literal */
795 if (IS_OP_LITERAL(op)) {
796 op->aop = aop = newAsmop(AOP_LIT);
797 aop->aopu.aop_lit = op->operand.valOperand;
798 aop->size = getSize(operandType(op));
803 sym_link *type = operandType(op);
804 if(IS_PTR_CONST(type))
805 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
808 /* if already has a asmop then continue */
812 /* if the underlying symbol has a aop */
813 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
814 DEBUGpic14_emitcode(";","%d",__LINE__);
815 op->aop = OP_SYMBOL(op)->aop;
819 /* if this is a true symbol */
820 if (IS_TRUE_SYMOP(op)) {
821 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
822 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
826 /* this is a temporary : this has
832 e) can be a return use only */
837 /* if the type is a conditional */
838 if (sym->regType == REG_CND) {
839 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
844 /* if it is spilt then two situations
846 b) has a spill location */
847 if (sym->isspilt || sym->nRegs == 0) {
849 DEBUGpic14_emitcode(";","%d",__LINE__);
850 /* rematerialize it NOW */
853 sym->aop = op->aop = aop = aopForRemat (op);
854 aop->size = getSize(sym->type);
855 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
860 /* WREG is not usable as an ordinary operand with PIC architecture,
861 * one might introduce a scratch register that can be used to make
862 * WREG accesible as an operand... disable WREG for now */
865 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
866 aop->size = getSize(sym->type);
867 for ( i = 0 ; i < 2 ; i++ )
868 aop->aopu.aop_str[i] = accUse[i];
869 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
875 if(sym->isptr) { // && sym->uptr
876 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
877 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
879 //PCOI(aop->aopu.pcop)->_const = 0;
880 //PCOI(aop->aopu.pcop)->index = 0;
882 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
883 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
885 //allocDirReg (IC_LEFT(ic));
887 aop->size = getSize(sym->type);
888 DEBUGpic14_emitcode(";","%d",__LINE__);
895 aop = op->aop = sym->aop = newAsmop(AOP_STR);
896 aop->size = getSize(sym->type);
897 for ( i = 0 ; i < fReturnSizePic ; i++ )
898 aop->aopu.aop_str[i] = fReturn[i];
900 DEBUGpic14_emitcode(";","%d",__LINE__);
905 /* else spill location */
906 if (sym->usl.spillLoc)
908 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
910 /* force a new aop if sizes differ */
911 sym->usl.spillLoc->aop = NULL;
913 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
914 __FUNCTION__,__LINE__,
915 sym->usl.spillLoc->rname,
916 sym->rname, sym->usl.spillLoc->offset);
918 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
919 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
920 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
922 sym->usl.spillLoc->offset);
923 aop->size = getSize(sym->type);
930 sym_link *type = operandType(op);
931 if(IS_PTR_CONST(type))
932 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
935 /* must be in a register */
936 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
937 sym->aop = op->aop = aop = newAsmop(AOP_REG);
938 aop->size = sym->nRegs;
939 for ( i = 0 ; i < sym->nRegs ;i++)
940 aop->aopu.aop_reg[i] = sym->regs[i];
943 /*-----------------------------------------------------------------*/
944 /* freeAsmop - free up the asmop given to an operand */
945 /*----------------------------------------------------------------*/
946 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
963 /* depending on the asmop type only three cases need work AOP_RO
964 , AOP_R1 && AOP_STK */
970 pic14_emitcode ("pop","ar0");
974 bitVectUnSetBit(ic->rUsed,R0_IDX);
980 pic14_emitcode ("pop","ar1");
984 bitVectUnSetBit(ic->rUsed,R1_IDX);
990 int stk = aop->aopu.aop_stk + aop->size;
991 bitVectUnSetBit(ic->rUsed,R0_IDX);
992 bitVectUnSetBit(ic->rUsed,R1_IDX);
994 getFreePtr(ic,&aop,FALSE);
996 if (options.stack10bit)
998 /* I'm not sure what to do here yet... */
1001 "*** Warning: probably generating bad code for "
1002 "10 bit stack mode.\n");
1006 pic14_emitcode ("mov","a,_bp");
1007 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1008 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1010 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1014 pic14_emitcode("pop","acc");
1015 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1017 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1020 freeAsmop(op,NULL,ic,TRUE);
1022 pic14_emitcode("pop","ar0");
1027 pic14_emitcode("pop","ar1");
1035 /* all other cases just dealloc */
1039 OP_SYMBOL(op)->aop = NULL;
1040 /* if the symbol has a spill */
1042 SPIL_LOC(op)->aop = NULL;
1047 /*-----------------------------------------------------------------*/
1048 /* aopGet - for fetching value of the aop */
1049 /*-----------------------------------------------------------------*/
1050 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1055 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1056 /* offset is greater than
1058 if (offset > (aop->size - 1) &&
1059 aop->type != AOP_LIT)
1062 /* depending on type */
1063 switch (aop->type) {
1067 DEBUGpic14_emitcode(";","%d",__LINE__);
1068 /* if we need to increment it */
1069 while (offset > aop->coff) {
1070 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1074 while (offset < aop->coff) {
1075 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1079 aop->coff = offset ;
1081 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1082 return (dname ? "acc" : "a");
1084 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1085 rs = Safe_calloc(1,strlen(s)+1);
1091 DEBUGpic14_emitcode(";","%d",__LINE__);
1092 if (aop->type == AOP_DPTR2)
1097 while (offset > aop->coff) {
1098 pic14_emitcode ("inc","dptr");
1102 while (offset < aop->coff) {
1103 pic14_emitcode("lcall","__decdptr");
1109 pic14_emitcode("clr","a");
1110 pic14_emitcode("movc","a,@a+dptr");
1113 pic14_emitcode("movx","a,@dptr");
1116 if (aop->type == AOP_DPTR2)
1121 return (dname ? "acc" : "a");
1126 sprintf (s,"%s",aop->aopu.aop_immd);
1129 sprintf(s,"(%s >> %d)",
1134 aop->aopu.aop_immd);
1135 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1136 rs = Safe_calloc(1,strlen(s)+1);
1142 sprintf(s,"(%s + %d)",
1145 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1147 sprintf(s,"%s",aop->aopu.aop_dir);
1148 rs = Safe_calloc(1,strlen(s)+1);
1154 // return aop->aopu.aop_reg[offset]->dname;
1156 return aop->aopu.aop_reg[offset]->name;
1159 //pic14_emitcode(";","%d",__LINE__);
1160 return aop->aopu.aop_dir;
1163 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1164 return "AOP_accumulator_bug";
1167 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1168 rs = Safe_calloc(1,strlen(s)+1);
1173 aop->coff = offset ;
1174 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1177 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1179 return aop->aopu.aop_str[offset];
1183 pCodeOp *pcop = aop->aopu.pcop;
1184 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1187 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1188 sprintf(s,"(%s+%d)", pcop->name,offset);
1190 DEBUGpic14_emitcode(";","%s",pcop->name);
1191 sprintf(s,"%s", pcop->name);
1194 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1197 rs = Safe_calloc(1,strlen(s)+1);
1203 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1204 "aopget got unsupported aop->type");
1209 /*-----------------------------------------------------------------*/
1210 /* popGetTempReg - create a new temporary pCodeOp */
1211 /*-----------------------------------------------------------------*/
1212 pCodeOp *popGetTempReg(void)
1217 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1218 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1219 PCOR(pcop)->r->wasUsed=1;
1220 PCOR(pcop)->r->isFree=0;
1226 /*-----------------------------------------------------------------*/
1227 /* popReleaseTempReg - create a new temporary pCodeOp */
1228 /*-----------------------------------------------------------------*/
1229 void popReleaseTempReg(pCodeOp *pcop)
1232 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1233 PCOR(pcop)->r->isFree = 1;
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLabel(unsigned int key)
1242 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1244 if(key>(unsigned int)max_key)
1247 return newpCodeOpLabel(NULL,key+100+labelOffset);
1250 /*-------------------------------------------------------------------*/
1251 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1252 /*-------------------------------------------------------------------*/
1253 pCodeOp *popGetHighLabel(unsigned int key)
1256 pcop = popGetLabel(key);
1257 PCOLAB(pcop)->offset = 1;
1261 /*-----------------------------------------------------------------*/
1262 /* popGetLit - asm operator to pcode operator conversion */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *popGetLit(unsigned int lit)
1267 return newpCodeOpLit(lit);
1270 /*-----------------------------------------------------------------*/
1271 /* popGetImmd - asm operator to pcode immediate conversion */
1272 /*-----------------------------------------------------------------*/
1273 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1276 return newpCodeOpImmd(name, offset,index, 0, is_func);
1280 /*-----------------------------------------------------------------*/
1281 /* popGetWithString - asm operator to pcode operator conversion */
1282 /*-----------------------------------------------------------------*/
1283 pCodeOp *popGetWithString(char *str, int isExtern)
1289 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1293 pcop = newpCodeOp(str,PO_STR);
1294 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1299 /*-----------------------------------------------------------------*/
1300 /* popRegFromString - */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *popRegFromString(char *str, int size, int offset)
1305 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1306 pcop->type = PO_DIR;
1308 DEBUGpic14_emitcode(";","%d",__LINE__);
1313 pcop->name = Safe_calloc(1,strlen(str)+1);
1314 strcpy(pcop->name,str);
1316 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1318 PCOR(pcop)->r = dirregWithName(pcop->name);
1319 if(PCOR(pcop)->r == NULL) {
1320 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1321 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1322 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1324 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1326 PCOR(pcop)->instance = offset;
1331 /*-----------------------------------------------------------------*/
1332 /*-----------------------------------------------------------------*/
1333 pCodeOp *popRegFromIdx(int rIdx)
1337 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1338 __FUNCTION__,__LINE__,rIdx);
1340 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1342 PCOR(pcop)->rIdx = rIdx;
1343 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1344 PCOR(pcop)->r->isFree = 0;
1345 PCOR(pcop)->r->wasUsed = 1;
1347 pcop->type = PCOR(pcop)->r->pc_type;
1353 /*-----------------------------------------------------------------*/
1354 /* popGet - asm operator to pcode operator conversion */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1358 //char *s = buffer ;
1363 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1364 /* offset is greater than
1367 if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1369 fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1371 assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1373 /* XXX: still needed for BIT operands (AOP_CRY) */
1374 if (offset > (aop->size - 1) &&
1375 aop->type != AOP_LIT)
1376 return NULL; //zero;
1378 /* depending on type */
1379 switch (aop->type) {
1386 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1390 DEBUGpic14_emitcode(";","%d",__LINE__);
1391 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1394 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1396 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1397 pcop->type = PO_DIR;
1399 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1400 strcpy(pcop->name,aop->aopu.aop_dir);
1401 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1402 if(PCOR(pcop)->r == NULL) {
1403 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1404 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1405 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1407 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1409 PCOR(pcop)->instance = offset;
1416 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1418 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1419 PCOR(pcop)->rIdx = rIdx;
1420 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1421 PCOR(pcop)->r->wasUsed=1;
1422 PCOR(pcop)->r->isFree=0;
1424 PCOR(pcop)->instance = offset;
1425 pcop->type = PCOR(pcop)->r->pc_type;
1426 //rs = aop->aopu.aop_reg[offset]->name;
1427 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1432 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1433 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1434 //if(PCOR(pcop)->r == NULL)
1435 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1439 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1442 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1443 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1445 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1446 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1447 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1448 pcop->type = PCOR(pcop)->r->pc_type;
1449 pcop->name = PCOR(pcop)->r->name;
1456 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1458 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1459 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1460 switch (aop->aopu.pcop->type)
1463 pcop = pCodeOpCopy (aop->aopu.pcop);
1464 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1465 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1466 PCOI(pcop)->index += offset;
1467 //PCOI(pcop)->offset = 0;
1470 pcop = pCodeOpCopy (aop->aopu.pcop);
1471 PCOR(pcop)->instance = offset;
1474 assert ( !"unhandled pCode type" );
1480 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1481 "popGet got unsupported aop->type");
1485 /*-----------------------------------------------------------------*/
1486 /* popGetAddr - access the low/high word of a symbol (immediate) */
1487 /* (for non-PO_IMMEDIATEs this is the same as poGet) */
1488 /*-----------------------------------------------------------------*/
1489 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1491 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1493 pCodeOp *pcop = aop->aopu.pcop;
1494 pcop = pCodeOpCopy (pcop);
1495 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1496 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1497 PCOI(pcop)->offset += offset;
1498 PCOI(pcop)->index += index;
1501 return popGet (aop, offset + index);
1505 /*-----------------------------------------------------------------*/
1506 /* aopPut - puts a string for a aop */
1507 /*-----------------------------------------------------------------*/
1508 void aopPut (asmop *aop, char *s, int offset)
1513 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1515 if (aop->size && offset > ( aop->size - 1)) {
1516 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1517 "aopPut got offset > aop->size");
1521 /* will assign value to value */
1522 /* depending on where it is ofcourse */
1523 switch (aop->type) {
1526 sprintf(d,"(%s + %d)",
1527 aop->aopu.aop_dir,offset);
1528 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1531 sprintf(d,"%s",aop->aopu.aop_dir);
1534 DEBUGpic14_emitcode(";","%d",__LINE__);
1536 pic14_emitcode("movf","%s,w",s);
1537 pic14_emitcode("movwf","%s",d);
1540 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1541 if(offset >= aop->size) {
1542 emitpcode(POC_CLRF,popGet(aop,offset));
1545 emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1548 emitpcode(POC_MOVWF,popGet(aop,offset));
1555 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1556 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1559 strcmp(s,"r0") == 0 ||
1560 strcmp(s,"r1") == 0 ||
1561 strcmp(s,"r2") == 0 ||
1562 strcmp(s,"r3") == 0 ||
1563 strcmp(s,"r4") == 0 ||
1564 strcmp(s,"r5") == 0 ||
1565 strcmp(s,"r6") == 0 ||
1566 strcmp(s,"r7") == 0 )
1567 pic14_emitcode("mov","%s,%s ; %d",
1568 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1572 if(strcmp(s,"W")==0 )
1573 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1575 pic14_emitcode("movwf","%s",
1576 aop->aopu.aop_reg[offset]->name);
1578 if(strcmp(s,zero)==0) {
1579 emitpcode(POC_CLRF,popGet(aop,offset));
1581 } else if(strcmp(s,"W")==0) {
1582 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1583 pcop->type = PO_GPR_REGISTER;
1585 PCOR(pcop)->rIdx = -1;
1586 PCOR(pcop)->r = NULL;
1588 DEBUGpic14_emitcode(";","%d",__LINE__);
1589 pcop->name = Safe_strdup(s);
1590 emitpcode(POC_MOVFW,pcop);
1591 emitpcode(POC_MOVWF,popGet(aop,offset));
1592 } else if(strcmp(s,one)==0) {
1593 emitpcode(POC_CLRF,popGet(aop,offset));
1594 emitpcode(POC_INCF,popGet(aop,offset));
1596 emitpcode(POC_MOVWF,popGet(aop,offset));
1604 if (aop->type == AOP_DPTR2)
1610 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1611 "aopPut writting to code space");
1615 while (offset > aop->coff) {
1617 pic14_emitcode ("inc","dptr");
1620 while (offset < aop->coff) {
1622 pic14_emitcode("lcall","__decdptr");
1627 /* if not in accumulater */
1630 pic14_emitcode ("movx","@dptr,a");
1632 if (aop->type == AOP_DPTR2)
1640 while (offset > aop->coff) {
1642 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1644 while (offset < aop->coff) {
1646 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1652 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1657 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1659 if (strcmp(s,"r0") == 0 ||
1660 strcmp(s,"r1") == 0 ||
1661 strcmp(s,"r2") == 0 ||
1662 strcmp(s,"r3") == 0 ||
1663 strcmp(s,"r4") == 0 ||
1664 strcmp(s,"r5") == 0 ||
1665 strcmp(s,"r6") == 0 ||
1666 strcmp(s,"r7") == 0 ) {
1668 sprintf(buffer,"a%s",s);
1669 pic14_emitcode("mov","@%s,%s",
1670 aop->aopu.aop_ptr->name,buffer);
1672 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1677 if (strcmp(s,"a") == 0)
1678 pic14_emitcode("push","acc");
1680 pic14_emitcode("push","%s",s);
1685 /* if bit variable */
1686 if (!aop->aopu.aop_dir) {
1687 pic14_emitcode("clr","a");
1688 pic14_emitcode("rlc","a");
1691 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1694 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1697 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1699 lbl = newiTempLabel(NULL);
1701 if (strcmp(s,"a")) {
1704 pic14_emitcode("clr","c");
1705 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1706 pic14_emitcode("cpl","c");
1707 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1708 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1715 if (strcmp(aop->aopu.aop_str[offset],s))
1716 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1721 if (!offset && (strcmp(s,"acc") == 0))
1724 if (strcmp(aop->aopu.aop_str[offset],s))
1725 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1729 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1730 "aopPut got unsupported aop->type");
1736 /*-----------------------------------------------------------------*/
1737 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1738 /*-----------------------------------------------------------------*/
1739 void mov2w (asmop *aop, int offset)
1745 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1747 if ( aop_isLitLike (aop) )
1748 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1750 emitpcode(POC_MOVFW,popGet(aop,offset));
1754 /*-----------------------------------------------------------------*/
1755 /* reAdjustPreg - points a register back to where it should */
1756 /*-----------------------------------------------------------------*/
1757 static void reAdjustPreg (asmop *aop)
1761 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1763 if ((size = aop->size) <= 1)
1766 switch (aop->type) {
1770 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1774 if (aop->type == AOP_DPTR2)
1780 pic14_emitcode("lcall","__decdptr");
1783 if (aop->type == AOP_DPTR2)
1795 /*-----------------------------------------------------------------*/
1796 /* opIsGptr: returns non-zero if the passed operand is */
1797 /* a generic pointer type. */
1798 /*-----------------------------------------------------------------*/
1799 static int opIsGptr(operand *op)
1801 sym_link *type = operandType(op);
1803 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1804 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1812 /*-----------------------------------------------------------------*/
1813 /* pic14_getDataSize - get the operand data size */
1814 /*-----------------------------------------------------------------*/
1815 int pic14_getDataSize(operand *op)
1817 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1820 return AOP_SIZE(op);
1822 // tsd- in the pic port, the genptr size is 1, so this code here
1823 // fails. ( in the 8051 port, the size was 4).
1826 size = AOP_SIZE(op);
1827 if (size == GPTRSIZE)
1829 sym_link *type = operandType(op);
1830 if (IS_GENPTR(type))
1832 /* generic pointer; arithmetic operations
1833 * should ignore the high byte (pointer type).
1836 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1843 /*-----------------------------------------------------------------*/
1844 /* pic14_outAcc - output Acc */
1845 /*-----------------------------------------------------------------*/
1846 void pic14_outAcc(operand *result)
1849 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1850 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1853 size = pic14_getDataSize(result);
1855 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1858 /* unsigned or positive */
1860 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1865 /*-----------------------------------------------------------------*/
1866 /* pic14_outBitC - output a bit C */
1867 /*-----------------------------------------------------------------*/
1868 void pic14_outBitC(operand *result)
1871 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1872 /* if the result is bit */
1873 if (AOP_TYPE(result) == AOP_CRY)
1874 aopPut(AOP(result),"c",0);
1876 pic14_emitcode("clr","a ; %d", __LINE__);
1877 pic14_emitcode("rlc","a");
1878 pic14_outAcc(result);
1882 /*-----------------------------------------------------------------*/
1883 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1884 /*-----------------------------------------------------------------*/
1885 void pic14_toBoolean(operand *oper)
1887 int size = AOP_SIZE(oper) - 1;
1890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1892 if ( AOP_TYPE(oper) != AOP_ACC) {
1893 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1896 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1901 /*-----------------------------------------------------------------*/
1902 /* genNot - generate code for ! operation */
1903 /*-----------------------------------------------------------------*/
1904 static void genNot (iCode *ic)
1911 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1912 /* assign asmOps to operand & result */
1913 aopOp (IC_LEFT(ic),ic,FALSE);
1914 aopOp (IC_RESULT(ic),ic,TRUE);
1916 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1917 /* if in bit space then a special case */
1918 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1919 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1920 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1921 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1923 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1924 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1925 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1930 assert (!pic14_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
1931 size = AOP_SIZE(IC_LEFT(ic));
1932 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1933 mov2w (AOP(IC_LEFT(ic)),0);
1936 if (aop_isLitLike (AOP(IC_LEFT(ic))))
1937 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1939 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1942 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1946 /* release the aops */
1947 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1948 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement */
1954 /*-----------------------------------------------------------------*/
1955 static void genCpl (iCode *ic)
1957 operand *left, *result;
1962 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1963 aopOp((left = IC_LEFT(ic)),ic,FALSE);
1964 aopOp((result=IC_RESULT(ic)),ic,TRUE);
1966 /* if both are in bit space then
1968 if (AOP_TYPE(result) == AOP_CRY &&
1969 AOP_TYPE(left) == AOP_CRY ) {
1971 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
1972 pic14_emitcode("cpl","c");
1973 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
1977 size = AOP_SIZE(result);
1980 if(AOP_TYPE(left) == AOP_ACC)
1981 emitpcode(POC_XORLW, popGetLit(0xff));
1983 emitpcode(POC_COMFW,popGet(AOP(left),offset));
1985 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1991 /* release the aops */
1992 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1993 freeAsmop(result,NULL,ic,TRUE);
1996 /*-----------------------------------------------------------------*/
1997 /* genUminusFloat - unary minus for floating points */
1998 /*-----------------------------------------------------------------*/
1999 static void genUminusFloat(operand *op,operand *result)
2001 int size ,offset =0 ;
2006 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2007 /* for this we just need to flip the
2008 first it then copy the rest in place */
2009 size = AOP_SIZE(op) - 1;
2010 l = aopGet(AOP(op),3,FALSE,FALSE);
2014 pic14_emitcode("cpl","acc.7");
2015 aopPut(AOP(result),"a",3);
2019 aopGet(AOP(op),offset,FALSE,FALSE),
2025 /*-----------------------------------------------------------------*/
2026 /* genUminus - unary minus code generation */
2027 /*-----------------------------------------------------------------*/
2028 static void genUminus (iCode *ic)
2031 sym_link *optype, *rtype;
2035 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2037 aopOp(IC_LEFT(ic),ic,FALSE);
2038 aopOp(IC_RESULT(ic),ic,TRUE);
2040 /* if both in bit space then special
2042 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2043 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2045 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2046 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2047 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2052 optype = operandType(IC_LEFT(ic));
2053 rtype = operandType(IC_RESULT(ic));
2055 /* if float then do float stuff */
2056 if (IS_FLOAT(optype)) {
2057 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2061 /* otherwise subtract from zero by taking the 2's complement */
2062 size = AOP_SIZE(IC_LEFT(ic));
2064 for(i=0; i<size; i++) {
2065 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2066 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2068 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2069 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2073 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2074 for(i=1; i<size; i++) {
2076 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2080 /* release the aops */
2081 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2082 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2085 /*-----------------------------------------------------------------*/
2086 /* saveRegisters - will look for a call and save the registers */
2087 /*-----------------------------------------------------------------*/
2088 static void saveRegisters(iCode *lic)
2097 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2099 for (ic = lic ; ic ; ic = ic->next)
2100 if (ic->op == CALL || ic->op == PCALL)
2104 fprintf(stderr,"found parameter push with no function call\n");
2108 /* if the registers have been saved already then
2110 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2113 /* find the registers in use at this time
2114 and push them away to safety */
2115 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2119 if (options.useXstack) {
2120 if (bitVectBitValue(rsave,R0_IDX))
2121 pic14_emitcode("mov","b,r0");
2122 pic14_emitcode("mov","r0,%s",spname);
2123 for (i = 0 ; i < pic14_nRegs ; i++) {
2124 if (bitVectBitValue(rsave,i)) {
2126 pic14_emitcode("mov","a,b");
2128 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2129 pic14_emitcode("movx","@r0,a");
2130 pic14_emitcode("inc","r0");
2133 pic14_emitcode("mov","%s,r0",spname);
2134 if (bitVectBitValue(rsave,R0_IDX))
2135 pic14_emitcode("mov","r0,b");
2137 //for (i = 0 ; i < pic14_nRegs ; i++) {
2138 // if (bitVectBitValue(rsave,i))
2139 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2142 dtype = operandType(IC_LEFT(ic));
2143 if (currFunc && dtype &&
2144 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2145 IFFUNC_ISISR(currFunc->type) &&
2148 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2151 /*-----------------------------------------------------------------*/
2152 /* unsaveRegisters - pop the pushed registers */
2153 /*-----------------------------------------------------------------*/
2154 static void unsaveRegisters (iCode *ic)
2161 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2162 /* find the registers in use at this time
2163 and push them away to safety */
2164 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2167 if (options.useXstack) {
2168 pic14_emitcode("mov","r0,%s",spname);
2169 for (i = pic14_nRegs ; i >= 0 ; i--) {
2170 if (bitVectBitValue(rsave,i)) {
2171 pic14_emitcode("dec","r0");
2172 pic14_emitcode("movx","a,@r0");
2174 pic14_emitcode("mov","b,a");
2176 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2180 pic14_emitcode("mov","%s,r0",spname);
2181 if (bitVectBitValue(rsave,R0_IDX))
2182 pic14_emitcode("mov","r0,b");
2184 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2185 // if (bitVectBitValue(rsave,i))
2186 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2192 /*-----------------------------------------------------------------*/
2194 /*-----------------------------------------------------------------*/
2195 static void pushSide(operand * oper, int size)
2199 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2201 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2202 if (AOP_TYPE(oper) != AOP_REG &&
2203 AOP_TYPE(oper) != AOP_DIR &&
2205 pic14_emitcode("mov","a,%s",l);
2206 pic14_emitcode("push","acc");
2208 pic14_emitcode("push","%s",l);
2213 /*-----------------------------------------------------------------*/
2214 /* assignResultValue - */
2215 /*-----------------------------------------------------------------*/
2216 static void assignResultValue(operand * oper)
2218 int size = AOP_SIZE(oper);
2222 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2224 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2227 if (GpsuedoStkPtr++)
2228 emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2229 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2234 /*-----------------------------------------------------------------*/
2235 /* genIpush - genrate code for pushing this gets a little complex */
2236 /*-----------------------------------------------------------------*/
2237 static void genIpush (iCode *ic)
2241 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2243 int size, offset = 0 ;
2247 /* if this is not a parm push : ie. it is spill push
2248 and spill push is always done on the local stack */
2249 if (!ic->parmPush) {
2251 /* and the item is spilt then do nothing */
2252 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2255 aopOp(IC_LEFT(ic),ic,FALSE);
2256 size = AOP_SIZE(IC_LEFT(ic));
2257 /* push it on the stack */
2259 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2264 pic14_emitcode("push","%s",l);
2269 /* this is a paramter push: in this case we call
2270 the routine to find the call and save those
2271 registers that need to be saved */
2274 /* then do the push */
2275 aopOp(IC_LEFT(ic),ic,FALSE);
2278 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2279 size = AOP_SIZE(IC_LEFT(ic));
2282 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2283 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2284 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2286 pic14_emitcode("mov","a,%s",l);
2287 pic14_emitcode("push","acc");
2289 pic14_emitcode("push","%s",l);
2292 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2296 /*-----------------------------------------------------------------*/
2297 /* genIpop - recover the registers: can happen only for spilling */
2298 /*-----------------------------------------------------------------*/
2299 static void genIpop (iCode *ic)
2303 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2308 /* if the temp was not pushed then */
2309 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2312 aopOp(IC_LEFT(ic),ic,FALSE);
2313 size = AOP_SIZE(IC_LEFT(ic));
2316 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2319 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2323 /*-----------------------------------------------------------------*/
2324 /* unsaverbank - restores the resgister bank from stack */
2325 /*-----------------------------------------------------------------*/
2326 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2330 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2336 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2338 if (options.useXstack) {
2340 r = getFreePtr(ic,&aop,FALSE);
2343 pic14_emitcode("mov","%s,_spx",r->name);
2344 pic14_emitcode("movx","a,@%s",r->name);
2345 pic14_emitcode("mov","psw,a");
2346 pic14_emitcode("dec","%s",r->name);
2349 pic14_emitcode ("pop","psw");
2352 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2353 if (options.useXstack) {
2354 pic14_emitcode("movx","a,@%s",r->name);
2355 //pic14_emitcode("mov","(%s+%d),a",
2356 // regspic14[i].base,8*bank+regspic14[i].offset);
2357 pic14_emitcode("dec","%s",r->name);
2360 pic14_emitcode("pop",""); //"(%s+%d)",
2361 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2364 if (options.useXstack) {
2366 pic14_emitcode("mov","_spx,%s",r->name);
2367 freeAsmop(NULL,aop,ic,TRUE);
2373 /*-----------------------------------------------------------------*/
2374 /* saverbank - saves an entire register bank on the stack */
2375 /*-----------------------------------------------------------------*/
2376 static void saverbank (int bank, iCode *ic, bool pushPsw)
2380 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2386 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2387 if (options.useXstack) {
2390 r = getFreePtr(ic,&aop,FALSE);
2391 pic14_emitcode("mov","%s,_spx",r->name);
2395 for (i = 0 ; i < pic14_nRegs ;i++) {
2396 if (options.useXstack) {
2397 pic14_emitcode("inc","%s",r->name);
2398 //pic14_emitcode("mov","a,(%s+%d)",
2399 // regspic14[i].base,8*bank+regspic14[i].offset);
2400 pic14_emitcode("movx","@%s,a",r->name);
2402 pic14_emitcode("push","");// "(%s+%d)",
2403 //regspic14[i].base,8*bank+regspic14[i].offset);
2407 if (options.useXstack) {
2408 pic14_emitcode("mov","a,psw");
2409 pic14_emitcode("movx","@%s,a",r->name);
2410 pic14_emitcode("inc","%s",r->name);
2411 pic14_emitcode("mov","_spx,%s",r->name);
2412 freeAsmop (NULL,aop,ic,TRUE);
2415 pic14_emitcode("push","psw");
2417 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2423 /*-----------------------------------------------------------------*/
2424 /* genCall - generates a call statement */
2425 /*-----------------------------------------------------------------*/
2426 static void genCall (iCode *ic)
2430 unsigned char *name;
2435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2437 /* if caller saves & we have not saved then */
2441 /* if we are calling a function that is not using
2442 the same register bank then we need to save the
2443 destination registers on the stack */
2444 dtype = operandType(IC_LEFT(ic));
2445 if (currFunc && dtype &&
2446 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2447 IFFUNC_ISISR(currFunc->type) &&
2450 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2452 /* if send set is not empty the assign */
2455 /* For the Pic port, there is no data stack.
2456 * So parameters passed to functions are stored
2457 * in registers. (The pCode optimizer will get
2458 * rid of most of these :).
2460 int psuedoStkPtr=-1;
2461 int firstTimeThruLoop = 1;
2463 _G.sendSet = reverseSet(_G.sendSet);
2465 /* First figure how many parameters are getting passed */
2466 for (sic = setFirstItem(_G.sendSet) ; sic ;
2467 sic = setNextItem(_G.sendSet)) {
2469 aopOp(IC_LEFT(sic),sic,FALSE);
2470 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2471 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2474 for (sic = setFirstItem(_G.sendSet) ; sic ;
2475 sic = setNextItem(_G.sendSet)) {
2476 int size, offset = 0;
2478 aopOp(IC_LEFT(sic),sic,FALSE);
2479 size = AOP_SIZE(IC_LEFT(sic));
2482 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2483 AopType(AOP_TYPE(IC_LEFT(sic))));
2485 if(!firstTimeThruLoop) {
2486 /* If this is not the first time we've been through the loop
2487 * then we need to save the parameter in a temporary
2488 * register. The last byte of the last parameter is
2490 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2493 firstTimeThruLoop=0;
2495 mov2w (AOP(IC_LEFT(sic)), offset);
2498 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2503 sym = OP_SYMBOL(IC_LEFT(ic));
2504 name = sym->rname[0] ? sym->rname : sym->name;
2505 isExtern = IS_EXTERN(sym->etype);
2507 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2509 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2511 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2514 /* if we need assign a result value */
2515 if ((IS_ITEMP(IC_RESULT(ic)) &&
2516 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2517 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2518 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2521 aopOp(IC_RESULT(ic),ic,FALSE);
2524 assignResultValue(IC_RESULT(ic));
2526 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2527 AopType(AOP_TYPE(IC_RESULT(ic))));
2529 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2532 /* adjust the stack for parameters if
2534 if (ic->parmBytes) {
2536 if (ic->parmBytes > 3) {
2537 pic14_emitcode("mov","a,%s",spname);
2538 pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2539 pic14_emitcode("mov","%s,a",spname);
2541 for ( i = 0 ; i < ic->parmBytes ;i++)
2542 pic14_emitcode("dec","%s",spname);
2546 /* if register bank was saved then pop them */
2548 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2550 /* if we hade saved some registers then unsave them */
2551 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2552 unsaveRegisters (ic);
2557 /*-----------------------------------------------------------------*/
2558 /* genPcall - generates a call by pointer statement */
2559 /*-----------------------------------------------------------------*/
2560 static void genPcall (iCode *ic)
2563 symbol *albl = newiTempLabel(NULL);
2564 symbol *blbl = newiTempLabel(NULL);
2571 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2572 /* if caller saves & we have not saved then */
2576 /* if we are calling a function that is not using
2577 the same register bank then we need to save the
2578 destination registers on the stack */
2579 dtype = operandType(IC_LEFT(ic));
2580 if (currFunc && dtype &&
2581 IFFUNC_ISISR(currFunc->type) &&
2582 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2583 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2586 aopOp(left,ic,FALSE);
2587 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2589 pushSide(IC_LEFT(ic), FPTRSIZE);
2591 /* if send set is not empty, assign parameters */
2594 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2595 /* no way to pass args - W always gets used to make the call */
2597 /* first idea - factor out a common helper function and call it.
2598 But don't know how to get it generated only once in its own block
2600 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2603 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2604 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2605 buffer = Safe_calloc(1,strlen(rname)+16);
2606 sprintf(buffer, "%s_goto_helper", rname);
2607 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2611 emitpcode(POC_CALL,popGetLabel(albl->key));
2612 pcop = popGetLabel(blbl->key);
2613 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2614 emitpcode(POC_GOTO,pcop);
2615 emitpLabel(albl->key);
2617 poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2619 emitpcode(poc,popGetAddr(AOP(left),1,0));
2620 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2621 emitpcode(poc,popGetAddr(AOP(left),0,0));
2622 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2624 emitpLabel(blbl->key);
2626 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2628 /* if we need to assign a result value */
2629 if ((IS_ITEMP(IC_RESULT(ic)) &&
2630 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2631 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2632 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2635 aopOp(IC_RESULT(ic),ic,FALSE);
2638 assignResultValue(IC_RESULT(ic));
2640 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2643 /* if register bank was saved then unsave them */
2644 if (currFunc && dtype &&
2645 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2646 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2648 /* if we hade saved some registers then
2651 unsaveRegisters (ic);
2655 /*-----------------------------------------------------------------*/
2656 /* resultRemat - result is rematerializable */
2657 /*-----------------------------------------------------------------*/
2658 static int resultRemat (iCode *ic)
2660 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2663 if (SKIP_IC(ic) || ic->op == IFX)
2666 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2667 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2668 if (sym->remat && !POINTER_SET(ic))
2675 #if defined(__BORLANDC__) || defined(_MSC_VER)
2676 #define STRCASECMP stricmp
2678 #define STRCASECMP strcasecmp
2682 /*-----------------------------------------------------------------*/
2683 /* inExcludeList - return 1 if the string is in exclude Reg list */
2684 /*-----------------------------------------------------------------*/
2685 static bool inExcludeList(char *s)
2687 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2690 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2691 if (options.excludeRegs[i] &&
2692 STRCASECMP(options.excludeRegs[i],"none") == 0)
2695 for ( i = 0 ; options.excludeRegs[i]; i++) {
2696 if (options.excludeRegs[i] &&
2697 STRCASECMP(s,options.excludeRegs[i]) == 0)
2704 /*-----------------------------------------------------------------*/
2705 /* genFunction - generated code for function entry */
2706 /*-----------------------------------------------------------------*/
2707 static void genFunction (iCode *ic)
2714 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2716 labelOffset += (max_key+4);
2720 /* create the function header */
2721 pic14_emitcode(";","-----------------------------------------");
2722 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2723 pic14_emitcode(";","-----------------------------------------");
2725 pic14_emitcode("","%s:",sym->rname);
2726 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2728 ftype = operandType(IC_LEFT(ic));
2730 /* if critical function then turn interrupts off */
2731 if (IFFUNC_ISCRITICAL(ftype))
2732 pic14_emitcode("clr","ea");
2734 /* here we need to generate the equates for the
2735 register bank if required */
2737 if (FUNC_REGBANK(ftype) != rbank) {
2740 rbank = FUNC_REGBANK(ftype);
2741 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2742 if (strcmp(regspic14[i].base,"0") == 0)
2743 pic14_emitcode("","%s = 0x%02x",
2745 8*rbank+regspic14[i].offset);
2747 pic14_emitcode ("","%s = %s + 0x%02x",
2750 8*rbank+regspic14[i].offset);
2755 /* if this is an interrupt service routine */
2756 if (IFFUNC_ISISR(sym->type)) {
2757 /* already done in pic14createInterruptVect() - delete me
2758 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2759 emitpcodeNULLop(POC_NOP);
2760 emitpcodeNULLop(POC_NOP);
2761 emitpcodeNULLop(POC_NOP);
2763 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2764 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2765 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2766 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2767 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2768 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2769 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2771 pBlockConvert2ISR(pb);
2773 if (!inExcludeList("acc"))
2774 pic14_emitcode ("push","acc");
2775 if (!inExcludeList("b"))
2776 pic14_emitcode ("push","b");
2777 if (!inExcludeList("dpl"))
2778 pic14_emitcode ("push","dpl");
2779 if (!inExcludeList("dph"))
2780 pic14_emitcode ("push","dph");
2781 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2783 pic14_emitcode ("push", "dpx");
2784 /* Make sure we're using standard DPTR */
2785 pic14_emitcode ("push", "dps");
2786 pic14_emitcode ("mov", "dps, #0x00");
2787 if (options.stack10bit)
2789 /* This ISR could conceivably use DPTR2. Better save it. */
2790 pic14_emitcode ("push", "dpl1");
2791 pic14_emitcode ("push", "dph1");
2792 pic14_emitcode ("push", "dpx1");
2795 /* if this isr has no bank i.e. is going to
2796 run with bank 0 , then we need to save more
2798 if (!FUNC_REGBANK(sym->type)) {
2800 /* if this function does not call any other
2801 function then we can be economical and
2802 save only those registers that are used */
2803 if (! IFFUNC_HASFCALL(sym->type)) {
2806 /* if any registers used */
2807 if (sym->regsUsed) {
2808 /* save the registers used */
2809 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2810 if (bitVectBitValue(sym->regsUsed,i) ||
2811 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2812 pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
2817 /* this function has a function call cannot
2818 determines register usage so we will have the
2820 saverbank(0,ic,FALSE);
2825 /* if callee-save to be used for this function
2826 then save the registers being used in this function */
2827 if (IFFUNC_CALLEESAVES(sym->type)) {
2830 /* if any registers used */
2831 if (sym->regsUsed) {
2832 /* save the registers used */
2833 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2834 if (bitVectBitValue(sym->regsUsed,i) ||
2835 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2836 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2844 /* set the register bank to the desired value */
2845 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2846 pic14_emitcode("push","psw");
2847 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2850 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2852 if (options.useXstack) {
2853 pic14_emitcode("mov","r0,%s",spname);
2854 pic14_emitcode("mov","a,_bp");
2855 pic14_emitcode("movx","@r0,a");
2856 pic14_emitcode("inc","%s",spname);
2860 /* set up the stack */
2861 pic14_emitcode ("push","_bp"); /* save the callers stack */
2863 pic14_emitcode ("mov","_bp,%s",spname);
2866 /* adjust the stack for the function */
2871 werror(W_STACK_OVERFLOW,sym->name);
2873 if (i > 3 && sym->recvSize < 4) {
2875 pic14_emitcode ("mov","a,sp");
2876 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2877 pic14_emitcode ("mov","sp,a");
2882 pic14_emitcode("inc","sp");
2887 pic14_emitcode ("mov","a,_spx");
2888 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2889 pic14_emitcode ("mov","_spx,a");
2894 /*-----------------------------------------------------------------*/
2895 /* genEndFunction - generates epilogue for functions */
2896 /*-----------------------------------------------------------------*/
2897 static void genEndFunction (iCode *ic)
2899 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2903 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2905 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2907 pic14_emitcode ("mov","%s,_bp",spname);
2910 /* if use external stack but some variables were
2911 added to the local stack then decrement the
2913 if (options.useXstack && sym->stack) {
2914 pic14_emitcode("mov","a,sp");
2915 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2916 pic14_emitcode("mov","sp,a");
2920 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2921 if (options.useXstack) {
2922 pic14_emitcode("mov","r0,%s",spname);
2923 pic14_emitcode("movx","a,@r0");
2924 pic14_emitcode("mov","_bp,a");
2925 pic14_emitcode("dec","%s",spname);
2929 pic14_emitcode ("pop","_bp");
2933 /* restore the register bank */
2934 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2935 pic14_emitcode ("pop","psw");
2937 if (IFFUNC_ISISR(sym->type)) {
2939 /* now we need to restore the registers */
2940 /* if this isr has no bank i.e. is going to
2941 run with bank 0 , then we need to save more
2943 if (!FUNC_REGBANK(sym->type)) {
2945 /* if this function does not call any other
2946 function then we can be economical and
2947 save only those registers that are used */
2948 if (! IFFUNC_HASFCALL(sym->type)) {
2951 /* if any registers used */
2952 if (sym->regsUsed) {
2953 /* save the registers used */
2954 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2955 if (bitVectBitValue(sym->regsUsed,i) ||
2956 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2957 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2962 /* this function has a function call cannot
2963 determines register usage so we will have the
2965 unsaverbank(0,ic,FALSE);
2969 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2971 if (options.stack10bit)
2973 pic14_emitcode ("pop", "dpx1");
2974 pic14_emitcode ("pop", "dph1");
2975 pic14_emitcode ("pop", "dpl1");
2977 pic14_emitcode ("pop", "dps");
2978 pic14_emitcode ("pop", "dpx");
2980 if (!inExcludeList("dph"))
2981 pic14_emitcode ("pop","dph");
2982 if (!inExcludeList("dpl"))
2983 pic14_emitcode ("pop","dpl");
2984 if (!inExcludeList("b"))
2985 pic14_emitcode ("pop","b");
2986 if (!inExcludeList("acc"))
2987 pic14_emitcode ("pop","acc");
2989 if (IFFUNC_ISCRITICAL(sym->type))
2990 pic14_emitcode("setb","ea");
2993 /* if debug then send end of function */
2994 /* if (options.debug && currFunc) { */
2996 debugFile->writeEndFunction (currFunc, ic, 1);
2999 pic14_emitcode ("reti","");
3000 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3001 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3002 emitpcode(POC_CLRF, popCopyReg(&pc_status));
3003 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3004 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3005 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3006 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3007 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3008 emitpcodeNULLop(POC_RETFIE);
3011 if (IFFUNC_ISCRITICAL(sym->type))
3012 pic14_emitcode("setb","ea");
3014 if (IFFUNC_CALLEESAVES(sym->type)) {
3017 /* if any registers used */
3018 if (sym->regsUsed) {
3019 /* save the registers used */
3020 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3021 if (bitVectBitValue(sym->regsUsed,i) ||
3022 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3023 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3029 /* if debug then send end of function */
3031 debugFile->writeEndFunction (currFunc, ic, 1);
3034 pic14_emitcode ("return","");
3035 emitpcodeNULLop(POC_RETURN);
3037 /* Mark the end of a function */
3038 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3043 /*-----------------------------------------------------------------*/
3044 /* genRet - generate code for return statement */
3045 /*-----------------------------------------------------------------*/
3046 static void genRet (iCode *ic)
3048 int size,offset = 0 , pushed = 0;
3052 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3053 /* if we have no return value then
3054 just generate the "ret" */
3058 /* we have something to return then
3059 move the return value into place */
3060 aopOp(IC_LEFT(ic),ic,FALSE);
3061 size = AOP_SIZE(IC_LEFT(ic));
3065 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3067 l = aopGet(AOP(IC_LEFT(ic)),offset++,
3069 pic14_emitcode("push","%s",l);
3072 l = aopGet(AOP(IC_LEFT(ic)),offset,
3074 if (strcmp(fReturn[offset],l)) {
3075 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) &&
3076 AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3077 ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3078 ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3079 emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3081 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3084 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3094 if (strcmp(fReturn[pushed],"a"))
3095 pic14_emitcode("pop",fReturn[pushed]);
3097 pic14_emitcode("pop","acc");
3100 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3103 /* generate a jump to the return label
3104 if the next is not the return statement */
3105 if (!(ic->next && ic->next->op == LABEL &&
3106 IC_LABEL(ic->next) == returnLabel)) {
3108 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3109 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3114 /*-----------------------------------------------------------------*/
3115 /* genLabel - generates a label */
3116 /*-----------------------------------------------------------------*/
3117 static void genLabel (iCode *ic)
3121 /* special case never generate */
3122 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3123 if (IC_LABEL(ic) == entryLabel)
3126 emitpLabel(IC_LABEL(ic)->key);
3127 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3130 /*-----------------------------------------------------------------*/
3131 /* genGoto - generates a goto */
3132 /*-----------------------------------------------------------------*/
3134 static void genGoto (iCode *ic)
3138 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3139 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3143 /*-----------------------------------------------------------------*/
3144 /* genMultbits :- multiplication of bits */
3145 /*-----------------------------------------------------------------*/
3146 static void genMultbits (operand *left,
3151 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3153 if(!pic14_sameRegs(AOP(result),AOP(right)))
3154 emitpcode(POC_BSF, popGet(AOP(result),0));
3156 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3157 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3158 emitpcode(POC_BCF, popGet(AOP(result),0));
3163 /*-----------------------------------------------------------------*/
3164 /* genMultOneByte : 8 bit multiplication & division */
3165 /*-----------------------------------------------------------------*/
3166 static void genMultOneByte (operand *left,
3170 sym_link *opetype = operandType(result);
3177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3178 DEBUGpic14_AopType(__LINE__,left,right,result);
3179 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3181 /* (if two literals, the value is computed before) */
3182 /* if one literal, literal on the right */
3183 if (AOP_TYPE(left) == AOP_LIT){
3189 size = AOP_SIZE(result);
3192 if (AOP_TYPE(right) == AOP_LIT){
3193 pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s",
3194 aopGet(AOP(right),0,FALSE,FALSE),
3195 aopGet(AOP(left),0,FALSE,FALSE),
3196 aopGet(AOP(result),0,FALSE,FALSE));
3197 pic14_emitcode("call","genMultLit");
3199 pic14_emitcode("multiply ","variable :%s by variable %s and store in %s",
3200 aopGet(AOP(right),0,FALSE,FALSE),
3201 aopGet(AOP(left),0,FALSE,FALSE),
3202 aopGet(AOP(result),0,FALSE,FALSE));
3203 pic14_emitcode("call","genMult8X8_8");
3206 genMult8X8_8 (left, right,result);
3209 /* signed or unsigned */
3210 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3211 //l = aopGet(AOP(left),0,FALSE,FALSE);
3213 //pic14_emitcode("mul","ab");
3214 /* if result size = 1, mul signed = mul unsigned */
3215 //aopPut(AOP(result),"a",0);
3217 } else { // (size > 1)
3219 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s",
3220 aopGet(AOP(right),0,FALSE,FALSE),
3221 aopGet(AOP(left),0,FALSE,FALSE),
3222 aopGet(AOP(result),0,FALSE,FALSE));
3224 if (SPEC_USIGN(opetype)){
3225 pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3226 genUMult8X8_16 (left, right, result, NULL);
3229 /* for filling the MSBs */
3230 emitpcode(POC_CLRF, popGet(AOP(result),2));
3231 emitpcode(POC_CLRF, popGet(AOP(result),3));
3235 pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3237 pic14_emitcode("mov","a,b");
3239 /* adjust the MSB if left or right neg */
3241 /* if one literal */
3242 if (AOP_TYPE(right) == AOP_LIT){
3243 pic14_emitcode("multiply ","right is a lit");
3244 /* AND literal negative */
3245 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3246 /* adjust MSB (c==0 after mul) */
3247 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3251 genSMult8X8_16 (left, right, result, NULL);
3255 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3257 pic14_emitcode("rlc","a");
3258 pic14_emitcode("subb","a,acc");
3266 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3267 //aopPut(AOP(result),"a",offset++);
3271 /*-----------------------------------------------------------------*/
3272 /* genMult - generates code for multiplication */
3273 /*-----------------------------------------------------------------*/
3274 static void genMult (iCode *ic)
3276 operand *left = IC_LEFT(ic);
3277 operand *right = IC_RIGHT(ic);
3278 operand *result= IC_RESULT(ic);
3282 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3283 /* assign the amsops */
3284 aopOp (left,ic,FALSE);
3285 aopOp (right,ic,FALSE);
3286 aopOp (result,ic,TRUE);
3288 DEBUGpic14_AopType(__LINE__,left,right,result);
3290 /* special cases first */
3292 if (AOP_TYPE(left) == AOP_CRY &&
3293 AOP_TYPE(right)== AOP_CRY) {
3294 genMultbits(left,right,result);
3298 /* if both are of size == 1 */
3299 if (AOP_SIZE(left) == 1 &&
3300 AOP_SIZE(right) == 1 ) {
3301 genMultOneByte(left,right,result);
3305 pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3307 assert( AOP_SIZE(left) == AOP_SIZE(right) );
3308 assert( AOP_SIZE(result) >= AOP_SIZE(left) );
3310 /* should have been converted to function call */
3314 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3315 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3316 freeAsmop(result,NULL,ic,TRUE);
3319 /*-----------------------------------------------------------------*/
3320 /* genDivbits :- division of bits */
3321 /*-----------------------------------------------------------------*/
3322 static void genDivbits (operand *left,
3331 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3332 /* the result must be bit */
3333 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3334 l = aopGet(AOP(left),0,FALSE,FALSE);
3338 pic14_emitcode("div","ab");
3339 pic14_emitcode("rrc","a");
3340 aopPut(AOP(result),"c",0);
3343 /*-----------------------------------------------------------------*/
3344 /* genDivOneByte : 8 bit division */
3345 /*-----------------------------------------------------------------*/
3346 static void genDivOneByte (operand *left,
3350 sym_link *opetype = operandType(result);
3356 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3357 size = AOP_SIZE(result) - 1;
3359 /* signed or unsigned */
3360 if (SPEC_USIGN(opetype)) {
3361 /* unsigned is easy */
3362 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3363 l = aopGet(AOP(left),0,FALSE,FALSE);
3365 pic14_emitcode("div","ab");
3366 aopPut(AOP(result),"a",0);
3368 aopPut(AOP(result),zero,offset++);
3372 /* signed is a little bit more difficult */
3374 /* save the signs of the operands */
3375 l = aopGet(AOP(left),0,FALSE,FALSE);
3377 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3378 pic14_emitcode("push","acc"); /* save it on the stack */
3380 /* now sign adjust for both left & right */
3381 l = aopGet(AOP(right),0,FALSE,FALSE);
3383 lbl = newiTempLabel(NULL);
3384 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3385 pic14_emitcode("cpl","a");
3386 pic14_emitcode("inc","a");
3387 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3388 pic14_emitcode("mov","b,a");
3390 /* sign adjust left side */
3391 l = aopGet(AOP(left),0,FALSE,FALSE);
3394 lbl = newiTempLabel(NULL);
3395 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3396 pic14_emitcode("cpl","a");
3397 pic14_emitcode("inc","a");
3398 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3400 /* now the division */
3401 pic14_emitcode("div","ab");
3402 /* we are interested in the lower order
3404 pic14_emitcode("mov","b,a");
3405 lbl = newiTempLabel(NULL);
3406 pic14_emitcode("pop","acc");
3407 /* if there was an over flow we don't
3408 adjust the sign of the result */
3409 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3410 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3412 pic14_emitcode("clr","a");
3413 pic14_emitcode("subb","a,b");
3414 pic14_emitcode("mov","b,a");
3415 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3417 /* now we are done */
3418 aopPut(AOP(result),"b",0);
3420 pic14_emitcode("mov","c,b.7");
3421 pic14_emitcode("subb","a,acc");
3424 aopPut(AOP(result),"a",offset++);
3428 /*-----------------------------------------------------------------*/
3429 /* genDiv - generates code for division */
3430 /*-----------------------------------------------------------------*/
3431 static void genDiv (iCode *ic)
3433 operand *left = IC_LEFT(ic);
3434 operand *right = IC_RIGHT(ic);
3435 operand *result= IC_RESULT(ic);
3438 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3439 /* assign the amsops */
3440 aopOp (left,ic,FALSE);
3441 aopOp (right,ic,FALSE);
3442 aopOp (result,ic,TRUE);
3444 /* special cases first */
3446 if (AOP_TYPE(left) == AOP_CRY &&
3447 AOP_TYPE(right)== AOP_CRY) {
3448 genDivbits(left,right,result);
3452 /* if both are of size == 1 */
3453 if (AOP_SIZE(left) == 1 &&
3454 AOP_SIZE(right) == 1 ) {
3455 genDivOneByte(left,right,result);
3459 /* should have been converted to function call */
3462 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3463 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3464 freeAsmop(result,NULL,ic,TRUE);
3467 /*-----------------------------------------------------------------*/
3468 /* genModbits :- modulus of bits */
3469 /*-----------------------------------------------------------------*/
3470 static void genModbits (operand *left,
3478 /* the result must be bit */
3479 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3480 l = aopGet(AOP(left),0,FALSE,FALSE);
3484 pic14_emitcode("div","ab");
3485 pic14_emitcode("mov","a,b");
3486 pic14_emitcode("rrc","a");
3487 aopPut(AOP(result),"c",0);
3490 /*-----------------------------------------------------------------*/
3491 /* genModOneByte : 8 bit modulus */
3492 /*-----------------------------------------------------------------*/
3493 static void genModOneByte (operand *left,
3497 sym_link *opetype = operandType(result);
3502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3503 /* signed or unsigned */
3504 if (SPEC_USIGN(opetype)) {
3505 /* unsigned is easy */
3506 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3507 l = aopGet(AOP(left),0,FALSE,FALSE);
3509 pic14_emitcode("div","ab");
3510 aopPut(AOP(result),"b",0);
3514 /* signed is a little bit more difficult */
3516 /* save the signs of the operands */
3517 l = aopGet(AOP(left),0,FALSE,FALSE);
3520 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3521 pic14_emitcode("push","acc"); /* save it on the stack */
3523 /* now sign adjust for both left & right */
3524 l = aopGet(AOP(right),0,FALSE,FALSE);
3527 lbl = newiTempLabel(NULL);
3528 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3529 pic14_emitcode("cpl","a");
3530 pic14_emitcode("inc","a");
3531 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3532 pic14_emitcode("mov","b,a");
3534 /* sign adjust left side */
3535 l = aopGet(AOP(left),0,FALSE,FALSE);
3538 lbl = newiTempLabel(NULL);
3539 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3540 pic14_emitcode("cpl","a");
3541 pic14_emitcode("inc","a");
3542 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3544 /* now the multiplication */
3545 pic14_emitcode("div","ab");
3546 /* we are interested in the lower order
3548 lbl = newiTempLabel(NULL);
3549 pic14_emitcode("pop","acc");
3550 /* if there was an over flow we don't
3551 adjust the sign of the result */
3552 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3553 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3555 pic14_emitcode("clr","a");
3556 pic14_emitcode("subb","a,b");
3557 pic14_emitcode("mov","b,a");
3558 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3560 /* now we are done */
3561 aopPut(AOP(result),"b",0);
3565 /*-----------------------------------------------------------------*/
3566 /* genMod - generates code for division */
3567 /*-----------------------------------------------------------------*/
3568 static void genMod (iCode *ic)
3570 operand *left = IC_LEFT(ic);
3571 operand *right = IC_RIGHT(ic);
3572 operand *result= IC_RESULT(ic);
3575 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3576 /* assign the amsops */
3577 aopOp (left,ic,FALSE);
3578 aopOp (right,ic,FALSE);
3579 aopOp (result,ic,TRUE);
3581 /* special cases first */
3583 if (AOP_TYPE(left) == AOP_CRY &&
3584 AOP_TYPE(right)== AOP_CRY) {
3585 genModbits(left,right,result);
3589 /* if both are of size == 1 */
3590 if (AOP_SIZE(left) == 1 &&
3591 AOP_SIZE(right) == 1 ) {
3592 genModOneByte(left,right,result);
3596 /* should have been converted to function call */
3600 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3601 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3602 freeAsmop(result,NULL,ic,TRUE);
3605 /*-----------------------------------------------------------------*/
3606 /* genIfxJump :- will create a jump depending on the ifx */
3607 /*-----------------------------------------------------------------*/
3609 note: May need to add parameter to indicate when a variable is in bit space.
3611 static void genIfxJump (iCode *ic, char *jval)
3615 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3616 /* if true label then we jump if condition
3618 if ( IC_TRUE(ic) ) {
3620 if(strcmp(jval,"a") == 0)
3622 else if (strcmp(jval,"c") == 0)
3625 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3626 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3629 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3630 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3634 /* false label is present */
3635 if(strcmp(jval,"a") == 0)
3637 else if (strcmp(jval,"c") == 0)
3640 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3641 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3644 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3645 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3650 /* mark the icode as generated */
3654 /*-----------------------------------------------------------------*/
3656 /*-----------------------------------------------------------------*/
3657 static void genSkip(iCode *ifx,int status_bit)
3663 if ( IC_TRUE(ifx) ) {
3664 switch(status_bit) {
3679 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3680 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3684 switch(status_bit) {
3698 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3699 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3705 /*-----------------------------------------------------------------*/
3707 /*-----------------------------------------------------------------*/
3708 static void genSkipc(resolvedIfx *rifx)
3719 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3720 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3721 rifx->generated = 1;
3724 /*-----------------------------------------------------------------*/
3726 /*-----------------------------------------------------------------*/
3727 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3733 if( (rifx->condition ^ invert_condition) & 1)
3738 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3739 rifx->generated = 1;
3742 /*-----------------------------------------------------------------*/
3744 /*-----------------------------------------------------------------*/
3745 static void genSkipz(iCode *ifx, int condition)
3757 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3759 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3762 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3764 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3769 /*-----------------------------------------------------------------*/
3771 /*-----------------------------------------------------------------*/
3772 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3779 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3781 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3784 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3785 rifx->generated = 1;
3790 /*-----------------------------------------------------------------*/
3791 /* genChkZeroes :- greater or less than comparison */
3792 /* For each byte in a literal that is zero, inclusive or the */
3793 /* the corresponding byte in the operand with W */
3794 /* returns true if any of the bytes are zero */
3795 /*-----------------------------------------------------------------*/
3796 static int genChkZeroes(operand *op, int lit, int size)
3803 i = (lit >> (size*8)) & 0xff;
3807 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3809 emitpcode(POC_IORFW, popGet(AOP(op),size));
3819 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3820 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3821 #define DEBUGpc emitpComment
3823 /*-----------------------------------------------------------------*/
3824 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3825 /* aop (if it's NOT a literal) or from lit (if */
3826 /* aop is a literal) */
3827 /*-----------------------------------------------------------------*/
3828 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3829 if (aop->type == AOP_LIT) {
3830 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3832 emitpcode (POC_MOVFW, popGet (aop, offset));
3836 /* genCmp performs a left < right comparison, stores
3837 * the outcome in result (if != NULL) and generates
3838 * control flow code for the ifx (if != NULL).
3840 * This version leaves in sequences like
3841 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3842 * which should be optmized by the peephole
3843 * optimizer - RN 2005-01-01 */
3844 static void genCmp (operand *left,operand *right,
3845 operand *result, iCode *ifx, int sign)
3855 int invert_result = 0;
3859 assert (AOP_SIZE(left) == AOP_SIZE(right));
3860 assert (left && right);
3862 size = AOP_SIZE(right) - 1;
3863 mask = (0x100UL << (size*8)) - 1;
3864 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3869 resolveIfx (&rIfx, ifx);
3871 /**********************************************************************
3872 * handle bits - bit compares are promoted to int compares seemingly! *
3873 **********************************************************************/
3875 // THIS IS COMPLETELY UNTESTED!
3876 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3877 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3878 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3879 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3882 // 1 < {0,1} is false --> clear C by skipping the next instruction
3883 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3884 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3885 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3886 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3887 emitCLRC; // only skipped for left=0 && right=1
3889 goto correct_result_in_carry;
3893 /*************************************************
3894 * make sure that left is register (or the like) *
3895 *************************************************/
3896 if (!isAOP_REGlike(left)) {
3897 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3898 assert (isAOP_LIT(left));
3899 assert (isAOP_REGlike(right));
3900 // swap left and right
3901 // left < right <==> right > left <==> (right >= left + 1)
3902 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3904 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3905 // MAXVALUE < right? always false
3906 if (performedLt) emitCLRC; else emitSETC;
3907 goto correct_result_in_carry;
3910 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3911 // that's why we handled it above.
3918 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3919 } else if (isAOP_LIT(right)) {
3920 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3923 assert (isAOP_REGlike(left)); // left must be register or the like
3924 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3926 /*************************************************
3927 * special cases go here *
3928 *************************************************/
3930 if (isAOP_LIT(right)) {
3932 // unsigned comparison to a literal
3933 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3935 // unsigned left < 0? always false
3936 if (performedLt) emitCLRC; else emitSETC;
3937 goto correct_result_in_carry;
3940 // signed comparison to a literal
3941 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3942 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3943 // signed left < 0x80000000? always false
3944 if (performedLt) emitCLRC; else emitSETC;
3945 goto correct_result_in_carry;
3946 } else if (lit == 0) {
3947 // compare left < 0; set CARRY if SIGNBIT(left) is set
3948 if (performedLt) emitSETC; else emitCLRC;
3949 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3950 if (performedLt) emitCLRC; else emitSETC;
3951 goto correct_result_in_carry;
3954 } // right is literal
3956 /*************************************************
3957 * perform a general case comparison *
3958 * make sure we get CARRY==1 <==> left >= right *
3959 *************************************************/
3960 // compare most significant bytes
3961 //DEBUGpc ("comparing bytes at offset %d", size);
3963 // unsigned comparison
3964 pic14_mov2w_regOrLit (AOP(right), lit, size);
3965 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3967 // signed comparison
3968 // (add 2^n to both operands then perform an unsigned comparison)
3969 if (isAOP_LIT(right)) {
3970 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3971 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3973 if (litbyte == 0x80) {
3974 // left >= 0x80 -- always true, but more bytes to come
3975 mov2w (AOP(left), size);
3976 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3979 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3980 mov2w (AOP(left), size);
3981 emitpcode (POC_ADDLW, popGetLit (0x80));
3982 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3985 pCodeOp *pctemp = popGetTempReg();
3986 mov2w (AOP(left), size);
3987 emitpcode (POC_ADDLW, popGetLit (0x80));
3988 emitpcode (POC_MOVWF, pctemp);
3989 mov2w (AOP(right), size);
3990 emitpcode (POC_ADDLW, popGetLit (0x80));
3991 emitpcode (POC_SUBFW, pctemp);
3992 popReleaseTempReg(pctemp);
3996 // compare remaining bytes (treat as unsigned case from above)
3997 templbl = newiTempLabel ( NULL );
4000 //DEBUGpc ("comparing bytes at offset %d", offs);
4002 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4003 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4004 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4006 emitpLabel (templbl->key);
4007 goto result_in_carry;
4011 /****************************************************
4012 * now CARRY contains the result of the comparison: *
4013 * SUBWF sets CARRY iff *
4014 * F-W >= 0 <==> F >= W <==> !(F < W) *
4015 * (F=left, W=right) *
4016 ****************************************************/
4020 // value will be used in the following genSkipc()
4021 rIfx.condition ^= 1;
4024 correct_result_in_carry:
4026 // assign result to variable (if neccessary)
4027 if (result && AOP_TYPE(result) != AOP_CRY) {
4028 //DEBUGpc ("assign result");
4029 size = AOP_SIZE(result);
4031 emitpcode (POC_CLRF, popGet (AOP(result), size));
4033 if (invert_result) {
4035 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4037 emitpcode (POC_RLF, popGet (AOP(result), 0));
4041 // perform conditional jump
4043 //DEBUGpc ("generate control flow");
4051 /* OLD VERSION -- BUGGY, DO NOT USE */
4053 /*-----------------------------------------------------------------*/
4054 /* genCmp :- greater or less than comparison */
4055 /*-----------------------------------------------------------------*/
4056 static void genCmp (operand *left,operand *right,
4057 operand *result, iCode *ifx, int sign)
4059 int size; //, offset = 0 ;
4060 unsigned long lit = 0L,i = 0;
4061 resolvedIfx rFalseIfx;
4062 // resolvedIfx rTrueIfx;
4066 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4069 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4070 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4074 resolveIfx(&rFalseIfx,ifx);
4075 truelbl = newiTempLabel(NULL);
4076 size = max(AOP_SIZE(left),AOP_SIZE(right));
4078 DEBUGpic14_AopType(__LINE__,left,right,result);
4082 /* if literal is on the right then swap with left */
4083 if ((AOP_TYPE(right) == AOP_LIT)) {
4084 operand *tmp = right ;
4085 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4086 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4089 lit = (lit - 1) & mask;
4092 rFalseIfx.condition ^= 1;
4095 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4096 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4100 //if(IC_TRUE(ifx) == NULL)
4101 /* if left & right are bit variables */
4102 if (AOP_TYPE(left) == AOP_CRY &&
4103 AOP_TYPE(right) == AOP_CRY ) {
4104 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4105 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4107 /* subtract right from left if at the
4108 end the carry flag is set then we know that
4109 left is greater than right */
4111 symbol *lbl = newiTempLabel(NULL);
4114 if(AOP_TYPE(right) == AOP_LIT) {
4116 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4118 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4125 genSkipCond(&rFalseIfx,left,size-1,7);
4127 /* no need to compare to 0...*/
4128 /* NOTE: this is a de-generate compare that most certainly
4129 * creates some dead code. */
4130 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4132 if(ifx) ifx->generated = 1;
4139 //i = (lit >> (size*8)) & 0xff;
4140 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4142 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4144 i = ((0-lit) & 0xff);
4147 /* lit is 0x7f, all signed chars are less than
4148 * this except for 0x7f itself */
4149 emitpcode(POC_XORLW, popGetLit(0x7f));
4150 genSkipz2(&rFalseIfx,0);
4152 emitpcode(POC_ADDLW, popGetLit(0x80));
4153 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4154 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4159 genSkipz2(&rFalseIfx,1);
4161 emitpcode(POC_ADDLW, popGetLit(i));
4162 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4166 if(ifx) ifx->generated = 1;
4170 /* chars are out of the way. now do ints and longs */
4173 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4180 genSkipCond(&rFalseIfx,left,size,7);
4181 if(ifx) ifx->generated = 1;
4186 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4188 //rFalseIfx.condition ^= 1;
4189 //genSkipCond(&rFalseIfx,left,size,7);
4190 //rFalseIfx.condition ^= 1;
4192 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4193 if(rFalseIfx.condition)
4194 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4196 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4198 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4199 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4200 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4203 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4205 if(rFalseIfx.condition) {
4207 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4213 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4214 emitpLabel(truelbl->key);
4215 if(ifx) ifx->generated = 1;
4222 if( (lit & 0xff) == 0) {
4223 /* lower byte is zero */
4224 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4225 i = ((lit >> 8) & 0xff) ^0x80;
4226 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4227 emitpcode(POC_ADDLW, popGetLit( 0x80));
4228 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4229 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4232 if(ifx) ifx->generated = 1;
4237 /* Special cases for signed longs */
4238 if( (lit & 0xffffff) == 0) {
4239 /* lower byte is zero */
4240 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4241 i = ((lit >> 8*3) & 0xff) ^0x80;
4242 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4243 emitpcode(POC_ADDLW, popGetLit( 0x80));
4244 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4245 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4248 if(ifx) ifx->generated = 1;
4256 if(lit & (0x80 << (size*8))) {
4257 /* lit is negative */
4258 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4260 //genSkipCond(&rFalseIfx,left,size,7);
4262 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4264 if(rFalseIfx.condition)
4265 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4267 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4271 /* lit is positive */
4272 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4273 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4274 if(rFalseIfx.condition)
4275 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4277 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4281 /* There are no more special cases, so perform a general compare */
4283 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4284 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4288 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4290 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4292 //rFalseIfx.condition ^= 1;
4293 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4295 emitpLabel(truelbl->key);
4297 if(ifx) ifx->generated = 1;
4304 /* sign is out of the way. So now do an unsigned compare */
4305 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4308 /* General case - compare to an unsigned literal on the right.*/
4310 i = (lit >> (size*8)) & 0xff;
4311 emitpcode(POC_MOVLW, popGetLit(i));
4312 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4314 i = (lit >> (size*8)) & 0xff;
4317 emitpcode(POC_MOVLW, popGetLit(i));
4319 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4321 /* this byte of the lit is zero,
4322 *if it's not the last then OR in the variable */
4324 emitpcode(POC_IORFW, popGet(AOP(left),size));
4329 emitpLabel(lbl->key);
4330 //if(emitFinalCheck)
4331 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4333 emitpLabel(truelbl->key);
4335 if(ifx) ifx->generated = 1;
4342 if(AOP_TYPE(left) == AOP_LIT) {
4343 //symbol *lbl = newiTempLabel(NULL);
4345 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4348 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4351 if((lit == 0) && (sign == 0)){
4354 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4356 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4358 genSkipz2(&rFalseIfx,0);
4359 if(ifx) ifx->generated = 1;
4366 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4367 /* degenerate compare can never be true */
4368 if(rFalseIfx.condition == 0)
4369 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4371 if(ifx) ifx->generated = 1;
4376 /* signed comparisons to a literal byte */
4378 int lp1 = (lit+1) & 0xff;
4380 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4383 rFalseIfx.condition ^= 1;
4384 genSkipCond(&rFalseIfx,right,0,7);
4387 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4388 emitpcode(POC_XORLW, popGetLit(0x7f));
4389 genSkipz2(&rFalseIfx,1);
4392 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4393 emitpcode(POC_ADDLW, popGetLit(0x80));
4394 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4395 rFalseIfx.condition ^= 1;
4396 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4399 if(ifx) ifx->generated = 1;
4401 /* unsigned comparisons to a literal byte */
4403 switch(lit & 0xff ) {
4405 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4406 genSkipz2(&rFalseIfx,0);
4407 if(ifx) ifx->generated = 1;
4410 genSkipCond(&rFalseIfx,right,0,7);
4411 if(ifx) ifx->generated = 1;
4415 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4416 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4417 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4418 rFalseIfx.condition ^= 1;
4419 if (AOP_TYPE(result) == AOP_CRY) {
4420 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4421 if(ifx) ifx->generated = 1;
4423 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4424 emitpcode(POC_CLRF, popGet(AOP(result),0));
4425 emitpcode(POC_RLF, popGet(AOP(result),0));
4426 emitpcode(POC_MOVLW, popGetLit(0x01));
4427 emitpcode(POC_XORWF, popGet(AOP(result),0));
4438 /* Size is greater than 1 */
4446 /* this means lit = 0xffffffff, or -1 */
4449 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4450 rFalseIfx.condition ^= 1;
4451 genSkipCond(&rFalseIfx,right,size,7);
4452 if(ifx) ifx->generated = 1;
4459 if(rFalseIfx.condition) {
4460 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4461 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4464 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4466 emitpcode(POC_IORFW, popGet(AOP(right),size));
4470 if(rFalseIfx.condition) {
4471 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4472 emitpLabel(truelbl->key);
4474 rFalseIfx.condition ^= 1;
4475 genSkipCond(&rFalseIfx,right,s,7);
4478 if(ifx) ifx->generated = 1;
4482 if((size == 1) && (0 == (lp1&0xff))) {
4483 /* lower byte of signed word is zero */
4484 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4485 i = ((lp1 >> 8) & 0xff) ^0x80;
4486 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4487 emitpcode(POC_ADDLW, popGetLit( 0x80));
4488 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4489 rFalseIfx.condition ^= 1;
4490 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4493 if(ifx) ifx->generated = 1;
4497 if(lit & (0x80 << (size*8))) {
4498 /* Lit is less than zero */
4499 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4500 //rFalseIfx.condition ^= 1;
4501 //genSkipCond(&rFalseIfx,left,size,7);
4502 //rFalseIfx.condition ^= 1;
4503 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4504 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4506 if(rFalseIfx.condition)
4507 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4509 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4513 /* Lit is greater than or equal to zero */
4514 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4515 //rFalseIfx.condition ^= 1;
4516 //genSkipCond(&rFalseIfx,right,size,7);
4517 //rFalseIfx.condition ^= 1;
4519 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4520 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4522 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4523 if(rFalseIfx.condition)
4524 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4526 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4531 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4532 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4536 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4538 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4540 rFalseIfx.condition ^= 1;
4541 //rFalseIfx.condition = 1;
4542 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4544 emitpLabel(truelbl->key);
4546 if(ifx) ifx->generated = 1;
4551 /* compare word or long to an unsigned literal on the right.*/
4556 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4559 break; /* handled above */
4562 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4564 emitpcode(POC_IORFW, popGet(AOP(right),size));
4565 genSkipz2(&rFalseIfx,0);
4569 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4571 emitpcode(POC_IORFW, popGet(AOP(right),size));
4574 if(rFalseIfx.condition)
4575 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4577 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4580 emitpcode(POC_MOVLW, popGetLit(lit+1));
4581 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4583 rFalseIfx.condition ^= 1;
4584 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4587 emitpLabel(truelbl->key);
4589 if(ifx) ifx->generated = 1;
4595 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4596 i = (lit >> (size*8)) & 0xff;
4598 emitpcode(POC_MOVLW, popGetLit(i));
4599 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4602 i = (lit >> (size*8)) & 0xff;
4605 emitpcode(POC_MOVLW, popGetLit(i));
4607 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4609 /* this byte of the lit is zero,
4610 *if it's not the last then OR in the variable */
4612 emitpcode(POC_IORFW, popGet(AOP(right),size));
4617 emitpLabel(lbl->key);
4619 rFalseIfx.condition ^= 1;
4620 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4624 emitpLabel(truelbl->key);
4625 if(ifx) ifx->generated = 1;
4629 /* Compare two variables */
4631 DEBUGpic14_emitcode(";sign","%d",sign);
4635 /* Sigh. thus sucks... */
4637 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4638 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4639 emitpcode(POC_MOVLW, popGetLit(0x80));
4640 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4641 emitpcode(POC_XORFW, popGet(AOP(right),size));
4642 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4644 /* Signed char comparison */
4645 /* Special thanks to Nikolai Golovchenko for this snippet */
4646 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4647 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4648 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4649 emitpcode(POC_XORFW, popGet(AOP(left),0));
4650 emitpcode(POC_XORFW, popGet(AOP(right),0));
4651 emitpcode(POC_ADDLW, popGetLit(0x80));
4653 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4654 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4656 if(ifx) ifx->generated = 1;
4662 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4663 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4667 /* The rest of the bytes of a multi-byte compare */
4671 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4674 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4675 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4680 emitpLabel(lbl->key);
4682 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4683 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4684 (AOP_TYPE(result) == AOP_REG)) {
4685 emitpcode(POC_CLRF, popGet(AOP(result),0));
4686 emitpcode(POC_RLF, popGet(AOP(result),0));
4688 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4690 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4691 if(ifx) ifx->generated = 1;
4698 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4699 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4700 pic14_outBitC(result);
4702 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4703 /* if the result is used in the next
4704 ifx conditional branch then generate
4705 code a little differently */
4707 genIfxJump (ifx,"c");
4709 pic14_outBitC(result);
4710 /* leave the result in acc */
4716 /*-----------------------------------------------------------------*/
4717 /* genCmpGt :- greater than comparison */
4718 /*-----------------------------------------------------------------*/
4719 static void genCmpGt (iCode *ic, iCode *ifx)
4721 operand *left, *right, *result;
4722 sym_link *letype , *retype;
4726 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4728 right= IC_RIGHT(ic);
4729 result = IC_RESULT(ic);
4731 letype = getSpec(operandType(left));
4732 retype =getSpec(operandType(right));
4733 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4734 /* assign the amsops */
4735 aopOp (left,ic,FALSE);
4736 aopOp (right,ic,FALSE);
4737 aopOp (result,ic,TRUE);
4739 genCmp(right, left, result, ifx, sign);
4741 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4742 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4743 freeAsmop(result,NULL,ic,TRUE);
4746 /*-----------------------------------------------------------------*/
4747 /* genCmpLt - less than comparisons */
4748 /*-----------------------------------------------------------------*/
4749 static void genCmpLt (iCode *ic, iCode *ifx)
4751 operand *left, *right, *result;
4752 sym_link *letype , *retype;
4756 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4758 right= IC_RIGHT(ic);
4759 result = IC_RESULT(ic);
4761 letype = getSpec(operandType(left));
4762 retype =getSpec(operandType(right));
4763 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4765 /* assign the amsops */
4766 aopOp (left,ic,FALSE);
4767 aopOp (right,ic,FALSE);
4768 aopOp (result,ic,TRUE);
4770 genCmp(left, right, result, ifx, sign);
4772 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4773 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4774 freeAsmop(result,NULL,ic,TRUE);
4777 /*-----------------------------------------------------------------*/
4778 /* genc16bit2lit - compare a 16 bit value to a literal */
4779 /*-----------------------------------------------------------------*/
4780 static void genc16bit2lit(operand *op, int lit, int offset)
4785 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4786 if( (lit&0xff) == 0)
4791 switch( BYTEofLONG(lit,i)) {
4793 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4796 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4799 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4802 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4803 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4808 switch( BYTEofLONG(lit,i)) {
4810 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4814 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4818 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4821 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4823 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4829 /*-----------------------------------------------------------------*/
4830 /* gencjneshort - compare and jump if not equal */
4831 /*-----------------------------------------------------------------*/
4832 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4834 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4839 //unsigned long lit = 0L;
4841 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4842 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4845 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4846 DEBUGpic14_AopType(__LINE__,left,right,result);
4848 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4849 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4850 if (AOP_SIZE(result)) {
4851 for (offset = 0; offset < AOP_SIZE(result); offset++)
4852 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4855 assert (AOP_SIZE(left) == AOP_SIZE(right));
4856 //resolveIfx(&rIfx,ifx);
4857 lbl = newiTempLabel (NULL);
4860 mov2w (AOP(right),size);
4861 emitpcode (POC_XORFW, popGet (AOP(left), size));
4865 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4868 emitpLabel (lbl->key);
4869 if (AOP_SIZE(result)) {
4871 emitpcode (POC_INCF, popGet (AOP(result), 0));
4874 genSkipz (ifx, NULL != IC_TRUE(ifx));
4881 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4882 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4883 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4884 for (offset=0; offset < AOP_SIZE(result); offset++)
4886 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4891 /* if the left side is a literal or
4892 if the right is in a pointer register and left
4894 if ((AOP_TYPE(left) == AOP_LIT) ||
4895 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4900 if(AOP_TYPE(right) == AOP_LIT)
4901 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4903 /* if the right side is a literal then anything goes */
4904 if (AOP_TYPE(right) == AOP_LIT &&
4905 AOP_TYPE(left) != AOP_DIR ) {
4908 genc16bit2lit(left, lit, 0);
4910 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4916 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4917 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4919 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4923 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4931 /* if the right side is in a register or in direct space or
4932 if the left is a pointer register & right is not */
4933 else if (AOP_TYPE(right) == AOP_REG ||
4934 AOP_TYPE(right) == AOP_DIR ||
4935 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4936 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4937 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4938 int lbl_key = lbl->key;
4941 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4942 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4943 __FUNCTION__,__LINE__);
4947 /* switch(size) { */
4949 /* genc16bit2lit(left, lit, 0); */
4951 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4957 if((AOP_TYPE(left) == AOP_DIR) &&
4958 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4960 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4961 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4963 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4965 switch (lit & 0xff) {
4967 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4970 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4971 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4972 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4976 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4977 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4978 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4979 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4983 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4984 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4989 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4992 if(AOP_TYPE(result) == AOP_CRY) {
4993 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4998 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5000 /* fix me. probably need to check result size too */
5001 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5006 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5016 } else if(AOP_TYPE(right) == AOP_REG &&
5017 AOP_TYPE(left) != AOP_DIR){
5021 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5022 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5023 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5028 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5033 /* right is a pointer reg need both a & b */
5036 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5038 pic14_emitcode("mov","b,%s",l);
5039 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5040 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5045 emitpcode(POC_INCF,popGet(AOP(result),0));
5047 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5049 emitpLabel(lbl->key);
5051 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5059 /*-----------------------------------------------------------------*/
5060 /* gencjne - compare and jump if not equal */
5061 /*-----------------------------------------------------------------*/
5062 static void gencjne(operand *left, operand *right, iCode *ifx)
5064 symbol *tlbl = newiTempLabel(NULL);
5066 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5067 gencjneshort(left, right, lbl);
5069 pic14_emitcode("mov","a,%s",one);
5070 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5071 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5072 pic14_emitcode("clr","a");
5073 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5075 emitpLabel(lbl->key);
5076 emitpLabel(tlbl->key);
5081 /*-----------------------------------------------------------------*/
5082 /* genCmpEq - generates code for equal to */
5083 /*-----------------------------------------------------------------*/
5084 static void genCmpEq (iCode *ic, iCode *ifx)
5086 operand *left, *right, *result;
5087 unsigned long lit = 0L;
5091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5094 DEBUGpic14_emitcode ("; ifx is non-null","");
5096 DEBUGpic14_emitcode ("; ifx is null","");
5098 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5099 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5100 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5102 size = max(AOP_SIZE(left),AOP_SIZE(right));
5104 DEBUGpic14_AopType(__LINE__,left,right,result);
5106 /* if literal, literal on the right or
5107 if the right is in a pointer register and left
5109 if (aop_isLitLike (AOP(IC_LEFT(ic)))
5110 || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5111 operand *tmp = right ;
5117 if(ifx && !AOP_SIZE(result)){
5119 /* if they are both bit variables */
5120 if (AOP_TYPE(left) == AOP_CRY &&
5121 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5122 if(AOP_TYPE(right) == AOP_LIT){
5123 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5125 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5126 pic14_emitcode("cpl","c");
5127 } else if(lit == 1L) {
5128 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5130 pic14_emitcode("clr","c");
5132 /* AOP_TYPE(right) == AOP_CRY */
5134 symbol *lbl = newiTempLabel(NULL);
5135 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5136 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5137 pic14_emitcode("cpl","c");
5138 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5140 /* if true label then we jump if condition
5142 tlbl = newiTempLabel(NULL);
5143 if ( IC_TRUE(ifx) ) {
5144 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
5145 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5147 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
5148 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5150 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5153 /* left and right are both bit variables, result is carry */
5156 resolveIfx(&rIfx,ifx);
5158 emitpcode(POC_MOVLW,popGet(AOP(left),0));
5159 emitpcode(POC_ANDFW,popGet(AOP(left),0));
5160 emitpcode(POC_BTFSC,popGet(AOP(right),0));
5161 emitpcode(POC_ANDLW,popGet(AOP(left),0));
5166 /* They're not both bit variables. Is the right a literal? */
5167 if(AOP_TYPE(right) == AOP_LIT) {
5168 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5173 switch(lit & 0xff) {
5175 if ( IC_TRUE(ifx) ) {
5176 emitpcode(POC_DECFW,popGet(AOP(left),offset));
5178 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5180 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5181 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5185 if ( IC_TRUE(ifx) ) {
5186 emitpcode(POC_INCFW,popGet(AOP(left),offset));
5188 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5190 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5191 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5195 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5197 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5202 /* end of size == 1 */
5206 genc16bit2lit(left,lit,offset);
5209 /* end of size == 2 */
5214 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5215 emitpcode(POC_IORFW,popGet(AOP(left),1));
5216 emitpcode(POC_IORFW,popGet(AOP(left),2));
5217 emitpcode(POC_IORFW,popGet(AOP(left),3));
5221 /* search for patterns that can be optimized */
5223 genc16bit2lit(left,lit,0);
5226 genSkipz(ifx,IC_TRUE(ifx) == NULL);
5228 genc16bit2lit(left,lit,2);
5230 emitpcode(POC_IORFW,popGet(AOP(left),2));
5231 emitpcode(POC_IORFW,popGet(AOP(left),3));
5244 } else if(AOP_TYPE(right) == AOP_CRY ) {
5245 /* we know the left is not a bit, but that the right is */
5246 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5247 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5248 popGet(AOP(right),offset));
5249 emitpcode(POC_XORLW,popGetLit(1));
5251 /* if the two are equal, then W will be 0 and the Z bit is set
5252 * we could test Z now, or go ahead and check the high order bytes if
5253 * the variable we're comparing is larger than a byte. */
5256 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5258 if ( IC_TRUE(ifx) ) {
5260 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5261 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5264 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5265 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5269 /* They're both variables that are larger than bits */
5272 tlbl = newiTempLabel(NULL);
5275 mov2w (AOP(right),offset); /* right might be litLike() */
5276 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5278 if ( IC_TRUE(ifx) ) {
5281 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5282 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5285 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5286 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5290 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5291 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5295 if(s>1 && IC_TRUE(ifx)) {
5296 emitpLabel(tlbl->key);
5297 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5301 /* mark the icode as generated */
5306 /* if they are both bit variables */
5307 if (AOP_TYPE(left) == AOP_CRY &&
5308 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5309 if(AOP_TYPE(right) == AOP_LIT){
5310 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5312 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5313 pic14_emitcode("cpl","c");
5314 } else if(lit == 1L) {
5315 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5317 pic14_emitcode("clr","c");
5319 /* AOP_TYPE(right) == AOP_CRY */
5321 symbol *lbl = newiTempLabel(NULL);
5322 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5323 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5324 pic14_emitcode("cpl","c");
5325 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5328 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5329 pic14_outBitC(result);
5333 genIfxJump (ifx,"c");
5336 /* if the result is used in an arithmetic operation
5337 then put the result in place */
5338 pic14_outBitC(result);
5341 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5342 gencjne(left,right,result,ifx);
5345 gencjne(left,right,newiTempLabel(NULL));
5347 if(IC_TRUE(ifx)->key)
5348 gencjne(left,right,IC_TRUE(ifx)->key);
5350 gencjne(left,right,IC_FALSE(ifx)->key);
5354 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5355 aopPut(AOP(result),"a",0);
5360 genIfxJump (ifx,"a");
5364 /* if the result is used in an arithmetic operation
5365 then put the result in place */
5367 if (AOP_TYPE(result) != AOP_CRY)
5368 pic14_outAcc(result);
5370 /* leave the result in acc */
5374 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5375 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5376 freeAsmop(result,NULL,ic,TRUE);
5379 /*-----------------------------------------------------------------*/
5380 /* ifxForOp - returns the icode containing the ifx for operand */
5381 /*-----------------------------------------------------------------*/
5382 static iCode *ifxForOp ( operand *op, iCode *ic )
5385 /* if true symbol then needs to be assigned */
5386 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5387 if (IS_TRUE_SYMOP(op))
5390 /* if this has register type condition and
5391 the next instruction is ifx with the same operand
5392 and live to of the operand is upto the ifx only then */
5394 ic->next->op == IFX &&
5395 IC_COND(ic->next)->key == op->key &&
5396 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5400 ic->next->op == IFX &&
5401 IC_COND(ic->next)->key == op->key) {
5402 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5406 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5408 ic->next->op == IFX)
5409 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5412 ic->next->op == IFX &&
5413 IC_COND(ic->next)->key == op->key) {
5414 DEBUGpic14_emitcode ("; "," key is okay");
5415 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5416 OP_SYMBOL(op)->liveTo,
5423 /*-----------------------------------------------------------------*/
5424 /* genAndOp - for && operation */
5425 /*-----------------------------------------------------------------*/
5426 static void genAndOp (iCode *ic)
5428 operand *left,*right, *result;
5432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5433 /* note here that && operations that are in an
5434 if statement are taken away by backPatchLabels
5435 only those used in arthmetic operations remain */
5436 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5437 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5438 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5440 DEBUGpic14_AopType(__LINE__,left,right,result);
5442 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5443 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5444 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5446 /* if both are bit variables */
5447 /* if (AOP_TYPE(left) == AOP_CRY && */
5448 /* AOP_TYPE(right) == AOP_CRY ) { */
5449 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5450 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5451 /* pic14_outBitC(result); */
5453 /* tlbl = newiTempLabel(NULL); */
5454 /* pic14_toBoolean(left); */
5455 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5456 /* pic14_toBoolean(right); */
5457 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5458 /* pic14_outBitAcc(result); */
5461 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5462 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5463 freeAsmop(result,NULL,ic,TRUE);
5467 /*-----------------------------------------------------------------*/
5468 /* genOrOp - for || operation */
5469 /*-----------------------------------------------------------------*/
5472 modified this code, but it doesn't appear to ever get called
5475 static void genOrOp (iCode *ic)
5477 operand *left,*right, *result;
5480 /* note here that || operations that are in an
5481 if statement are taken away by backPatchLabels
5482 only those used in arthmetic operations remain */
5484 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5485 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5486 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5487 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5489 DEBUGpic14_AopType(__LINE__,left,right,result);
5491 /* if both are bit variables */
5492 if (AOP_TYPE(left) == AOP_CRY &&
5493 AOP_TYPE(right) == AOP_CRY ) {
5494 pic14_emitcode("clrc","");
5495 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5496 AOP(left)->aopu.aop_dir,
5497 AOP(left)->aopu.aop_dir);
5498 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5499 AOP(right)->aopu.aop_dir,
5500 AOP(right)->aopu.aop_dir);
5501 pic14_emitcode("setc","");
5504 tlbl = newiTempLabel(NULL);
5505 pic14_toBoolean(left);
5507 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5508 pic14_toBoolean(right);
5509 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5511 pic14_outBitAcc(result);
5514 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5515 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5516 freeAsmop(result,NULL,ic,TRUE);
5519 /*-----------------------------------------------------------------*/
5520 /* isLiteralBit - test if lit == 2^n */
5521 /*-----------------------------------------------------------------*/
5522 static int isLiteralBit(unsigned long lit)
5524 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5525 0x100L,0x200L,0x400L,0x800L,
5526 0x1000L,0x2000L,0x4000L,0x8000L,
5527 0x10000L,0x20000L,0x40000L,0x80000L,
5528 0x100000L,0x200000L,0x400000L,0x800000L,
5529 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5530 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5534 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5535 for(idx = 0; idx < 32; idx++)
5541 /*-----------------------------------------------------------------*/
5542 /* continueIfTrue - */
5543 /*-----------------------------------------------------------------*/
5544 static void continueIfTrue (iCode *ic)
5547 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5549 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5553 /*-----------------------------------------------------------------*/
5555 /*-----------------------------------------------------------------*/
5556 static void jumpIfTrue (iCode *ic)
5559 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5561 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5565 /*-----------------------------------------------------------------*/
5566 /* jmpTrueOrFalse - */
5567 /*-----------------------------------------------------------------*/
5568 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5571 // ugly but optimized by peephole
5572 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5574 symbol *nlbl = newiTempLabel(NULL);
5575 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5576 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5577 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5578 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5581 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5582 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5587 /*-----------------------------------------------------------------*/
5588 /* genAnd - code for and */
5589 /*-----------------------------------------------------------------*/
5590 static void genAnd (iCode *ic, iCode *ifx)
5592 operand *left, *right, *result;
5594 unsigned long lit = 0L;
5599 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5600 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5601 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5602 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5604 resolveIfx(&rIfx,ifx);
5606 /* if left is a literal & right is not then exchange them */
5607 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5608 AOP_NEEDSACC(left)) {
5609 operand *tmp = right ;
5614 /* if result = right then exchange them */
5615 if(pic14_sameRegs(AOP(result),AOP(right))){
5616 operand *tmp = right ;
5621 /* if right is bit then exchange them */
5622 if (AOP_TYPE(right) == AOP_CRY &&
5623 AOP_TYPE(left) != AOP_CRY){
5624 operand *tmp = right ;
5628 if(AOP_TYPE(right) == AOP_LIT)
5629 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5631 size = AOP_SIZE(result);
5633 DEBUGpic14_AopType(__LINE__,left,right,result);
5636 // result = bit & yy;
5637 if (AOP_TYPE(left) == AOP_CRY){
5638 // c = bit & literal;
5639 if(AOP_TYPE(right) == AOP_LIT){
5641 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5644 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5647 if(size && (AOP_TYPE(result) == AOP_CRY)){
5648 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5651 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5655 pic14_emitcode("clr","c");
5658 if (AOP_TYPE(right) == AOP_CRY){
5660 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5661 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5664 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5666 pic14_emitcode("rrc","a");
5667 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5673 pic14_outBitC(result);
5675 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5676 genIfxJump(ifx, "c");
5680 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5681 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5682 if((AOP_TYPE(right) == AOP_LIT) &&
5683 (AOP_TYPE(result) == AOP_CRY) &&
5684 (AOP_TYPE(left) != AOP_CRY)){
5685 int posbit = isLiteralBit(lit);
5689 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5692 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5697 while (posbit > 7) {
5701 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5702 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5703 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5710 symbol *tlbl = newiTempLabel(NULL);
5711 int sizel = AOP_SIZE(left);
5713 pic14_emitcode("setb","c");
5715 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5716 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5718 if((posbit = isLiteralBit(bytelit)) != 0)
5719 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5721 if(bytelit != 0x0FFL)
5722 pic14_emitcode("anl","a,%s",
5723 aopGet(AOP(right),offset,FALSE,TRUE));
5724 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5729 // bit = left & literal
5731 pic14_emitcode("clr","c");
5732 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5734 // if(left & literal)
5737 jmpTrueOrFalse(ifx, tlbl);
5741 pic14_outBitC(result);
5745 /* if left is same as result */
5746 if(pic14_sameRegs(AOP(result),AOP(left))){
5748 for(;size--; offset++,lit>>=8) {
5749 if(AOP_TYPE(right) == AOP_LIT){
5750 switch(lit & 0xff) {
5752 /* and'ing with 0 has clears the result */
5753 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5756 /* and'ing with 0xff is a nop when the result and left are the same */
5761 int p = my_powof2( (~lit) & 0xff );
5763 /* only one bit is set in the literal, so use a bcf instruction */
5764 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5767 if(know_W != (int)(lit&0xff))
5768 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5770 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5775 if (AOP_TYPE(left) == AOP_ACC) {
5776 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5778 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5779 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5786 // left & result in different registers
5787 if(AOP_TYPE(result) == AOP_CRY){
5789 // if(size), result in bit
5790 // if(!size && ifx), conditional oper: if(left & right)
5791 symbol *tlbl = newiTempLabel(NULL);
5792 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5794 pic14_emitcode("setb","c");
5796 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5797 pic14_emitcode("anl","a,%s",
5798 aopGet(AOP(left),offset,FALSE,FALSE));
5799 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5804 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5805 pic14_outBitC(result);
5807 jmpTrueOrFalse(ifx, tlbl);
5809 for(;(size--);offset++) {
5811 // result = left & right
5812 if(AOP_TYPE(right) == AOP_LIT){
5813 int t = (lit >> (offset*8)) & 0x0FFL;
5816 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5819 if(AOP_TYPE(left) != AOP_ACC) {
5820 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5822 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5825 if(AOP_TYPE(left) == AOP_ACC) {
5826 emitpcode(POC_ANDLW, popGetLit(t));
5828 emitpcode(POC_MOVLW, popGetLit(t));
5829 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5831 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5836 if (AOP_TYPE(left) == AOP_ACC) {
5837 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5839 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5840 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5842 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5848 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5849 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5850 freeAsmop(result,NULL,ic,TRUE);
5853 /*-----------------------------------------------------------------*/
5854 /* genOr - code for or */
5855 /*-----------------------------------------------------------------*/
5856 static void genOr (iCode *ic, iCode *ifx)
5858 operand *left, *right, *result;
5860 unsigned long lit = 0L;
5863 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5865 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5866 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5867 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5869 DEBUGpic14_AopType(__LINE__,left,right,result);
5871 /* if left is a literal & right is not then exchange them */
5872 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5873 AOP_NEEDSACC(left)) {
5874 operand *tmp = right ;
5879 /* if result = right then exchange them */
5880 if(pic14_sameRegs(AOP(result),AOP(right))){
5881 operand *tmp = right ;
5886 /* if right is bit then exchange them */
5887 if (AOP_TYPE(right) == AOP_CRY &&
5888 AOP_TYPE(left) != AOP_CRY){
5889 operand *tmp = right ;
5894 DEBUGpic14_AopType(__LINE__,left,right,result);
5896 if(AOP_TYPE(right) == AOP_LIT)
5897 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5899 size = AOP_SIZE(result);
5903 if (AOP_TYPE(left) == AOP_CRY){
5904 if(AOP_TYPE(right) == AOP_LIT){
5905 // c = bit & literal;
5907 // lit != 0 => result = 1
5908 if(AOP_TYPE(result) == AOP_CRY){
5910 emitpcode(POC_BSF, popGet(AOP(result),0));
5911 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5912 // AOP(result)->aopu.aop_dir,
5913 // AOP(result)->aopu.aop_dir);
5915 continueIfTrue(ifx);
5919 // lit == 0 => result = left
5920 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5922 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5925 if (AOP_TYPE(right) == AOP_CRY){
5926 if(pic14_sameRegs(AOP(result),AOP(left))){
5928 emitpcode(POC_BCF, popGet(AOP(result),0));
5929 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5930 emitpcode(POC_BSF, popGet(AOP(result),0));
5932 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5933 AOP(result)->aopu.aop_dir,
5934 AOP(result)->aopu.aop_dir);
5935 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5936 AOP(right)->aopu.aop_dir,
5937 AOP(right)->aopu.aop_dir);
5938 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5939 AOP(result)->aopu.aop_dir,
5940 AOP(result)->aopu.aop_dir);
5942 if( AOP_TYPE(result) == AOP_ACC) {
5943 emitpcode(POC_MOVLW, popGetLit(0));
5944 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5945 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5946 emitpcode(POC_MOVLW, popGetLit(1));
5950 emitpcode(POC_BCF, popGet(AOP(result),0));
5951 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5952 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5953 emitpcode(POC_BSF, popGet(AOP(result),0));
5955 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5956 AOP(result)->aopu.aop_dir,
5957 AOP(result)->aopu.aop_dir);
5958 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5959 AOP(right)->aopu.aop_dir,
5960 AOP(right)->aopu.aop_dir);
5961 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5962 AOP(left)->aopu.aop_dir,
5963 AOP(left)->aopu.aop_dir);
5964 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5965 AOP(result)->aopu.aop_dir,
5966 AOP(result)->aopu.aop_dir);
5971 symbol *tlbl = newiTempLabel(NULL);
5972 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5975 emitpcode(POC_BCF, popGet(AOP(result),0));
5976 if( AOP_TYPE(right) == AOP_ACC) {
5977 emitpcode(POC_IORLW, popGetLit(0));
5979 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5980 emitpcode(POC_BSF, popGet(AOP(result),0));
5985 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5986 pic14_emitcode(";XXX setb","c");
5987 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5988 AOP(left)->aopu.aop_dir,tlbl->key+100);
5989 pic14_toBoolean(right);
5990 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5991 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5992 jmpTrueOrFalse(ifx, tlbl);
5996 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6003 pic14_outBitC(result);
6005 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6006 genIfxJump(ifx, "c");
6010 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6011 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6012 if((AOP_TYPE(right) == AOP_LIT) &&
6013 (AOP_TYPE(result) == AOP_CRY) &&
6014 (AOP_TYPE(left) != AOP_CRY)){
6016 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6019 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6021 continueIfTrue(ifx);
6024 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6025 // lit = 0, result = boolean(left)
6027 pic14_emitcode(";XXX setb","c");
6028 pic14_toBoolean(right);
6030 symbol *tlbl = newiTempLabel(NULL);
6031 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6033 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6035 genIfxJump (ifx,"a");
6039 pic14_outBitC(result);
6043 /* if left is same as result */
6044 if(pic14_sameRegs(AOP(result),AOP(left))){
6046 for(;size--; offset++,lit>>=8) {
6047 if(AOP_TYPE(right) == AOP_LIT){
6048 if((lit & 0xff) == 0)
6049 /* or'ing with 0 has no effect */
6052 int p = my_powof2(lit & 0xff);
6054 /* only one bit is set in the literal, so use a bsf instruction */
6056 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6058 if(know_W != (int)(lit & 0xff))
6059 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6060 know_W = lit & 0xff;
6061 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6066 if (AOP_TYPE(left) == AOP_ACC) {
6067 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6068 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6070 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6071 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6073 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6074 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6080 // left & result in different registers
6081 if(AOP_TYPE(result) == AOP_CRY){
6083 // if(size), result in bit
6084 // if(!size && ifx), conditional oper: if(left | right)
6085 symbol *tlbl = newiTempLabel(NULL);
6086 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6087 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6091 pic14_emitcode(";XXX setb","c");
6093 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6094 pic14_emitcode(";XXX orl","a,%s",
6095 aopGet(AOP(left),offset,FALSE,FALSE));
6096 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6101 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6102 pic14_outBitC(result);
6104 jmpTrueOrFalse(ifx, tlbl);
6105 } else for(;(size--);offset++){
6107 // result = left | right
6108 if(AOP_TYPE(right) == AOP_LIT){
6109 int t = (lit >> (offset*8)) & 0x0FFL;
6112 if (AOP_TYPE(left) != AOP_ACC) {
6113 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6115 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6119 if (AOP_TYPE(left) == AOP_ACC) {
6120 emitpcode(POC_IORLW, popGetLit(t));
6122 emitpcode(POC_MOVLW, popGetLit(t));
6123 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6125 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6130 // faster than result <- left, anl result,right
6131 // and better if result is SFR
6132 if (AOP_TYPE(left) == AOP_ACC) {
6133 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6135 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6136 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6138 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6143 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6144 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6145 freeAsmop(result,NULL,ic,TRUE);
6148 /*-----------------------------------------------------------------*/
6149 /* genXor - code for xclusive or */
6150 /*-----------------------------------------------------------------*/
6151 static void genXor (iCode *ic, iCode *ifx)
6153 operand *left, *right, *result;
6155 unsigned long lit = 0L;
6158 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6160 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6161 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6162 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6164 /* if left is a literal & right is not ||
6165 if left needs acc & right does not */
6166 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6167 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6168 operand *tmp = right ;
6173 /* if result = right then exchange them */
6174 if(pic14_sameRegs(AOP(result),AOP(right))){
6175 operand *tmp = right ;
6180 /* if right is bit then exchange them */
6181 if (AOP_TYPE(right) == AOP_CRY &&
6182 AOP_TYPE(left) != AOP_CRY){
6183 operand *tmp = right ;
6187 if(AOP_TYPE(right) == AOP_LIT)
6188 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6190 size = AOP_SIZE(result);
6194 if (AOP_TYPE(left) == AOP_CRY){
6195 if(AOP_TYPE(right) == AOP_LIT){
6196 // c = bit & literal;
6198 // lit>>1 != 0 => result = 1
6199 if(AOP_TYPE(result) == AOP_CRY){
6201 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6202 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6204 continueIfTrue(ifx);
6207 pic14_emitcode("setb","c");
6211 // lit == 0, result = left
6212 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6214 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6216 // lit == 1, result = not(left)
6217 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6218 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6219 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6220 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6223 assert ( !"incomplete genXor" );
6224 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6225 pic14_emitcode("cpl","c");
6232 symbol *tlbl = newiTempLabel(NULL);
6233 if (AOP_TYPE(right) == AOP_CRY){
6235 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6238 int sizer = AOP_SIZE(right);
6240 // if val>>1 != 0, result = 1
6241 pic14_emitcode("setb","c");
6243 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6245 // test the msb of the lsb
6246 pic14_emitcode("anl","a,#0xfe");
6247 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6251 pic14_emitcode("rrc","a");
6253 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6254 pic14_emitcode("cpl","c");
6255 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6260 pic14_outBitC(result);
6262 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6263 genIfxJump(ifx, "c");
6267 if(pic14_sameRegs(AOP(result),AOP(left))){
6268 /* if left is same as result */
6269 for(;size--; offset++) {
6270 if(AOP_TYPE(right) == AOP_LIT){
6271 int t = (lit >> (offset*8)) & 0x0FFL;
6275 if (IS_AOP_PREG(left)) {
6276 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6277 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6278 aopPut(AOP(result),"a",offset);
6280 emitpcode(POC_MOVLW, popGetLit(t));
6281 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6282 pic14_emitcode("xrl","%s,%s",
6283 aopGet(AOP(left),offset,FALSE,TRUE),
6284 aopGet(AOP(right),offset,FALSE,FALSE));
6287 if (AOP_TYPE(left) == AOP_ACC)
6288 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6290 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6291 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6293 if (IS_AOP_PREG(left)) {
6294 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6295 aopPut(AOP(result),"a",offset);
6297 pic14_emitcode("xrl","%s,a",
6298 aopGet(AOP(left),offset,FALSE,TRUE));
6304 // left & result in different registers
6305 if(AOP_TYPE(result) == AOP_CRY){
6307 // if(size), result in bit
6308 // if(!size && ifx), conditional oper: if(left ^ right)
6309 symbol *tlbl = newiTempLabel(NULL);
6310 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6312 pic14_emitcode("setb","c");
6314 if((AOP_TYPE(right) == AOP_LIT) &&
6315 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6316 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6318 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6319 pic14_emitcode("xrl","a,%s",
6320 aopGet(AOP(left),offset,FALSE,FALSE));
6322 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6327 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6328 pic14_outBitC(result);
6330 jmpTrueOrFalse(ifx, tlbl);
6331 } else for(;(size--);offset++){
6333 // result = left & right
6334 if(AOP_TYPE(right) == AOP_LIT){
6335 int t = (lit >> (offset*8)) & 0x0FFL;
6338 if (AOP_TYPE(left) != AOP_ACC) {
6339 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6341 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6342 pic14_emitcode("movf","%s,w",
6343 aopGet(AOP(left),offset,FALSE,FALSE));
6344 pic14_emitcode("movwf","%s",
6345 aopGet(AOP(result),offset,FALSE,FALSE));
6348 if (AOP_TYPE(left) == AOP_ACC) {
6349 emitpcode(POC_XORLW, popGetLit(t));
6351 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6353 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6356 if (AOP_TYPE(left) == AOP_ACC) {
6357 emitpcode(POC_XORLW, popGetLit(t));
6359 emitpcode(POC_MOVLW, popGetLit(t));
6360 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6362 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6363 pic14_emitcode("movlw","0x%x",t);
6364 pic14_emitcode("xorwf","%s,w",
6365 aopGet(AOP(left),offset,FALSE,FALSE));
6366 pic14_emitcode("movwf","%s",
6367 aopGet(AOP(result),offset,FALSE,FALSE));
6373 // faster than result <- left, anl result,right
6374 // and better if result is SFR
6375 if (AOP_TYPE(left) == AOP_ACC) {
6376 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6378 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6379 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6381 if ( AOP_TYPE(result) != AOP_ACC){
6382 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6388 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6389 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6390 freeAsmop(result,NULL,ic,TRUE);
6393 /*-----------------------------------------------------------------*/
6394 /* genInline - write the inline code out */
6395 /*-----------------------------------------------------------------*/
6396 static void genInline (iCode *ic)
6398 char *buffer, *bp, *bp1;
6401 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6403 _G.inLine += (!options.asmpeep);
6405 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6406 strcpy(buffer,IC_INLINE(ic));
6408 /* emit each line as a code */
6414 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6422 /* print label, use this special format with NULL directive
6423 * to denote that the argument should not be indented with tab */
6424 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6431 if ((bp1 != bp) && *bp1)
6432 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6436 _G.inLine -= (!options.asmpeep);
6439 /*-----------------------------------------------------------------*/
6440 /* genRRC - rotate right with carry */
6441 /*-----------------------------------------------------------------*/
6442 static void genRRC (iCode *ic)
6444 operand *left , *result ;
6445 int size, offset = 0, same;
6448 /* rotate right with carry */
6450 result=IC_RESULT(ic);
6451 aopOp (left,ic,FALSE);
6452 aopOp (result,ic,FALSE);
6454 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6456 same = pic14_sameRegs(AOP(result),AOP(left));
6458 size = AOP_SIZE(result);
6460 /* get the lsb and put it into the carry */
6461 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6468 emitpcode(POC_RRF, popGet(AOP(left),offset));
6470 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6471 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6477 freeAsmop(left,NULL,ic,TRUE);
6478 freeAsmop(result,NULL,ic,TRUE);
6481 /*-----------------------------------------------------------------*/
6482 /* genRLC - generate code for rotate left with carry */
6483 /*-----------------------------------------------------------------*/
6484 static void genRLC (iCode *ic)
6486 operand *left , *result ;
6487 int size, offset = 0;
6491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6492 /* rotate right with carry */
6494 result=IC_RESULT(ic);
6495 aopOp (left,ic,FALSE);
6496 aopOp (result,ic,FALSE);
6498 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6500 same = pic14_sameRegs(AOP(result),AOP(left));
6502 /* move it to the result */
6503 size = AOP_SIZE(result);
6505 /* get the msb and put it into the carry */
6506 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6513 emitpcode(POC_RLF, popGet(AOP(left),offset));
6515 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6516 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6523 freeAsmop(left,NULL,ic,TRUE);
6524 freeAsmop(result,NULL,ic,TRUE);
6527 /*-----------------------------------------------------------------*/
6528 /* genGetHbit - generates code get highest order bit */
6529 /*-----------------------------------------------------------------*/
6530 static void genGetHbit (iCode *ic)
6532 operand *left, *result;
6534 result=IC_RESULT(ic);
6535 aopOp (left,ic,FALSE);
6536 aopOp (result,ic,FALSE);
6539 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6540 /* get the highest order byte into a */
6541 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6542 if(AOP_TYPE(result) == AOP_CRY){
6543 pic14_emitcode("rlc","a");
6544 pic14_outBitC(result);
6547 pic14_emitcode("rl","a");
6548 pic14_emitcode("anl","a,#0x01");
6549 pic14_outAcc(result);
6553 freeAsmop(left,NULL,ic,TRUE);
6554 freeAsmop(result,NULL,ic,TRUE);
6557 /*-----------------------------------------------------------------*/
6558 /* AccRol - rotate left accumulator by known count */
6559 /*-----------------------------------------------------------------*/
6560 static void AccRol (operand *op,int offset,int shCount)
6563 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6564 shCount &= 0x0007; // shCount : 0..7
6569 pic14_emitcode("rl","a");
6570 emitpcode(POC_RLF,popGet(AOP(op),offset));
6573 pic14_emitcode("rl","a");
6574 pic14_emitcode("rl","a");
6575 emitpcode(POC_RLF,popGet(AOP(op),offset));
6576 emitpcode(POC_RLF,popGet(AOP(op),offset));
6579 pic14_emitcode("swap","a");
6580 pic14_emitcode("rr","a");
6581 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6582 emitpcode(POC_RRF,popGet(AOP(op),offset));
6585 pic14_emitcode("swap","a");
6586 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6589 pic14_emitcode("swap","a");
6590 pic14_emitcode("rl","a");
6591 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6592 emitpcode(POC_RLF,popGet(AOP(op),offset));
6595 pic14_emitcode("rr","a");
6596 pic14_emitcode("rr","a");
6597 emitpcode(POC_RRF,popGet(AOP(op),offset));
6598 emitpcode(POC_RRF,popGet(AOP(op),offset));
6601 pic14_emitcode("rr","a");
6602 emitpcode(POC_RRF,popGet(AOP(op),offset));
6607 /*-----------------------------------------------------------------*/
6608 /* AccLsh - left shift accumulator by known count */
6609 /*-----------------------------------------------------------------*/
6610 static void AccLsh (operand *op,int offset,int shCount)
6613 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6618 emitpcode (POC_RLF, popGet (AOP(op), 0));
6620 /* rotate left accumulator */
6621 AccRol(op,offset,shCount);
6622 /* and kill the lower order bits */
6623 emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6624 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6629 /*-----------------------------------------------------------------*/
6630 /* AccRsh - right shift accumulator by known count */
6631 /*-----------------------------------------------------------------*/
6632 static void AccRsh (operand *op,int offset,int shCount)
6635 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6639 emitpcode (POC_RRF, popGet (AOP(op), 0));
6641 /* rotate right accumulator */
6642 AccRol(op,offset,8 - shCount);
6643 /* and kill the higher order bits */
6644 emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6645 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6651 /*-----------------------------------------------------------------*/
6652 /* AccSRsh - signed right shift accumulator by known count */
6653 /*-----------------------------------------------------------------*/
6654 static void AccSRsh (int shCount)
6657 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6660 pic14_emitcode("mov","c,acc.7");
6661 pic14_emitcode("rrc","a");
6662 } else if(shCount == 2){
6663 pic14_emitcode("mov","c,acc.7");
6664 pic14_emitcode("rrc","a");
6665 pic14_emitcode("mov","c,acc.7");
6666 pic14_emitcode("rrc","a");
6668 tlbl = newiTempLabel(NULL);
6669 /* rotate right accumulator */
6670 AccRol(8 - shCount);
6671 /* and kill the higher order bits */
6672 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6673 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6674 pic14_emitcode("orl","a,#0x%02x",
6675 (unsigned char)~SRMask[shCount]);
6676 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6681 /*-----------------------------------------------------------------*/
6682 /* shiftR1Left2Result - shift right one byte from left to result */
6683 /*-----------------------------------------------------------------*/
6684 static void shiftR1Left2ResultSigned (operand *left, int offl,
6685 operand *result, int offr,
6691 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6693 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6697 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6699 emitpcode(POC_RRF, popGet(AOP(result),offr));
6701 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6702 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6708 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6710 emitpcode(POC_RRF, popGet(AOP(result),offr));
6712 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6713 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6715 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6716 emitpcode(POC_RRF, popGet(AOP(result),offr));
6722 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6724 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6725 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6728 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6729 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6730 emitpcode(POC_ANDLW, popGetLit(0x1f));
6732 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6733 emitpcode(POC_IORLW, popGetLit(0xe0));
6735 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6739 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6740 emitpcode(POC_ANDLW, popGetLit(0x0f));
6741 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742 emitpcode(POC_IORLW, popGetLit(0xf0));
6743 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6749 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6750 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6752 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6753 emitpcode(POC_ANDLW, popGetLit(0x07));
6754 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6755 emitpcode(POC_IORLW, popGetLit(0xf8));
6756 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6761 emitpcode(POC_MOVLW, popGetLit(0x00));
6762 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6763 emitpcode(POC_MOVLW, popGetLit(0xfe));
6764 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6765 emitpcode(POC_IORLW, popGetLit(0x01));
6766 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6768 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6769 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6770 emitpcode(POC_DECF, popGet(AOP(result),offr));
6771 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6772 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6778 emitpcode(POC_MOVLW, popGetLit(0x00));
6779 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6780 emitpcode(POC_MOVLW, popGetLit(0xff));
6781 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6783 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6784 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6785 emitpcode(POC_DECF, popGet(AOP(result),offr));
6793 /*-----------------------------------------------------------------*/
6794 /* shiftR1Left2Result - shift right one byte from left to result */
6795 /*-----------------------------------------------------------------*/
6796 static void shiftR1Left2Result (operand *left, int offl,
6797 operand *result, int offr,
6798 int shCount, int sign)
6803 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6805 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6807 /* Copy the msb into the carry if signed. */
6809 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6819 emitpcode(POC_RRF, popGet(AOP(result),offr));
6821 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6822 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6828 emitpcode(POC_RRF, popGet(AOP(result),offr));
6830 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6831 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6834 emitpcode(POC_RRF, popGet(AOP(result),offr));
6839 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6841 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6842 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6845 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6846 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6847 emitpcode(POC_ANDLW, popGetLit(0x1f));
6848 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6852 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6853 emitpcode(POC_ANDLW, popGetLit(0x0f));
6854 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6858 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6859 emitpcode(POC_ANDLW, popGetLit(0x0f));
6860 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6862 emitpcode(POC_RRF, popGet(AOP(result),offr));
6867 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6868 emitpcode(POC_ANDLW, popGetLit(0x80));
6869 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6870 emitpcode(POC_RLF, popGet(AOP(result),offr));
6871 emitpcode(POC_RLF, popGet(AOP(result),offr));
6876 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6878 emitpcode(POC_RLF, popGet(AOP(result),offr));
6887 /*-----------------------------------------------------------------*/
6888 /* shiftL1Left2Result - shift left one byte from left to result */
6889 /*-----------------------------------------------------------------*/
6890 static void shiftL1Left2Result (operand *left, int offl,
6891 operand *result, int offr, int shCount)
6897 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6899 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6900 DEBUGpic14_emitcode ("; ***","same = %d",same);
6901 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6903 /* shift left accumulator */
6904 //AccLsh(shCount); // don't comment out just yet...
6905 // aopPut(AOP(result),"a",offr);
6909 /* Shift left 1 bit position */
6910 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6912 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6914 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6915 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6919 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6920 emitpcode(POC_ANDLW,popGetLit(0x7e));
6921 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6922 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6925 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6926 emitpcode(POC_ANDLW,popGetLit(0x3e));
6927 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6928 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6929 emitpcode(POC_RLF, popGet(AOP(result),offr));
6932 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6933 emitpcode(POC_ANDLW, popGetLit(0xf0));
6934 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6937 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6938 emitpcode(POC_ANDLW, popGetLit(0xf0));
6939 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6940 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6943 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6944 emitpcode(POC_ANDLW, popGetLit(0x30));
6945 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6946 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6947 emitpcode(POC_RLF, popGet(AOP(result),offr));
6950 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6951 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6952 emitpcode(POC_RRF, popGet(AOP(result),offr));
6956 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6962 /*-----------------------------------------------------------------*/
6963 /* movLeft2Result - move byte from left to result */
6964 /*-----------------------------------------------------------------*/
6965 static void movLeft2Result (operand *left, int offl,
6966 operand *result, int offr)
6970 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6971 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6972 l = aopGet(AOP(left),offl,FALSE,FALSE);
6974 if (*l == '@' && (IS_AOP_PREG(result))) {
6975 pic14_emitcode("mov","a,%s",l);
6976 aopPut(AOP(result),"a",offr);
6978 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6979 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6984 /*-----------------------------------------------------------------*/
6985 /* shiftLeft_Left2ResultLit - shift left by known count */
6986 /*-----------------------------------------------------------------*/
6988 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6990 int size, same, offr, i;
6992 size = AOP_SIZE(left);
6993 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6995 same = pic14_sameRegs (AOP(left), AOP(result));
6998 shCount = shCount & 0x07;
7004 case 0: /* takes 0 or 2N cycles (for offr==0) */
7005 if (!same || offr) {
7006 for (i=size-1; i >= 0; i--)
7007 movLeft2Result (left, i, result, offr + i);
7011 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7013 shiftLeft_Left2ResultLit (left, result, 8 * offr);
7014 shiftLeft_Left2ResultLit (result, result, shCount);
7015 return; /* prevent clearing result again */
7018 for (i=0; i < size; i++) {
7019 if (same && !offr) {
7020 emitpcode (POC_RLF, popGet (AOP(left), i));
7022 emitpcode (POC_RLFW, popGet (AOP(left), i));
7023 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7029 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7030 /* works in-place/with offr as well */
7031 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7032 emitpcode (POC_ANDLW, popGetLit (0xF0));
7033 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7035 for (i = size - 2; i >= 0; i--)
7037 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7038 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7039 emitpcode (POC_ANDLW, popGetLit (0x0F));
7040 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7041 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7045 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7046 /* works in-place/with offr as well */
7047 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7048 for (i = size-2; i >= 0; i--) {
7049 emitpcode (POC_RRFW, popGet (AOP(left), i));
7050 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7052 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7053 emitpcode (POC_RRF, popGet (AOP(result), offr));
7057 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7058 shiftLeft_Left2ResultLit (result, result, 1);
7059 return; /* prevent clearing result again */
7065 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7069 /*-----------------------------------------------------------------*/
7070 /* shiftRight_Left2ResultLit - shift right by known count */
7071 /*-----------------------------------------------------------------*/
7073 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7075 int size, same, offr, i;
7077 size = AOP_SIZE(left);
7078 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7080 same = pic14_sameRegs (AOP(left), AOP(result));
7083 shCount = shCount & 0x07;
7091 case 0: /* takes 0 or 2N cycles (for offr==0) */
7092 if (!same || offr) {
7093 for (i=0; i < size; i++)
7094 movLeft2Result (left, i + offr, result, i);
7098 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7099 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7101 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7102 shiftRight_Left2ResultLit (result, result, shCount, sign);
7103 return; /* prevent sign-extending result again */
7107 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7110 for (i = size-1; i >= 0; i--) {
7111 if (same && !offr) {
7112 emitpcode (POC_RRF, popGet (AOP(left), i));
7114 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7115 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7121 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7122 /* works in-place/with offr as well */
7123 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7124 emitpcode (POC_ANDLW, popGetLit (0x0F));
7125 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7127 for (i = 1; i < size; i++)
7129 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7130 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7131 emitpcode (POC_ANDLW, popGetLit (0xF0));
7132 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7133 emitpcode (POC_XORWF, popGet (AOP(result), i));
7138 emitpcode (POC_MOVLW, popGetLit (0xF0));
7139 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7140 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7144 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7145 /* works in-place/with offr as well */
7146 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7147 for (i = 0; i < size-1; i++) {
7148 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7149 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7151 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7153 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7156 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7161 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7162 shiftRight_Left2ResultLit (result, result, 1, sign);
7163 return; /* prevent sign extending result again */
7168 addSign (result, size, sign);
7172 /*-----------------------------------------------------------------*/
7173 /* shiftL2Left2Result - shift left two bytes from left to result */
7174 /*-----------------------------------------------------------------*/
7175 static void shiftL2Left2Result (operand *left, int offl,
7176 operand *result, int offr, int shCount)
7180 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7182 if(pic14_sameRegs(AOP(result), AOP(left))) {
7190 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7191 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7192 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7196 emitpcode(POC_RLF, popGet(AOP(result),offr));
7197 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7203 emitpcode(POC_MOVLW, popGetLit(0x0f));
7204 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7205 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7206 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7207 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7208 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7209 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7211 emitpcode(POC_RLF, popGet(AOP(result),offr));
7212 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7216 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7217 emitpcode(POC_RRF, popGet(AOP(result),offr));
7218 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7219 emitpcode(POC_RRF, popGet(AOP(result),offr));
7220 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7221 emitpcode(POC_ANDLW,popGetLit(0xc0));
7222 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7223 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7224 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7225 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7228 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7229 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7230 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7231 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7232 emitpcode(POC_RRF, popGet(AOP(result),offr));
7242 /* note, use a mov/add for the shift since the mov has a
7243 chance of getting optimized out */
7244 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7245 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7246 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7247 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7248 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7252 emitpcode(POC_RLF, popGet(AOP(result),offr));
7253 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7259 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7260 emitpcode(POC_ANDLW, popGetLit(0xF0));
7261 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7262 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7263 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7264 emitpcode(POC_ANDLW, popGetLit(0xF0));
7265 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7266 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7270 emitpcode(POC_RLF, popGet(AOP(result),offr));
7271 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7275 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7276 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7277 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7278 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7280 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7281 emitpcode(POC_RRF, popGet(AOP(result),offr));
7282 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7283 emitpcode(POC_ANDLW,popGetLit(0xc0));
7284 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7285 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7286 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7287 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7290 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7291 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7292 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7293 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7294 emitpcode(POC_RRF, popGet(AOP(result),offr));
7300 /*-----------------------------------------------------------------*/
7301 /* shiftR2Left2Result - shift right two bytes from left to result */
7302 /*-----------------------------------------------------------------*/
7303 static void shiftR2Left2Result (operand *left, int offl,
7304 operand *result, int offr,
7305 int shCount, int sign)
7310 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7311 same = pic14_sameRegs(AOP(result), AOP(left));
7313 if(same && ((offl + MSB16) == offr)){
7315 /* don't crash result[offr] */
7316 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7317 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7320 movLeft2Result(left,offl, result, offr);
7321 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7324 /* a:x >> shCount (x = lsb(result))*/
7327 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7329 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7338 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7343 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7344 emitpcode(POC_RRF,popGet(AOP(result),offr));
7346 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7347 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7348 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7349 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7354 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7357 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7358 emitpcode(POC_RRF,popGet(AOP(result),offr));
7365 emitpcode(POC_MOVLW, popGetLit(0xf0));
7366 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7367 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7369 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7370 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7371 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7372 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7374 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7375 emitpcode(POC_ANDLW, popGetLit(0x0f));
7376 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7378 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7379 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7380 emitpcode(POC_ANDLW, popGetLit(0xf0));
7381 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7382 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7386 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7387 emitpcode(POC_RRF, popGet(AOP(result),offr));
7391 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7392 emitpcode(POC_BTFSC,
7393 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7394 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7402 emitpcode(POC_RLF, popGet(AOP(result),offr));
7403 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7405 emitpcode(POC_RLF, popGet(AOP(result),offr));
7406 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7407 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7408 emitpcode(POC_ANDLW,popGetLit(0x03));
7410 emitpcode(POC_BTFSC,
7411 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7412 emitpcode(POC_IORLW,popGetLit(0xfc));
7414 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7415 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7416 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7417 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7419 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7420 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7421 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7422 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7423 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7424 emitpcode(POC_RLF, popGet(AOP(result),offr));
7425 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7426 emitpcode(POC_ANDLW,popGetLit(0x03));
7428 emitpcode(POC_BTFSC,
7429 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7430 emitpcode(POC_IORLW,popGetLit(0xfc));
7432 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7433 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7440 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7441 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7442 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7443 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7446 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7448 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7452 /*-----------------------------------------------------------------*/
7453 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7454 /*-----------------------------------------------------------------*/
7455 static void shiftLLeftOrResult (operand *left, int offl,
7456 operand *result, int offr, int shCount)
7459 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7461 /* shift left accumulator */
7462 AccLsh(left,offl,shCount);
7463 /* or with result */
7464 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7465 assert ( !"broken (modifies left, fails for left==result))" );
7468 /*-----------------------------------------------------------------*/
7469 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7470 /*-----------------------------------------------------------------*/
7471 static void shiftRLeftOrResult (operand *left, int offl,
7472 operand *result, int offr, int shCount)
7475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7477 /* shift right accumulator */
7478 AccRsh(left,offl,shCount);
7479 /* or with result */
7480 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7481 assert ( !"broken (modifies left, fails for left==result))" );
7484 /*-----------------------------------------------------------------*/
7485 /* genlshOne - left shift a one byte quantity by known count */
7486 /*-----------------------------------------------------------------*/
7487 static void genlshOne (operand *result, operand *left, int shCount)
7490 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7491 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7494 /*-----------------------------------------------------------------*/
7495 /* genlshTwo - left shift two bytes by known amount != 0 */
7496 /*-----------------------------------------------------------------*/
7497 static void genlshTwo (operand *result,operand *left, int shCount)
7502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7503 size = pic14_getDataSize(result);
7505 /* if shCount >= 8 */
7511 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7513 movLeft2Result(left, LSB, result, MSB16);
7515 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7518 /* 1 <= shCount <= 7 */
7521 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7523 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7527 /*-----------------------------------------------------------------*/
7528 /* shiftLLong - shift left one long from left to result */
7529 /* offl = LSB or MSB16 */
7530 /*-----------------------------------------------------------------*/
7531 static void shiftLLong (operand *left, operand *result, int offr )
7534 int size = AOP_SIZE(result);
7537 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7538 if(size >= LSB+offr){
7539 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7541 pic14_emitcode("add","a,acc");
7542 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7543 size >= MSB16+offr && offr != LSB )
7544 pic14_emitcode("xch","a,%s",
7545 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7547 aopPut(AOP(result),"a",LSB+offr);
7550 if(size >= MSB16+offr){
7551 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7552 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7555 pic14_emitcode("rlc","a");
7556 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7557 size >= MSB24+offr && offr != LSB)
7558 pic14_emitcode("xch","a,%s",
7559 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7561 aopPut(AOP(result),"a",MSB16+offr);
7564 if(size >= MSB24+offr){
7565 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7566 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7569 pic14_emitcode("rlc","a");
7570 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7571 size >= MSB32+offr && offr != LSB )
7572 pic14_emitcode("xch","a,%s",
7573 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7575 aopPut(AOP(result),"a",MSB24+offr);
7578 if(size > MSB32+offr){
7579 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7580 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7583 pic14_emitcode("rlc","a");
7584 aopPut(AOP(result),"a",MSB32+offr);
7587 aopPut(AOP(result),zero,LSB);
7590 /*-----------------------------------------------------------------*/
7591 /* genlshFour - shift four byte by a known amount != 0 */
7592 /*-----------------------------------------------------------------*/
7593 static void genlshFour (operand *result, operand *left, int shCount)
7598 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7599 size = AOP_SIZE(result);
7601 /* if shifting more that 3 bytes */
7602 if (shCount >= 24 ) {
7605 /* lowest order of left goes to the highest
7606 order of the destination */
7607 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7609 movLeft2Result(left, LSB, result, MSB32);
7610 aopPut(AOP(result),zero,LSB);
7611 aopPut(AOP(result),zero,MSB16);
7612 aopPut(AOP(result),zero,MSB32);
7616 /* more than two bytes */
7617 else if ( shCount >= 16 ) {
7618 /* lower order two bytes goes to higher order two bytes */
7620 /* if some more remaining */
7622 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7624 movLeft2Result(left, MSB16, result, MSB32);
7625 movLeft2Result(left, LSB, result, MSB24);
7627 aopPut(AOP(result),zero,MSB16);
7628 aopPut(AOP(result),zero,LSB);
7632 /* if more than 1 byte */
7633 else if ( shCount >= 8 ) {
7634 /* lower order three bytes goes to higher order three bytes */
7638 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7640 movLeft2Result(left, LSB, result, MSB16);
7642 else{ /* size = 4 */
7644 movLeft2Result(left, MSB24, result, MSB32);
7645 movLeft2Result(left, MSB16, result, MSB24);
7646 movLeft2Result(left, LSB, result, MSB16);
7647 aopPut(AOP(result),zero,LSB);
7649 else if(shCount == 1)
7650 shiftLLong(left, result, MSB16);
7652 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7653 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7654 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7655 aopPut(AOP(result),zero,LSB);
7660 /* 1 <= shCount <= 7 */
7661 else if(shCount <= 2){
7662 shiftLLong(left, result, LSB);
7664 shiftLLong(result, result, LSB);
7666 /* 3 <= shCount <= 7, optimize */
7668 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7669 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7670 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7676 /*-----------------------------------------------------------------*/
7677 /* genLeftShiftLiteral - left shifting by known count */
7678 /*-----------------------------------------------------------------*/
7679 static void genLeftShiftLiteral (operand *left,
7684 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7688 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7689 freeAsmop(right,NULL,ic,TRUE);
7691 aopOp(left,ic,FALSE);
7692 aopOp(result,ic,FALSE);
7694 size = getSize(operandType(result));
7697 pic14_emitcode("; shift left ","result %d, left %d",size,
7701 /* I suppose that the left size >= result size */
7704 movLeft2Result(left, size, result, size);
7708 else if(shCount >= (size * 8))
7710 aopPut(AOP(result),zero,size);
7714 genlshOne (result,left,shCount);
7719 genlshTwo (result,left,shCount);
7723 genlshFour (result,left,shCount);
7727 freeAsmop(left,NULL,ic,TRUE);
7728 freeAsmop(result,NULL,ic,TRUE);
7732 /*-----------------------------------------------------------------*
7733 * genMultiAsm - repeat assembly instruction for size of register.
7734 * if endian == 1, then the high byte (i.e base address + size of
7735 * register) is used first else the low byte is used first;
7736 *-----------------------------------------------------------------*/
7737 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7743 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7756 emitpcode(poc, popGet(AOP(reg),offset));
7761 /*-----------------------------------------------------------------*/
7762 /* genLeftShift - generates code for left shifting */
7763 /*-----------------------------------------------------------------*/
7764 static void genLeftShift (iCode *ic)
7766 operand *left,*right, *result;
7768 unsigned long lit = 0L;
7770 symbol *tlbl , *tlbl1;
7774 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7776 right = IC_RIGHT(ic);
7778 result = IC_RESULT(ic);
7780 aopOp(right,ic,FALSE);
7781 aopOp(left,ic,FALSE);
7782 aopOp(result,ic,FALSE);
7785 /* if the shift count is known then do it
7786 as efficiently as possible */
7787 if (AOP_TYPE(right) == AOP_LIT) {
7788 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7792 /* shift count is unknown then we have to form
7793 a loop get the loop count in B : Note: we take
7794 only the lower order byte since shifting
7795 more that 32 bits make no sense anyway, ( the
7796 largest size of an object can be only 32 bits ) */
7798 /* this code fails for RIGHT == RESULT */
7799 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7801 /* now move the left to the result if they are not the
7803 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7804 AOP_SIZE(result) > 1) {
7806 size = AOP_SIZE(result);
7809 l = aopGet(AOP(left),offset,FALSE,TRUE);
7810 if (*l == '@' && (IS_AOP_PREG(result))) {
7812 pic14_emitcode("mov","a,%s",l);
7813 aopPut(AOP(result),"a",offset);
7815 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7816 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7817 //aopPut(AOP(result),l,offset);
7823 if(AOP_TYPE(left) == AOP_LIT)
7824 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7826 size = AOP_SIZE(result);
7828 /* if it is only one byte then */
7830 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7831 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7832 emitpcode(POC_ANDLW, popGetLit(0xf0));
7833 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7834 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7835 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7836 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7837 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7838 emitpcode(POC_RLFW, popGet(AOP(result),0));
7839 emitpcode(POC_ANDLW, popGetLit(0xfe));
7840 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7841 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7842 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7845 tlbl = newiTempLabel(NULL);
7846 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7847 mov2w (AOP(left), 0);
7848 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7851 emitpcode(POC_COMFW, popGet(AOP(right),0));
7852 emitpcode(POC_RRF, popGet(AOP(result),0));
7853 emitpLabel(tlbl->key);
7854 emitpcode(POC_RLF, popGet(AOP(result),0));
7855 emitpcode(POC_ADDLW, popGetLit(1));
7857 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7862 if (pic14_sameRegs(AOP(left),AOP(result))) {
7864 tlbl = newiTempLabel(NULL);
7865 emitpcode(POC_COMFW, popGet(AOP(right),0));
7866 genMultiAsm(POC_RRF, result, size,1);
7867 emitpLabel(tlbl->key);
7868 genMultiAsm(POC_RLF, result, size,0);
7869 emitpcode(POC_ADDLW, popGetLit(1));
7871 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7875 //tlbl = newiTempLabel(NULL);
7877 //tlbl1 = newiTempLabel(NULL);
7879 //reAdjustPreg(AOP(result));
7881 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7882 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7883 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7885 //pic14_emitcode("add","a,acc");
7886 //aopPut(AOP(result),"a",offset++);
7888 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7890 // pic14_emitcode("rlc","a");
7891 // aopPut(AOP(result),"a",offset++);
7893 //reAdjustPreg(AOP(result));
7895 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7896 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7899 tlbl = newiTempLabel(NULL);
7900 tlbl1= newiTempLabel(NULL);
7902 size = AOP_SIZE(result);
7905 pctemp = popGetTempReg(); /* grab a temporary working register. */
7907 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7909 /* offset should be 0, 1 or 3 */
7910 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7912 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7914 emitpcode(POC_MOVWF, pctemp);
7917 emitpLabel(tlbl->key);
7920 emitpcode(POC_RLF, popGet(AOP(result),0));
7922 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7924 emitpcode(POC_DECFSZ, pctemp);
7925 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7926 emitpLabel(tlbl1->key);
7928 popReleaseTempReg(pctemp);
7932 freeAsmop (right,NULL,ic,TRUE);
7933 freeAsmop(left,NULL,ic,TRUE);
7934 freeAsmop(result,NULL,ic,TRUE);
7938 /*-----------------------------------------------------------------*/
7939 /* genrshOne - right shift a one byte quantity by known count */
7940 /*-----------------------------------------------------------------*/
7941 static void genrshOne (operand *result, operand *left,
7942 int shCount, int sign)
7945 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7946 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7949 /*-----------------------------------------------------------------*/
7950 /* genrshTwo - right shift two bytes by known amount != 0 */
7951 /*-----------------------------------------------------------------*/
7952 static void genrshTwo (operand *result,operand *left,
7953 int shCount, int sign)
7956 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7957 /* if shCount >= 8 */
7961 shiftR1Left2Result(left, MSB16, result, LSB,
7964 movLeft2Result(left, MSB16, result, LSB);
7966 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7969 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7970 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7974 /* 1 <= shCount <= 7 */
7976 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7979 /*-----------------------------------------------------------------*/
7980 /* shiftRLong - shift right one long from left to result */
7981 /* offl = LSB or MSB16 */
7982 /*-----------------------------------------------------------------*/
7983 static void shiftRLong (operand *left, int offl,
7984 operand *result, int sign)
7989 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7991 size = AOP_SIZE(left);
7992 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7995 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7999 assert (offl >= 0 && offl < size);
8001 same = pic14_sameRegs (AOP(left), AOP(result));
8003 /* perform the shift */
8006 if (same && !offl) {
8007 emitpcode (POC_RRF, popGet (AOP(result), size));
8009 emitpcode (POC_RRFW, popGet (AOP(left), size));
8010 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8014 addSign (result, AOP_SIZE(left) - offl, sign);
8017 /*-----------------------------------------------------------------*/
8018 /* genrshFour - shift four byte by a known amount != 0 */
8019 /*-----------------------------------------------------------------*/
8020 static void genrshFour (operand *result, operand *left,
8021 int shCount, int sign)
8024 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8025 /* if shifting more that 3 bytes */
8026 if(shCount >= 24 ) {
8029 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8031 movLeft2Result(left, MSB32, result, LSB);
8033 addSign(result, MSB16, sign);
8035 else if(shCount >= 16){
8038 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8040 movLeft2Result(left, MSB24, result, LSB);
8041 movLeft2Result(left, MSB32, result, MSB16);
8043 addSign(result, MSB24, sign);
8045 else if(shCount >= 8){
8048 shiftRLong(left, MSB16, result, sign);
8049 else if(shCount == 0){
8050 movLeft2Result(left, MSB16, result, LSB);
8051 movLeft2Result(left, MSB24, result, MSB16);
8052 movLeft2Result(left, MSB32, result, MSB24);
8053 addSign(result, MSB32, sign);
8056 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8057 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8058 /* the last shift is signed */
8059 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8060 addSign(result, MSB32, sign);
8063 else{ /* 1 <= shCount <= 7 */
8065 shiftRLong(left, LSB, result, sign);
8067 shiftRLong(result, LSB, result, sign);
8070 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8071 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8072 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8077 /*-----------------------------------------------------------------*/
8078 /* genRightShiftLiteral - right shifting by known count */
8079 /*-----------------------------------------------------------------*/
8080 static void genRightShiftLiteral (operand *left,
8086 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8090 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8091 freeAsmop(right,NULL,ic,TRUE);
8093 aopOp(left,ic,FALSE);
8094 aopOp(result,ic,FALSE);
8097 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8101 lsize = pic14_getDataSize(left);
8102 res_size = pic14_getDataSize(result);
8103 /* test the LEFT size !!! */
8105 /* I suppose that the left size >= result size */
8108 movLeft2Result(left, res_size, result, res_size);
8111 else if(shCount >= (lsize * 8)){
8114 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8116 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8117 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8122 emitpcode(POC_MOVLW, popGetLit(0));
8123 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8124 emitpcode(POC_MOVLW, popGetLit(0xff));
8126 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8131 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8138 genrshOne (result,left,shCount,sign);
8142 genrshTwo (result,left,shCount,sign);
8146 genrshFour (result,left,shCount,sign);
8154 freeAsmop(left,NULL,ic,TRUE);
8155 freeAsmop(result,NULL,ic,TRUE);
8159 /*-----------------------------------------------------------------*/
8160 /* genSignedRightShift - right shift of signed number */
8161 /*-----------------------------------------------------------------*/
8162 static void genSignedRightShift (iCode *ic)
8164 operand *right, *left, *result;
8167 symbol *tlbl, *tlbl1 ;
8170 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8172 /* we do it the hard way put the shift count in b
8173 and loop thru preserving the sign */
8175 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8177 right = IC_RIGHT(ic);
8179 result = IC_RESULT(ic);
8181 aopOp(right,ic,FALSE);
8182 aopOp(left,ic,FALSE);
8183 aopOp(result,ic,FALSE);
8186 if ( AOP_TYPE(right) == AOP_LIT) {
8187 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8188 //genRightShiftLiteral (left,right,result,ic,1);
8191 /* shift count is unknown then we have to form
8192 a loop get the loop count in B : Note: we take
8193 only the lower order byte since shifting
8194 more that 32 bits make no sense anyway, ( the
8195 largest size of an object can be only 32 bits ) */
8197 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8198 //pic14_emitcode("inc","b");
8199 //freeAsmop (right,NULL,ic,TRUE);
8200 //aopOp(left,ic,FALSE);
8201 //aopOp(result,ic,FALSE);
8203 /* now move the left to the result if they are not the
8205 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8206 AOP_SIZE(result) > 1) {
8208 size = AOP_SIZE(result);
8212 l = aopGet(AOP(left),offset,FALSE,TRUE);
8213 if (*l == '@' && IS_AOP_PREG(result)) {
8214 pic14_emitcode("mov","a,%s",l);
8215 aopPut(AOP(result),"a",offset);
8217 aopPut(AOP(result),l,offset);
8219 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8220 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8226 /* mov the highest order bit to OVR */
8227 tlbl = newiTempLabel(NULL);
8228 tlbl1= newiTempLabel(NULL);
8230 size = AOP_SIZE(result);
8233 pctemp = popGetTempReg(); /* grab a temporary working register. */
8235 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8237 /* offset should be 0, 1 or 3 */
8238 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8240 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8242 emitpcode(POC_MOVWF, pctemp);
8245 emitpLabel(tlbl->key);
8247 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8248 emitpcode(POC_RRF, popGet(AOP(result),offset));
8251 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8254 emitpcode(POC_DECFSZ, pctemp);
8255 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8256 emitpLabel(tlbl1->key);
8258 popReleaseTempReg(pctemp);
8260 size = AOP_SIZE(result);
8262 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8263 pic14_emitcode("rlc","a");
8264 pic14_emitcode("mov","ov,c");
8265 /* if it is only one byte then */
8267 l = aopGet(AOP(left),0,FALSE,FALSE);
8269 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8270 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8271 pic14_emitcode("mov","c,ov");
8272 pic14_emitcode("rrc","a");
8273 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8274 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8275 aopPut(AOP(result),"a",0);
8279 reAdjustPreg(AOP(result));
8280 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8281 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8282 pic14_emitcode("mov","c,ov");
8284 l = aopGet(AOP(result),offset,FALSE,FALSE);
8286 pic14_emitcode("rrc","a");
8287 aopPut(AOP(result),"a",offset--);
8289 reAdjustPreg(AOP(result));
8290 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8291 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8296 freeAsmop(left,NULL,ic,TRUE);
8297 freeAsmop(result,NULL,ic,TRUE);
8298 freeAsmop(right,NULL,ic,TRUE);
8301 /*-----------------------------------------------------------------*/
8302 /* genRightShift - generate code for right shifting */
8303 /*-----------------------------------------------------------------*/
8304 static void genRightShift (iCode *ic)
8306 operand *right, *left, *result;
8310 symbol *tlbl, *tlbl1 ;
8313 /* if signed then we do it the hard way preserve the
8314 sign bit moving it inwards */
8315 retype = getSpec(operandType(IC_RESULT(ic)));
8316 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8318 if (!SPEC_USIGN(retype)) {
8319 genSignedRightShift (ic);
8323 /* signed & unsigned types are treated the same : i.e. the
8324 signed is NOT propagated inwards : quoting from the
8325 ANSI - standard : "for E1 >> E2, is equivalent to division
8326 by 2**E2 if unsigned or if it has a non-negative value,
8327 otherwise the result is implementation defined ", MY definition
8328 is that the sign does not get propagated */
8330 right = IC_RIGHT(ic);
8332 result = IC_RESULT(ic);
8334 aopOp(right,ic,FALSE);
8335 aopOp(left,ic,FALSE);
8336 aopOp(result,ic,FALSE);
8338 /* if the shift count is known then do it
8339 as efficiently as possible */
8340 if (AOP_TYPE(right) == AOP_LIT) {
8341 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8342 //genRightShiftLiteral (left,right,result,ic, 0);
8346 /* shift count is unknown then we have to form
8347 a loop get the loop count in B : Note: we take
8348 only the lower order byte since shifting
8349 more that 32 bits make no sense anyway, ( the
8350 largest size of an object can be only 32 bits ) */
8352 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8353 pic14_emitcode("inc","b");
8355 /* now move the left to the result if they are not the
8357 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8358 AOP_SIZE(result) > 1) {
8360 size = AOP_SIZE(result);
8363 l = aopGet(AOP(left),offset,FALSE,TRUE);
8364 if (*l == '@' && IS_AOP_PREG(result)) {
8366 pic14_emitcode("mov","a,%s",l);
8367 aopPut(AOP(result),"a",offset);
8369 aopPut(AOP(result),l,offset);
8374 tlbl = newiTempLabel(NULL);
8375 tlbl1= newiTempLabel(NULL);
8376 size = AOP_SIZE(result);
8379 /* if it is only one byte then */
8382 tlbl = newiTempLabel(NULL);
8383 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8384 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8385 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8388 emitpcode(POC_COMFW, popGet(AOP(right),0));
8389 emitpcode(POC_RLF, popGet(AOP(result),0));
8390 emitpLabel(tlbl->key);
8391 emitpcode(POC_RRF, popGet(AOP(result),0));
8392 emitpcode(POC_ADDLW, popGetLit(1));
8394 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8399 reAdjustPreg(AOP(result));
8400 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8401 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8404 l = aopGet(AOP(result),offset,FALSE,FALSE);
8406 pic14_emitcode("rrc","a");
8407 aopPut(AOP(result),"a",offset--);
8409 reAdjustPreg(AOP(result));
8411 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8412 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8415 freeAsmop(left,NULL,ic,TRUE);
8416 freeAsmop (right,NULL,ic,TRUE);
8417 freeAsmop(result,NULL,ic,TRUE);
8420 /*-----------------------------------------------------------------*/
8421 /* genUnpackBits - generates code for unpacking bits */
8422 /*-----------------------------------------------------------------*/
8423 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8426 int offset = 0; /* result byte offset */
8427 int rsize; /* result size */
8428 int rlen = 0; /* remaining bitfield length */
8429 sym_link *etype; /* bitfield type information */
8430 int blen; /* bitfield length */
8431 int bstr; /* bitfield starting bit within byte */
8434 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8435 etype = getSpec(operandType(result));
8436 rsize = getSize (operandType (result));
8437 blen = SPEC_BLEN (etype);
8438 bstr = SPEC_BSTR (etype);
8440 /* single bit field case */
8442 if (ifx) { /* that is for an if statement */
8445 resolveIfx(&rIfx,ifx);
8446 if (ptype == -1) /* direct */
8447 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8449 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8450 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8451 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8456 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8457 for (i=0; i < AOP_SIZE(result); i++)
8458 emitpcode (POC_CLRF, popGet (AOP(result), i));
8459 if (ptype == -1) /* direct */
8460 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8462 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8463 emitpcode(POC_BTFSC,pcop);
8464 emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),0,0));
8470 static int has_warned=0;
8473 fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8478 /* read the first byte */
8483 // pic14_emitcode("mov","a,@%s",rname);
8484 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8488 pic14_emitcode("movx","a,@%s",rname);
8492 pic14_emitcode("movx","a,@dptr");
8496 pic14_emitcode("clr","a");
8497 pic14_emitcode("movc","a","@a+dptr");
8501 pic14_emitcode("lcall","__gptrget");
8505 /* if we have bitdisplacement then it fits */
8506 /* into this byte completely or if length is */
8507 /* less than a byte */
8508 if ((shCnt = SPEC_BSTR(etype)) || blen <= 8) {
8510 /* shift right acc */
8511 AccRsh(left,0,shCnt);
8513 pic14_emitcode("anl","a,#0x%02x",
8514 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8515 aopPut(AOP(result),"a",offset);
8519 /* bit field did not fit in a byte */
8520 rlen = SPEC_BLEN(etype) - 8;
8521 aopPut(AOP(result),"a",offset++);
8528 pic14_emitcode("inc","%s",rname);
8529 pic14_emitcode("mov","a,@%s",rname);
8533 pic14_emitcode("inc","%s",rname);
8534 pic14_emitcode("movx","a,@%s",rname);
8538 pic14_emitcode("inc","dptr");
8539 pic14_emitcode("movx","a,@dptr");
8543 pic14_emitcode("clr","a");
8544 pic14_emitcode("inc","dptr");
8545 pic14_emitcode("movc","a","@a+dptr");
8549 pic14_emitcode("inc","dptr");
8550 pic14_emitcode("lcall","__gptrget");
8555 /* if we are done */
8559 aopPut(AOP(result),"a",offset++);
8564 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8565 aopPut(AOP(result),"a",offset);
8572 /*-----------------------------------------------------------------*/
8573 /* genDataPointerGet - generates code when ptr offset is known */
8574 /*-----------------------------------------------------------------*/
8575 static void genDataPointerGet (operand *left,
8579 int size , offset = 0;
8582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8585 /* optimization - most of the time, left and result are the same
8586 * address, but different types. for the pic code, we could omit
8589 aopOp(result,ic,TRUE);
8591 if (pic14_sameRegs (AOP(left), AOP(result)))
8594 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8596 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8598 size = AOP_SIZE(result);
8599 if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8602 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8603 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8607 freeAsmop(left,NULL,ic,TRUE);
8608 freeAsmop(result,NULL,ic,TRUE);
8611 /*-----------------------------------------------------------------*/
8612 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8613 /*-----------------------------------------------------------------*/
8614 static void genNearPointerGet (operand *left,
8619 sym_link *ltype = operandType(left);
8620 sym_link *rtype = operandType(result);
8621 sym_link *retype= getSpec(rtype); /* bitfield type information */
8625 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8628 aopOp(left,ic,FALSE);
8630 /* if left is rematerialisable and
8631 result is not bit variable type and
8632 the left is pointer to data space i.e
8633 lower 128 bytes of space */
8634 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8635 !IS_BITVAR(retype) &&
8636 DCL_TYPE(ltype) == POINTER) {
8637 genDataPointerGet (left,result,ic);
8641 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8642 aopOp (result,ic,FALSE);
8644 /* Check if can access directly instead of via a pointer */
8645 if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8649 /* If the pointer value is not in a the FSR then need to put it in */
8650 if (!AOP_INPREG(AOP(left)) && !direct) {
8651 /* otherwise get a free pointer register */
8652 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8653 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */
8654 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8656 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8657 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8662 /* if bitfield then unpack the bits */
8663 if (IS_BITFIELD(retype))
8664 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8666 /* we have can just get the values */
8667 int size = AOP_SIZE(result);
8670 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8674 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8676 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8677 if (AOP_TYPE(result) == AOP_LIT) {
8678 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8680 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8682 if (size && !direct)
8683 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8688 /* now some housekeeping stuff */
8690 /* we had to allocate for this iCode */
8691 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8692 freeAsmop(NULL,aop,ic,TRUE);
8694 /* we did not allocate which means left
8695 already in a pointer register, then
8696 if size > 0 && this could be used again
8697 we have to point it back to where it
8699 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8700 if (AOP_SIZE(result) > 1 &&
8701 !OP_SYMBOL(left)->remat &&
8702 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8704 int size = AOP_SIZE(result) - 1;
8706 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8711 freeAsmop(left,NULL,ic,TRUE);
8712 freeAsmop(result,NULL,ic,TRUE);
8716 /*-----------------------------------------------------------------*/
8717 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8718 /*-----------------------------------------------------------------*/
8719 static void genPagedPointerGet (operand *left,
8726 sym_link *rtype, *retype;
8729 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8731 rtype = operandType(result);
8732 retype= getSpec(rtype);
8734 aopOp(left,ic,FALSE);
8736 /* if the value is already in a pointer register
8737 then don't need anything more */
8738 if (!AOP_INPREG(AOP(left))) {
8739 /* otherwise get a free pointer register */
8741 preg = getFreePtr(ic,&aop,FALSE);
8742 pic14_emitcode("mov","%s,%s",
8744 aopGet(AOP(left),0,FALSE,TRUE));
8745 rname = preg->name ;
8747 rname = aopGet(AOP(left),0,FALSE,FALSE);
8749 freeAsmop(left,NULL,ic,TRUE);
8750 aopOp (result,ic,FALSE);
8752 /* if bitfield then unpack the bits */
8753 if (IS_BITFIELD(retype))
8754 genUnpackBits (result,left,rname,PPOINTER,0);
8756 /* we have can just get the values */
8757 int size = AOP_SIZE(result);
8762 pic14_emitcode("movx","a,@%s",rname);
8763 aopPut(AOP(result),"a",offset);
8768 pic14_emitcode("inc","%s",rname);
8772 /* now some housekeeping stuff */
8774 /* we had to allocate for this iCode */
8775 freeAsmop(NULL,aop,ic,TRUE);
8777 /* we did not allocate which means left
8778 already in a pointer register, then
8779 if size > 0 && this could be used again
8780 we have to point it back to where it
8782 if (AOP_SIZE(result) > 1 &&
8783 !OP_SYMBOL(left)->remat &&
8784 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8786 int size = AOP_SIZE(result) - 1;
8788 pic14_emitcode("dec","%s",rname);
8793 freeAsmop(result,NULL,ic,TRUE);
8798 /*-----------------------------------------------------------------*/
8799 /* genFarPointerGet - gget value from far space */
8800 /*-----------------------------------------------------------------*/
8801 static void genFarPointerGet (operand *left,
8802 operand *result, iCode *ic)
8805 sym_link *retype = getSpec(operandType(result));
8808 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8810 aopOp(left,ic,FALSE);
8812 /* if the operand is already in dptr
8813 then we do nothing else we move the value to dptr */
8814 if (AOP_TYPE(left) != AOP_STR) {
8815 /* if this is remateriazable */
8816 if (AOP_TYPE(left) == AOP_IMMD)
8817 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8818 else { /* we need to get it byte by byte */
8819 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8820 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8821 if (options.model == MODEL_FLAT24)
8823 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8827 /* so dptr know contains the address */
8828 freeAsmop(left,NULL,ic,TRUE);
8829 aopOp(result,ic,FALSE);
8831 /* if bit then unpack */
8832 if (IS_BITFIELD(retype))
8833 genUnpackBits(result,left,"dptr",FPOINTER,0);
8835 size = AOP_SIZE(result);
8839 pic14_emitcode("movx","a,@dptr");
8840 aopPut(AOP(result),"a",offset++);
8842 pic14_emitcode("inc","dptr");
8846 freeAsmop(result,NULL,ic,TRUE);
8849 /*-----------------------------------------------------------------*/
8850 /* genCodePointerGet - get value from code space */
8851 /*-----------------------------------------------------------------*/
8852 static void genCodePointerGet (operand *left,
8853 operand *result, iCode *ic)
8856 sym_link *retype = getSpec(operandType(result));
8858 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8860 aopOp(left,ic,FALSE);
8862 /* if the operand is already in dptr
8863 then we do nothing else we move the value to dptr */
8864 if (AOP_TYPE(left) != AOP_STR) {
8865 /* if this is remateriazable */
8866 if (AOP_TYPE(left) == AOP_IMMD)
8867 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8868 else { /* we need to get it byte by byte */
8869 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8870 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8871 if (options.model == MODEL_FLAT24)
8873 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8877 /* so dptr know contains the address */
8878 freeAsmop(left,NULL,ic,TRUE);
8879 aopOp(result,ic,FALSE);
8881 /* if bit then unpack */
8882 if (IS_BITFIELD(retype))
8883 genUnpackBits(result,left,"dptr",CPOINTER,0);
8885 size = AOP_SIZE(result);
8889 pic14_emitcode("clr","a");
8890 pic14_emitcode("movc","a,@a+dptr");
8891 aopPut(AOP(result),"a",offset++);
8893 pic14_emitcode("inc","dptr");
8897 freeAsmop(result,NULL,ic,TRUE);
8900 /*-----------------------------------------------------------------*/
8901 /* genGenPointerGet - gget value from generic pointer space */
8902 /*-----------------------------------------------------------------*/
8903 static void genGenPointerGet (operand *left,
8904 operand *result, iCode *ic)
8907 sym_link *retype = getSpec(operandType(result));
8910 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8911 aopOp(left,ic,FALSE);
8912 aopOp(result,ic,FALSE);
8915 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8917 /* if the operand is already in dptr
8918 then we do nothing else we move the value to dptr */
8919 // if (AOP_TYPE(left) != AOP_STR) {
8920 /* if this is remateriazable */
8921 if (AOP_TYPE(left) == AOP_IMMD) {
8922 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8923 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8925 else { /* we need to get it byte by byte */
8927 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8928 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8930 size = AOP_SIZE(result);
8934 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8935 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8937 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8942 /* so dptr know contains the address */
8944 /* if bit then unpack */
8945 //if (IS_BITFIELD(retype))
8946 // genUnpackBits(result,"dptr",GPOINTER);
8949 freeAsmop(left,NULL,ic,TRUE);
8950 freeAsmop(result,NULL,ic,TRUE);
8954 /*-----------------------------------------------------------------*/
8955 /* genConstPointerGet - get value from const generic pointer space */
8956 /*-----------------------------------------------------------------*/
8957 static void genConstPointerGet (operand *left,
8958 operand *result, iCode *ic)
8960 //sym_link *retype = getSpec(operandType(result));
8961 symbol *albl, *blbl;//, *clbl;
8967 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8968 aopOp(left,ic,FALSE);
8969 aopOp(result,ic,FALSE);
8971 size = AOP_SIZE(result);
8973 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8975 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8977 lit = aop_isLitLike (AOP(left));
8978 poc = lit ? POC_MOVLW : POC_MOVFW;
8982 for (i = 0; i < size; i++)
8984 albl = newiTempLabel(NULL);
8985 blbl = newiTempLabel(NULL);
8987 emitpcode(POC_CALL,popGetLabel(albl->key));
8988 pcop = popGetLabel(blbl->key);
8989 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8990 emitpcode(POC_GOTO,pcop);
8992 emitpLabel(albl->key);
8993 emitpcode(poc,popGetAddr(AOP(left),1,i));
8994 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8995 emitpcode(poc,popGetAddr(AOP(left),0,i));
8996 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8998 emitpLabel(blbl->key);
8999 emitpcode(POC_MOVWF,popGet(AOP(result),i));
9002 albl = newiTempLabel(NULL);
9003 blbl = newiTempLabel(NULL);
9004 //clbl = newiTempLabel(NULL);
9006 emitpcode (POC_GOTO, popGetLabel (blbl->key));
9008 emitpLabel(albl->key);
9009 emitpcode(poc,popGet(AOP(left),1));
9010 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
9011 emitpcode(poc,popGet(AOP(left),0));
9012 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
9014 emitpLabel(blbl->key);
9016 for (i = 0; i < size; i++)
9018 emitpcode(POC_CALL,popGetLabel(albl->key));
9019 /* the next two instructions (plus clbl) might be useless... */
9020 //pcop = popGetLabel(clbl->key);
9021 //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
9022 //emitpcode(POC_GOTO,pcop);
9023 //emitpLabel(clbl->key);
9026 emitpcode (POC_INCF, popGet (AOP(left), 0));
9028 emitpcode (POC_INCF, popGet (AOP(left), 1));
9030 emitpcode(POC_MOVWF,popGet(AOP(result),i));
9033 /* restore left's value */
9034 emitpcode (POC_MOVLW, popGetLit (size-1));
9035 emitpcode (POC_SUBWF, popGet (AOP(left), 0));
9037 emitpcode (POC_DECF, popGet (AOP(left), 1));
9041 freeAsmop(left,NULL,ic,TRUE);
9042 freeAsmop(result,NULL,ic,TRUE);
9045 /*-----------------------------------------------------------------*/
9046 /* genPointerGet - generate code for pointer get */
9047 /*-----------------------------------------------------------------*/
9048 static void genPointerGet (iCode *ic)
9050 operand *left, *result ;
9051 sym_link *type, *etype;
9055 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9058 result = IC_RESULT(ic) ;
9060 /* depending on the type of pointer we need to
9061 move it to the correct pointer register */
9062 type = operandType(left);
9063 etype = getSpec(type);
9065 if (IS_PTR_CONST(type))
9066 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9068 /* if left is of type of pointer then it is simple */
9069 if (IS_PTR(type) && !IS_FUNC(type->next))
9070 p_type = DCL_TYPE(type);
9072 /* we have to go by the storage class */
9073 p_type = PTR_TYPE(SPEC_OCLS(etype));
9075 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9077 if (SPEC_OCLS(etype)->codesp ) {
9078 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9079 //p_type = CPOINTER ;
9082 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9083 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9084 /*p_type = FPOINTER ;*/
9086 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9087 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9088 /* p_type = PPOINTER; */
9090 if (SPEC_OCLS(etype) == idata )
9091 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9092 /* p_type = IPOINTER; */
9094 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9095 /* p_type = POINTER ; */
9098 /* now that we have the pointer type we assign
9099 the pointer values */
9104 genNearPointerGet (left,result,ic);
9108 genPagedPointerGet(left,result,ic);
9112 genFarPointerGet (left,result,ic);
9116 genConstPointerGet (left,result,ic);
9117 //pic14_emitcodePointerGet (left,result,ic);
9121 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
9122 genConstPointerGet (left,result,ic);
9124 genGenPointerGet (left,result,ic);
9127 assert ( !"unhandled pointer type" );
9133 /*-----------------------------------------------------------------*/
9134 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into */
9135 /* A through a pointer register (R0, R1, or DPTR). The original */
9136 /* value of A can be preserved in B. */
9137 /* PIC has to use INDF register. */
9138 /*-----------------------------------------------------------------*/
9140 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9148 pic14_emitcode ("mov", "b,a");
9149 // pic14_emitcode ("mov", "a,@%s", rname);
9150 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
9155 pic14_emitcode ("mov", "b,a");
9156 pic14_emitcode ("movx", "a,@%s", rname);
9161 pic14_emitcode ("mov", "b,a");
9162 pic14_emitcode ("movx", "a,@dptr");
9167 pic14_emitcode ("mov", "b,a");
9168 pic14_emitcode ("clr", "a");
9169 pic14_emitcode ("movc", "a,@a+dptr");
9175 pic14_emitcode ("push", "b");
9176 pic14_emitcode ("push", "acc");
9178 pic14_emitcode ("lcall", "__gptrget");
9180 pic14_emitcode ("pop", "b");
9185 /*-----------------------------------------------------------------*/
9186 /* emitPtrByteSet - emits code to set a byte from src through a */
9187 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
9188 /*-----------------------------------------------------------------*/
9190 emitPtrByteSet (char *rname, int p_type, char *src)
9200 pic14_emitcode ("mov", "@%s,a", rname);
9203 // pic14_emitcode ("mov", "@%s,%s", rname, src);
9204 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9209 pic14_emitcode ("movx", "@%s,a", rname);
9214 pic14_emitcode ("movx", "@dptr,a");
9219 pic14_emitcode ("lcall", "__gptrput");
9224 /*-----------------------------------------------------------------*/
9225 /* genPackBits - generates code for packed bit storage */
9226 /*-----------------------------------------------------------------*/
9227 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
9229 int offset = 0; /* source byte offset */
9230 int rlen = 0; /* remaining bitfield length */
9231 int blen; /* bitfield length */
9232 int bstr; /* bitfield starting bit within byte */
9233 int litval; /* source literal value (if AOP_LIT) */
9234 unsigned char mask; /* bitmask within current byte */
9237 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9239 blen = SPEC_BLEN (etype);
9240 bstr = SPEC_BSTR (etype);
9242 /* If the bitfield length is less than a byte */
9245 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9246 (unsigned char) (0xFF >> (8 - bstr)));
9248 if (AOP_TYPE (right) == AOP_LIT)
9250 /* Case with a bitfield length <8 and literal source
9252 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9256 if (AOP(result)->type == AOP_PCODE)
9257 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9259 pcop = popGet(AOP(result),0);
9260 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9262 emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
9266 litval = lit << bstr;
9267 litval &= (~mask) & 0xff;
9269 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9271 emitPtrByteGet (rname, p_type, FALSE);
9272 if ((mask|litval)!=0xff)
9273 emitpcode(POC_ANDLW,popGetLit(mask));
9275 emitpcode(POC_IORLW,popGetLit(litval));
9282 /* Note more efficient code, of pre clearing bit then only setting it if required, can only be done if it is known that the result is not a SFR */
9283 emitpcode(POC_RRFW,popGet(AOP(right),0));
9285 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9287 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9289 } else if (p_type!=GPOINTER) {
9290 /* Case with a bitfield length == 1 and no generic pointer
9292 if (AOP_TYPE (right) == AOP_CRY)
9293 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9296 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9297 pic14_emitcode ("rrc","a");
9299 emitPtrByteGet (rname, p_type, FALSE);
9300 pic14_emitcode ("mov","acc.%d,c",bstr);
9306 /* Case with a bitfield length < 8 and arbitrary source
9308 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9309 /* shift and mask source value */
9310 AccLsh (right,0,bstr);
9311 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9312 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9314 //pushedB = pushB ();
9316 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9318 emitPtrByteGet (rname, p_type, TRUE);
9320 pic14_emitcode ("anl", "a,#0x%02x", mask);
9321 pic14_emitcode ("orl", "a,b");
9322 emitpcode(POC_ANDLW,popGetLit(mask));
9323 emitpcode(POC_IORFW,popGet(AOP(right),0));
9324 if (p_type == GPOINTER)
9325 pic14_emitcode ("pop", "b");
9332 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9334 emitPtrByteSet (rname, p_type, "a");
9338 /* Bit length is greater than 7 bits. In this case, copy */
9339 /* all except the partial byte at the end */
9340 for (rlen=blen;rlen>=8;rlen-=8)
9342 emitPtrByteSet (rname, p_type,
9343 aopGet (AOP (right), offset++, FALSE, TRUE) );
9345 pic14_emitcode ("inc", "%s", rname);
9348 /* If there was a partial byte at the end */
9351 mask = (((unsigned char) -1 << rlen) & 0xff);
9353 if (AOP_TYPE (right) == AOP_LIT)
9355 /* Case with partial byte and literal source
9357 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9358 litval >>= (blen-rlen);
9359 litval &= (~mask) & 0xff;
9360 emitPtrByteGet (rname, p_type, FALSE);
9361 if ((mask|litval)!=0xff)
9362 pic14_emitcode ("anl","a,#0x%02x", mask);
9364 pic14_emitcode ("orl","a,#0x%02x", litval);
9369 /* Case with partial byte and arbitrary source
9371 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9372 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9374 //pushedB = pushB ();
9375 /* transfer A to B and get next byte */
9376 emitPtrByteGet (rname, p_type, TRUE);
9378 pic14_emitcode ("anl", "a,#0x%02x", mask);
9379 pic14_emitcode ("orl", "a,b");
9380 if (p_type == GPOINTER)
9381 pic14_emitcode ("pop", "b");
9385 emitPtrByteSet (rname, p_type, "a");
9390 /*-----------------------------------------------------------------*/
9391 /* SetIrp - Set IRP bit */
9392 /*-----------------------------------------------------------------*/
9393 void SetIrp(operand *result) {
9395 if (AOP_TYPE(result) == AOP_LIT) {
9396 unsigned lit = (unsigned)operandLitValue(result);
9397 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9399 if (PCOP(AOP(result))->type == PO_LITERAL) {
9400 int addrs = PCOL(AOP(result))->lit;
9401 emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9403 emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9404 if(AOP_SIZE(result) > 1) {
9405 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9406 emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9412 /*-----------------------------------------------------------------*/
9413 /* genDataPointerSet - remat pointer to data space */
9414 /*-----------------------------------------------------------------*/
9415 static void genDataPointerSet(operand *right,
9419 int size, offset = 0 ;
9422 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9423 aopOp(right,ic,FALSE);
9424 aopOp(result,ic,FALSE);
9426 size = AOP_SIZE(right);
9428 if ( AOP_TYPE(result) == AOP_PCODE) {
9429 fprintf(stderr,"genDataPointerSet %s, %d\n",
9430 AOP(result)->aopu.pcop->name,
9431 PCOI(AOP(result)->aopu.pcop)->offset);
9435 // tsd, was l+1 - the underline `_' prefix was being stripped
9437 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9439 if (AOP_TYPE(right) == AOP_LIT) {
9440 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9441 lit = lit >> (8*offset);
9443 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9444 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9446 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9449 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9450 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9456 freeAsmop(right,NULL,ic,TRUE);
9457 freeAsmop(result,NULL,ic,TRUE);
9460 /*-----------------------------------------------------------------*/
9461 /* genNearPointerSet - pic14_emitcode for near pointer put */
9462 /*-----------------------------------------------------------------*/
9463 static void genNearPointerSet (operand *right,
9468 sym_link *ptype = operandType(result);
9469 sym_link *retype = getSpec(operandType(right));
9470 sym_link *letype = getSpec(ptype);
9475 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9476 aopOp(result,ic,FALSE);
9479 /* if the result is rematerializable &
9480 in data space & not a bit variable */
9481 //if (AOP_TYPE(result) == AOP_IMMD &&
9482 if (AOP_TYPE(result) == AOP_PCODE &&
9483 DCL_TYPE(ptype) == POINTER &&
9484 !IS_BITVAR (retype) &&
9485 !IS_BITVAR (letype)) {
9486 genDataPointerSet (right,result,ic);
9487 freeAsmop(result,NULL,ic,TRUE);
9491 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9492 aopOp(right,ic,FALSE);
9493 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9495 /* Check if can access directly instead of via a pointer */
9496 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9500 /* If the pointer value is not in a the FSR then need to put it in */
9501 if (!AOP_INPREG(AOP(result)) && !direct) {
9502 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9503 if (PCOP(AOP(result))->type == PO_LITERAL)
9504 emitpcode(POC_MOVLW, popGet(AOP(result),0));
9506 emitpcode(POC_MOVFW, popGet(AOP(result),0));
9507 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9510 /* Must set/reset IRP bit for use with FSR. */
9511 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9515 /* if bitfield then unpack the bits */
9516 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9517 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
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);
9574 /*-----------------------------------------------------------------*/
9575 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9576 /*-----------------------------------------------------------------*/
9577 static void genPagedPointerSet (operand *right,
9587 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9589 retype= getSpec(operandType(right));
9591 aopOp(result,ic,FALSE);
9593 /* if the value is already in a pointer register
9594 then don't need anything more */
9595 if (!AOP_INPREG(AOP(result))) {
9596 /* otherwise get a free pointer register */
9598 preg = getFreePtr(ic,&aop,FALSE);
9599 pic14_emitcode("mov","%s,%s",
9601 aopGet(AOP(result),0,FALSE,TRUE));
9602 rname = preg->name ;
9604 rname = aopGet(AOP(result),0,FALSE,FALSE);
9606 freeAsmop(result,NULL,ic,TRUE);
9607 aopOp (right,ic,FALSE);
9609 /* if bitfield then unpack the bits */
9610 if (IS_BITFIELD(retype))
9611 genPackBits (retype,result,right,rname,PPOINTER);
9613 /* we have can just get the values */
9614 int size = AOP_SIZE(right);
9618 l = aopGet(AOP(right),offset,FALSE,TRUE);
9621 pic14_emitcode("movx","@%s,a",rname);
9624 pic14_emitcode("inc","%s",rname);
9630 /* now some housekeeping stuff */
9632 /* we had to allocate for this iCode */
9633 freeAsmop(NULL,aop,ic,TRUE);
9635 /* we did not allocate which means left
9636 already in a pointer register, then
9637 if size > 0 && this could be used again
9638 we have to point it back to where it
9640 if (AOP_SIZE(right) > 1 &&
9641 !OP_SYMBOL(result)->remat &&
9642 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9644 int size = AOP_SIZE(right) - 1;
9646 pic14_emitcode("dec","%s",rname);
9651 freeAsmop(right,NULL,ic,TRUE);
9656 /*-----------------------------------------------------------------*/
9657 /* genFarPointerSet - set value from far space */
9658 /*-----------------------------------------------------------------*/
9659 static void genFarPointerSet (operand *right,
9660 operand *result, iCode *ic)
9663 sym_link *retype = getSpec(operandType(right));
9666 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9667 aopOp(result,ic,FALSE);
9669 /* if the operand is already in dptr
9670 then we do nothing else we move the value to dptr */
9671 if (AOP_TYPE(result) != AOP_STR) {
9672 /* if this is remateriazable */
9673 if (AOP_TYPE(result) == AOP_IMMD)
9674 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9675 else { /* we need to get it byte by byte */
9676 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9677 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9678 if (options.model == MODEL_FLAT24)
9680 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9684 /* so dptr know contains the address */
9685 freeAsmop(result,NULL,ic,TRUE);
9686 aopOp(right,ic,FALSE);
9688 /* if bit then unpack */
9689 if (IS_BITFIELD(retype))
9690 genPackBits(retype,result,right,"dptr",FPOINTER);
9692 size = AOP_SIZE(right);
9696 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9698 pic14_emitcode("movx","@dptr,a");
9700 pic14_emitcode("inc","dptr");
9704 freeAsmop(right,NULL,ic,TRUE);
9707 /*-----------------------------------------------------------------*/
9708 /* genGenPointerSet - set value from generic pointer space */
9709 /*-----------------------------------------------------------------*/
9710 static void genGenPointerSet (operand *right,
9711 operand *result, iCode *ic)
9713 sym_link *ptype = operandType(result);
9714 sym_link *retype = getSpec(operandType(right));
9715 sym_link *letype = getSpec (ptype);
9718 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9720 aopOp(result,ic,FALSE);
9721 aopOp(right,ic,FALSE);
9723 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9725 /* if the operand is already in dptr
9726 then we do nothing else we move the value to dptr */
9727 if (AOP_TYPE(result) != AOP_STR) {
9728 /* if this is remateriazable */
9729 if (AOP_TYPE(result) == AOP_IMMD) {
9730 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9731 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9734 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9735 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9737 /* Must set/reset IRP bit for use with FSR. */
9738 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9743 /* if bitfield then unpack the bits */
9744 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9745 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9747 /* we have can just get the values */
9748 int size = AOP_SIZE(right);
9751 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9753 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9755 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9757 if (AOP_TYPE(right) == AOP_LIT) {
9758 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9760 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9762 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9765 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9770 freeAsmop(right,NULL,ic,TRUE);
9771 freeAsmop(result,NULL,ic,TRUE);
9774 /*-----------------------------------------------------------------*/
9775 /* genPointerSet - stores the value into a pointer location */
9776 /*-----------------------------------------------------------------*/
9777 static void genPointerSet (iCode *ic)
9779 operand *right, *result ;
9780 sym_link *type, *etype;
9784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9786 right = IC_RIGHT(ic);
9787 result = IC_RESULT(ic) ;
9789 /* depending on the type of pointer we need to
9790 move it to the correct pointer register */
9791 type = operandType(result);
9792 etype = getSpec(type);
9793 /* if left is of type of pointer then it is simple */
9794 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9795 p_type = DCL_TYPE(type);
9798 /* we have to go by the storage class */
9799 p_type = PTR_TYPE(SPEC_OCLS(etype));
9801 /* if (SPEC_OCLS(etype)->codesp ) { */
9802 /* p_type = CPOINTER ; */
9805 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9806 /* p_type = FPOINTER ; */
9808 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9809 /* p_type = PPOINTER ; */
9811 /* if (SPEC_OCLS(etype) == idata ) */
9812 /* p_type = IPOINTER ; */
9814 /* p_type = POINTER ; */
9817 /* now that we have the pointer type we assign
9818 the pointer values */
9823 genNearPointerSet (right,result,ic);
9827 genPagedPointerSet (right,result,ic);
9831 genFarPointerSet (right,result,ic);
9835 genGenPointerSet (right,result,ic);
9839 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9840 "genPointerSet: illegal pointer type");
9844 /*-----------------------------------------------------------------*/
9845 /* genIfx - generate code for Ifx statement */
9846 /*-----------------------------------------------------------------*/
9847 static void genIfx (iCode *ic, iCode *popIc)
9849 operand *cond = IC_COND(ic);
9853 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9855 aopOp(cond,ic,FALSE);
9857 /* get the value into acc */
9858 if (AOP_TYPE(cond) != AOP_CRY)
9859 pic14_toBoolean(cond);
9862 /* the result is now in the accumulator */
9863 freeAsmop(cond,NULL,ic,TRUE);
9865 /* if there was something to be popped then do it */
9869 /* if the condition is a bit variable */
9870 if (isbit && IS_ITEMP(cond) &&
9872 genIfxJump(ic,SPIL_LOC(cond)->rname);
9873 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9876 if (isbit && !IS_ITEMP(cond))
9877 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9885 /*-----------------------------------------------------------------*/
9886 /* genAddrOf - generates code for address of */
9887 /*-----------------------------------------------------------------*/
9888 static void genAddrOf (iCode *ic)
9890 operand *right, *result, *left;
9894 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9897 //aopOp(IC_RESULT(ic),ic,FALSE);
9899 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9900 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9901 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9903 DEBUGpic14_AopType(__LINE__,left,right,result);
9904 assert (IS_SYMOP (left));
9906 /* sanity check: generic pointers to code space are not yet supported,
9907 * pionters to codespace must not be assigned addresses of __data values. */
9909 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9910 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)));
9911 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)));
9912 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)));
9913 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)));
9916 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9917 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9918 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9919 OP_SYMBOL(left)->name);
9920 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9921 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9922 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9923 OP_SYMBOL(left)->name);
9926 size = AOP_SIZE(IC_RESULT(ic));
9930 /* fixing bug #863624, reported from (errolv) */
9931 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9932 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9935 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9936 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9941 freeAsmop(left,NULL,ic,FALSE);
9942 freeAsmop(result,NULL,ic,TRUE);
9947 /*-----------------------------------------------------------------*/
9948 /* genFarFarAssign - assignment when both are in far space */
9949 /*-----------------------------------------------------------------*/
9950 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9952 int size = AOP_SIZE(right);
9955 /* first push the right side on to the stack */
9957 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9959 pic14_emitcode ("push","acc");
9962 freeAsmop(right,NULL,ic,FALSE);
9963 /* now assign DPTR to result */
9964 aopOp(result,ic,FALSE);
9965 size = AOP_SIZE(result);
9967 pic14_emitcode ("pop","acc");
9968 aopPut(AOP(result),"a",--offset);
9970 freeAsmop(result,NULL,ic,FALSE);
9975 /*-----------------------------------------------------------------*/
9976 /* genAssign - generate code for assignment */
9977 /*-----------------------------------------------------------------*/
9978 static void genAssign (iCode *ic)
9980 operand *result, *right;
9981 int size, offset,know_W;
9982 unsigned long lit = 0L;
9984 result = IC_RESULT(ic);
9985 right = IC_RIGHT(ic) ;
9988 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9990 /* if they are the same */
9991 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9994 aopOp(right,ic,FALSE);
9995 aopOp(result,ic,TRUE);
9997 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9999 /* if they are the same registers */
10000 if (pic14_sameRegs(AOP(right),AOP(result)))
10003 /* special case: assign from __code */
10004 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10005 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10006 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10007 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10008 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10010 emitpComment ("genAssign from CODESPACE");
10011 genConstPointerGet (right, result, ic);
10015 /* just for symmetry reasons... */
10016 if (!IS_ITEMP(result)
10017 && IS_SYMOP (result)
10018 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10020 assert ( !"cannot write to CODESPACE" );
10023 /* if the result is a bit */
10024 if (AOP_TYPE(result) == AOP_CRY) {
10026 /* if the right size is a literal then
10027 we know what the value is */
10028 if (AOP_TYPE(right) == AOP_LIT) {
10030 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10031 popGet(AOP(result),0));
10033 if (((int) operandLitValue(right)))
10034 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10035 AOP(result)->aopu.aop_dir,
10036 AOP(result)->aopu.aop_dir);
10038 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10039 AOP(result)->aopu.aop_dir,
10040 AOP(result)->aopu.aop_dir);
10044 /* the right is also a bit variable */
10045 if (AOP_TYPE(right) == AOP_CRY) {
10046 emitpcode(POC_BCF, popGet(AOP(result),0));
10047 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10048 emitpcode(POC_BSF, popGet(AOP(result),0));
10050 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10051 AOP(result)->aopu.aop_dir,
10052 AOP(result)->aopu.aop_dir);
10053 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10054 AOP(right)->aopu.aop_dir,
10055 AOP(right)->aopu.aop_dir);
10056 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10057 AOP(result)->aopu.aop_dir,
10058 AOP(result)->aopu.aop_dir);
10062 /* we need to or */
10063 emitpcode(POC_BCF, popGet(AOP(result),0));
10064 pic14_toBoolean(right);
10066 emitpcode(POC_BSF, popGet(AOP(result),0));
10067 //aopPut(AOP(result),"a",0);
10071 /* bit variables done */
10073 size = AOP_SIZE(result);
10075 if(AOP_TYPE(right) == AOP_LIT)
10076 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10078 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10079 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10080 if(aopIdx(AOP(result),0) == 4) {
10081 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10082 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10083 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10086 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10091 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10092 if(AOP_TYPE(right) == AOP_LIT) {
10094 if(know_W != (int)(lit&0xff))
10095 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10097 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10099 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10103 } else if (AOP_TYPE(right) == AOP_CRY) {
10104 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10106 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10107 emitpcode(POC_INCF, popGet(AOP(result),0));
10110 mov2w (AOP(right), offset);
10111 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10119 freeAsmop (right,NULL,ic,FALSE);
10120 freeAsmop (result,NULL,ic,TRUE);
10123 /*-----------------------------------------------------------------*/
10124 /* genJumpTab - genrates code for jump table */
10125 /*-----------------------------------------------------------------*/
10126 static void genJumpTab (iCode *ic)
10132 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10134 aopOp(IC_JTCOND(ic),ic,FALSE);
10135 /* get the condition into accumulator */
10136 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10138 /* multiply by three */
10139 pic14_emitcode("add","a,acc");
10140 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10142 jtab = newiTempLabel(NULL);
10143 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10144 pic14_emitcode("jmp","@a+dptr");
10145 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10147 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10148 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10149 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10150 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10152 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10153 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10154 emitpLabel(jtab->key);
10156 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10158 /* now generate the jump labels */
10159 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10160 jtab = setNextItem(IC_JTLABELS(ic))) {
10161 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10162 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10168 /*-----------------------------------------------------------------*/
10169 /* genMixedOperation - gen code for operators between mixed types */
10170 /*-----------------------------------------------------------------*/
10172 TSD - Written for the PIC port - but this unfortunately is buggy.
10173 This routine is good in that it is able to efficiently promote
10174 types to different (larger) sizes. Unfortunately, the temporary
10175 variables that are optimized out by this routine are sometimes
10176 used in other places. So until I know how to really parse the
10177 iCode tree, I'm going to not be using this routine :(.
10179 static int genMixedOperation (iCode *ic)
10183 operand *result = IC_RESULT(ic);
10184 sym_link *ctype = operandType(IC_LEFT(ic));
10185 operand *right = IC_RIGHT(ic);
10191 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10193 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10199 nextright = IC_RIGHT(nextic);
10200 nextleft = IC_LEFT(nextic);
10201 nextresult = IC_RESULT(nextic);
10203 aopOp(right,ic,FALSE);
10204 aopOp(result,ic,FALSE);
10205 aopOp(nextright, nextic, FALSE);
10206 aopOp(nextleft, nextic, FALSE);
10207 aopOp(nextresult, nextic, FALSE);
10209 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10211 operand *t = right;
10215 pic14_emitcode(";remove right +","");
10217 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10219 operand *t = right;
10223 pic14_emitcode(";remove left +","");
10227 big = AOP_SIZE(nextleft);
10228 small = AOP_SIZE(nextright);
10230 switch(nextic->op) {
10233 pic14_emitcode(";optimize a +","");
10234 /* if unsigned or not an integral type */
10235 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10236 pic14_emitcode(";add a bit to something","");
10239 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10241 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10242 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10243 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10245 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10253 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10254 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10255 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10258 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10260 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10261 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10262 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10263 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10264 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10267 pic14_emitcode("rlf","known_zero,w");
10274 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10275 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10276 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10278 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10288 freeAsmop(right,NULL,ic,TRUE);
10289 freeAsmop(result,NULL,ic,TRUE);
10290 freeAsmop(nextright,NULL,ic,TRUE);
10291 freeAsmop(nextleft,NULL,ic,TRUE);
10293 nextic->generated = 1;
10300 /*-----------------------------------------------------------------*/
10301 /* genCast - gen code for casting */
10302 /*-----------------------------------------------------------------*/
10303 static void genCast (iCode *ic)
10305 operand *result = IC_RESULT(ic);
10306 sym_link *ctype = operandType(IC_LEFT(ic));
10307 sym_link *rtype = operandType(IC_RIGHT(ic));
10308 operand *right = IC_RIGHT(ic);
10312 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10313 /* if they are equivalent then do nothing */
10314 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10317 aopOp(right,ic,FALSE) ;
10318 aopOp(result,ic,FALSE);
10320 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10322 /* if the result is a bit */
10323 if (AOP_TYPE(result) == AOP_CRY) {
10324 /* if the right size is a literal then
10325 we know what the value is */
10326 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10327 if (AOP_TYPE(right) == AOP_LIT) {
10329 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10330 popGet(AOP(result),0));
10332 if (((int) operandLitValue(right)))
10333 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10334 AOP(result)->aopu.aop_dir,
10335 AOP(result)->aopu.aop_dir);
10337 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10338 AOP(result)->aopu.aop_dir,
10339 AOP(result)->aopu.aop_dir);
10344 /* the right is also a bit variable */
10345 if (AOP_TYPE(right) == AOP_CRY) {
10348 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10350 pic14_emitcode("clrc","");
10351 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10352 AOP(right)->aopu.aop_dir,
10353 AOP(right)->aopu.aop_dir);
10354 aopPut(AOP(result),"c",0);
10358 /* we need to or */
10359 if (AOP_TYPE(right) == AOP_REG) {
10360 emitpcode(POC_BCF, popGet(AOP(result),0));
10361 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10362 emitpcode(POC_BSF, popGet(AOP(result),0));
10364 pic14_toBoolean(right);
10365 aopPut(AOP(result),"a",0);
10369 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10371 size = AOP_SIZE(result);
10373 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10375 emitpcode(POC_CLRF, popGet(AOP(result),0));
10376 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10377 emitpcode(POC_INCF, popGet(AOP(result),0));
10380 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10385 /* if they are the same size : or less */
10386 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10388 /* if they are in the same place */
10389 if (pic14_sameRegs(AOP(right),AOP(result)))
10392 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10393 if (IS_PTR_CONST(rtype))
10394 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10395 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10396 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10398 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10399 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10400 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10401 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10402 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10403 if(AOP_SIZE(result) <2)
10404 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10408 /* if they in different places then copy */
10409 size = AOP_SIZE(result);
10412 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10413 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10415 //aopPut(AOP(result),
10416 // aopGet(AOP(right),offset,FALSE,FALSE),
10426 /* if the result is of type pointer */
10427 if (IS_PTR(ctype)) {
10430 sym_link *type = operandType(right);
10431 sym_link *etype = getSpec(type);
10432 DEBUGpic14_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10434 /* pointer to generic pointer */
10435 if (IS_GENPTR(ctype)) {
10439 p_type = DCL_TYPE(type);
10441 /* we have to go by the storage class */
10442 p_type = PTR_TYPE(SPEC_OCLS(etype));
10444 /* if (SPEC_OCLS(etype)->codesp ) */
10445 /* p_type = CPOINTER ; */
10447 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10448 /* p_type = FPOINTER ; */
10450 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10451 /* p_type = PPOINTER; */
10453 /* if (SPEC_OCLS(etype) == idata ) */
10454 /* p_type = IPOINTER ; */
10456 /* p_type = POINTER ; */
10459 /* the first two bytes are known */
10460 DEBUGpic14_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10461 size = GPTRSIZE - 1;
10464 if(offset < AOP_SIZE(right)) {
10465 DEBUGpic14_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10466 if ((AOP_TYPE(right) == AOP_PCODE) &&
10467 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10468 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10469 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10471 aopPut(AOP(result),
10472 aopGet(AOP(right),offset,FALSE,FALSE),
10476 emitpcode(POC_CLRF,popGet(AOP(result),offset));
10479 /* the last byte depending on type */
10483 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10486 pic14_emitcode(";BUG!? ","%d",__LINE__);
10490 pic14_emitcode(";BUG!? ","%d",__LINE__);
10494 pic14_emitcode(";BUG!? ","%d",__LINE__);
10499 /* this should never happen */
10500 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10501 "got unknown pointer type");
10504 //aopPut(AOP(result),l, GPTRSIZE - 1);
10508 /* just copy the pointers */
10509 size = AOP_SIZE(result);
10512 aopPut(AOP(result),
10513 aopGet(AOP(right),offset,FALSE,FALSE),
10522 /* so we now know that the size of destination is greater
10523 than the size of the source.
10524 Now, if the next iCode is an operator then we might be
10525 able to optimize the operation without performing a cast.
10527 if(genMixedOperation(ic))
10530 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10532 /* we move to result for the size of source */
10533 size = AOP_SIZE(right);
10536 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10537 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10541 /* now depending on the sign of the destination */
10542 size = AOP_SIZE(result) - AOP_SIZE(right);
10543 /* if unsigned or not an integral type */
10544 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10546 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10548 /* we need to extend the sign :{ */
10551 /* Save one instruction of casting char to int */
10552 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10553 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10554 emitpcode(POC_DECF, popGet(AOP(result),offset));
10556 emitpcodeNULLop(POC_CLRW);
10559 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10561 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10563 emitpcode(POC_MOVLW, popGetLit(0xff));
10566 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
10571 freeAsmop(right,NULL,ic,TRUE);
10572 freeAsmop(result,NULL,ic,TRUE);
10576 /*-----------------------------------------------------------------*/
10577 /* genDjnz - generate decrement & jump if not zero instrucion */
10578 /*-----------------------------------------------------------------*/
10579 static int genDjnz (iCode *ic, iCode *ifx)
10581 symbol *lbl, *lbl1;
10583 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10588 /* if the if condition has a false label
10589 then we cannot save */
10593 /* if the minus is not of the form
10595 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10596 !IS_OP_LITERAL(IC_RIGHT(ic)))
10599 if (operandLitValue(IC_RIGHT(ic)) != 1)
10602 /* if the size of this greater than one then no
10604 if (getSize(operandType(IC_RESULT(ic))) > 1)
10607 /* otherwise we can save BIG */
10608 lbl = newiTempLabel(NULL);
10609 lbl1= newiTempLabel(NULL);
10611 aopOp(IC_RESULT(ic),ic,FALSE);
10613 if (IS_AOP_PREG(IC_RESULT(ic))) {
10614 pic14_emitcode("dec","%s",
10615 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10616 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10617 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10621 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10622 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10624 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10625 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10628 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10629 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10630 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10631 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10634 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10635 ifx->generated = 1;
10639 /*-----------------------------------------------------------------*/
10640 /* genReceive - generate code for a receive iCode */
10641 /*-----------------------------------------------------------------*/
10642 static void genReceive (iCode *ic)
10645 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10647 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10648 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10649 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10651 int size = getSize(operandType(IC_RESULT(ic)));
10652 int offset = fReturnSizePic - size;
10654 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10655 fReturn[fReturnSizePic - offset - 1] : "acc"));
10658 aopOp(IC_RESULT(ic),ic,FALSE);
10659 size = AOP_SIZE(IC_RESULT(ic));
10662 pic14_emitcode ("pop","acc");
10663 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10668 aopOp(IC_RESULT(ic),ic,FALSE);
10670 assignResultValue(IC_RESULT(ic));
10673 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10676 /*-----------------------------------------------------------------*/
10677 /* genDummyRead - generate code for dummy read of volatiles */
10678 /*-----------------------------------------------------------------*/
10680 genDummyRead (iCode * ic)
10683 pic14_emitcode ("; genDummyRead","");
10684 pic14_emitcode ("; not implemented","");
10689 /*-----------------------------------------------------------------*/
10690 /* genpic14Code - generate code for pic14 based controllers */
10691 /*-----------------------------------------------------------------*/
10693 * At this point, ralloc.c has gone through the iCode and attempted
10694 * to optimize in a way suitable for a PIC. Now we've got to generate
10695 * PIC instructions that correspond to the iCode.
10697 * Once the instructions are generated, we'll pass through both the
10698 * peep hole optimizer and the pCode optimizer.
10699 *-----------------------------------------------------------------*/
10701 void genpic14Code (iCode *lic)
10708 lineHead = lineCurr = NULL;
10710 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10713 /* if debug information required */
10714 if (options.debug && currFunc) {
10716 debugFile->writeFunction (currFunc, lic);
10721 for (ic = lic ; ic ; ic = ic->next ) {
10723 //DEBUGpic14_emitcode(";ic","");
10724 //fprintf (stderr, "in ic loop\n");
10725 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10726 //ic->lineno, printCLine(ic->filename, ic->lineno));
10728 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10730 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10731 cline = printCLine (ic->filename, ic->lineno);
10732 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10733 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10734 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10737 if (options.iCodeInAsm) {
10738 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10740 /* if the result is marked as
10741 spilt and rematerializable or code for
10742 this has already been generated then
10744 if (resultRemat(ic) || ic->generated )
10747 /* depending on the operation */
10766 /* IPOP happens only when trying to restore a
10767 spilt live range, if there is an ifx statement
10768 following this pop then the if statement might
10769 be using some of the registers being popped which
10770 would destory the contents of the register so
10771 we need to check for this condition and handle it */
10773 ic->next->op == IFX &&
10774 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10775 genIfx (ic->next,ic);
10793 genEndFunction (ic);
10813 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10830 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10834 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10841 /* note these two are xlated by algebraic equivalence
10842 during parsing SDCC.y */
10843 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10844 "got '>=' or '<=' shouldn't have come here");
10848 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10860 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10864 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10868 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10892 genRightShift (ic);
10895 case GET_VALUE_AT_ADDRESS:
10900 if (POINTER_SET(ic))
10927 addSet(&_G.sendSet,ic);
10930 case DUMMY_READ_VOLATILE:
10935 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10942 /* now we are ready to call the
10943 peep hole optimizer */
10944 if (!options.nopeep) {
10945 peepHole (&lineHead);
10947 /* now do the actual printing */
10948 printLine (lineHead,codeOutFile);
10951 DFPRINTF((stderr,"printing pBlock\n\n"));
10952 printpBlock(stdout,pb);
10959 aop_isLitLike (asmop *aop)
10962 if (aop->type == AOP_LIT) return 1;
10963 if (aop->type == AOP_IMMD) return 1;
10964 if ((aop->type == AOP_PCODE) &&
10965 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10967 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10968 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10975 op_isLitLike (operand *op)
10978 if (aop_isLitLike (AOP(op))) return 1;