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];
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];
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 /* should have been converted to function call */
3311 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3312 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3313 freeAsmop(result,NULL,ic,TRUE);
3316 /*-----------------------------------------------------------------*/
3317 /* genDivbits :- division of bits */
3318 /*-----------------------------------------------------------------*/
3319 static void genDivbits (operand *left,
3328 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3329 /* the result must be bit */
3330 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3331 l = aopGet(AOP(left),0,FALSE,FALSE);
3335 pic14_emitcode("div","ab");
3336 pic14_emitcode("rrc","a");
3337 aopPut(AOP(result),"c",0);
3340 /*-----------------------------------------------------------------*/
3341 /* genDivOneByte : 8 bit division */
3342 /*-----------------------------------------------------------------*/
3343 static void genDivOneByte (operand *left,
3347 sym_link *opetype = operandType(result);
3353 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3354 size = AOP_SIZE(result) - 1;
3356 /* signed or unsigned */
3357 if (SPEC_USIGN(opetype)) {
3358 /* unsigned is easy */
3359 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3360 l = aopGet(AOP(left),0,FALSE,FALSE);
3362 pic14_emitcode("div","ab");
3363 aopPut(AOP(result),"a",0);
3365 aopPut(AOP(result),zero,offset++);
3369 /* signed is a little bit more difficult */
3371 /* save the signs of the operands */
3372 l = aopGet(AOP(left),0,FALSE,FALSE);
3374 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3375 pic14_emitcode("push","acc"); /* save it on the stack */
3377 /* now sign adjust for both left & right */
3378 l = aopGet(AOP(right),0,FALSE,FALSE);
3380 lbl = newiTempLabel(NULL);
3381 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3382 pic14_emitcode("cpl","a");
3383 pic14_emitcode("inc","a");
3384 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3385 pic14_emitcode("mov","b,a");
3387 /* sign adjust left side */
3388 l = aopGet(AOP(left),0,FALSE,FALSE);
3391 lbl = newiTempLabel(NULL);
3392 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3393 pic14_emitcode("cpl","a");
3394 pic14_emitcode("inc","a");
3395 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3397 /* now the division */
3398 pic14_emitcode("div","ab");
3399 /* we are interested in the lower order
3401 pic14_emitcode("mov","b,a");
3402 lbl = newiTempLabel(NULL);
3403 pic14_emitcode("pop","acc");
3404 /* if there was an over flow we don't
3405 adjust the sign of the result */
3406 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3407 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3409 pic14_emitcode("clr","a");
3410 pic14_emitcode("subb","a,b");
3411 pic14_emitcode("mov","b,a");
3412 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3414 /* now we are done */
3415 aopPut(AOP(result),"b",0);
3417 pic14_emitcode("mov","c,b.7");
3418 pic14_emitcode("subb","a,acc");
3421 aopPut(AOP(result),"a",offset++);
3425 /*-----------------------------------------------------------------*/
3426 /* genDiv - generates code for division */
3427 /*-----------------------------------------------------------------*/
3428 static void genDiv (iCode *ic)
3430 operand *left = IC_LEFT(ic);
3431 operand *right = IC_RIGHT(ic);
3432 operand *result= IC_RESULT(ic);
3435 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3436 /* assign the amsops */
3437 aopOp (left,ic,FALSE);
3438 aopOp (right,ic,FALSE);
3439 aopOp (result,ic,TRUE);
3441 /* special cases first */
3443 if (AOP_TYPE(left) == AOP_CRY &&
3444 AOP_TYPE(right)== AOP_CRY) {
3445 genDivbits(left,right,result);
3449 /* if both are of size == 1 */
3450 if (AOP_SIZE(left) == 1 &&
3451 AOP_SIZE(right) == 1 ) {
3452 genDivOneByte(left,right,result);
3456 /* should have been converted to function call */
3459 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3460 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3461 freeAsmop(result,NULL,ic,TRUE);
3464 /*-----------------------------------------------------------------*/
3465 /* genModbits :- modulus of bits */
3466 /*-----------------------------------------------------------------*/
3467 static void genModbits (operand *left,
3475 /* the result must be bit */
3476 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3477 l = aopGet(AOP(left),0,FALSE,FALSE);
3481 pic14_emitcode("div","ab");
3482 pic14_emitcode("mov","a,b");
3483 pic14_emitcode("rrc","a");
3484 aopPut(AOP(result),"c",0);
3487 /*-----------------------------------------------------------------*/
3488 /* genModOneByte : 8 bit modulus */
3489 /*-----------------------------------------------------------------*/
3490 static void genModOneByte (operand *left,
3494 sym_link *opetype = operandType(result);
3499 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3500 /* signed or unsigned */
3501 if (SPEC_USIGN(opetype)) {
3502 /* unsigned is easy */
3503 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3504 l = aopGet(AOP(left),0,FALSE,FALSE);
3506 pic14_emitcode("div","ab");
3507 aopPut(AOP(result),"b",0);
3511 /* signed is a little bit more difficult */
3513 /* save the signs of the operands */
3514 l = aopGet(AOP(left),0,FALSE,FALSE);
3517 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3518 pic14_emitcode("push","acc"); /* save it on the stack */
3520 /* now sign adjust for both left & right */
3521 l = aopGet(AOP(right),0,FALSE,FALSE);
3524 lbl = newiTempLabel(NULL);
3525 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3526 pic14_emitcode("cpl","a");
3527 pic14_emitcode("inc","a");
3528 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3529 pic14_emitcode("mov","b,a");
3531 /* sign adjust left side */
3532 l = aopGet(AOP(left),0,FALSE,FALSE);
3535 lbl = newiTempLabel(NULL);
3536 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3537 pic14_emitcode("cpl","a");
3538 pic14_emitcode("inc","a");
3539 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3541 /* now the multiplication */
3542 pic14_emitcode("div","ab");
3543 /* we are interested in the lower order
3545 lbl = newiTempLabel(NULL);
3546 pic14_emitcode("pop","acc");
3547 /* if there was an over flow we don't
3548 adjust the sign of the result */
3549 pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3550 pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3552 pic14_emitcode("clr","a");
3553 pic14_emitcode("subb","a,b");
3554 pic14_emitcode("mov","b,a");
3555 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3557 /* now we are done */
3558 aopPut(AOP(result),"b",0);
3562 /*-----------------------------------------------------------------*/
3563 /* genMod - generates code for division */
3564 /*-----------------------------------------------------------------*/
3565 static void genMod (iCode *ic)
3567 operand *left = IC_LEFT(ic);
3568 operand *right = IC_RIGHT(ic);
3569 operand *result= IC_RESULT(ic);
3572 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3573 /* assign the amsops */
3574 aopOp (left,ic,FALSE);
3575 aopOp (right,ic,FALSE);
3576 aopOp (result,ic,TRUE);
3578 /* special cases first */
3580 if (AOP_TYPE(left) == AOP_CRY &&
3581 AOP_TYPE(right)== AOP_CRY) {
3582 genModbits(left,right,result);
3586 /* if both are of size == 1 */
3587 if (AOP_SIZE(left) == 1 &&
3588 AOP_SIZE(right) == 1 ) {
3589 genModOneByte(left,right,result);
3593 /* should have been converted to function call */
3597 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3598 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3599 freeAsmop(result,NULL,ic,TRUE);
3602 /*-----------------------------------------------------------------*/
3603 /* genIfxJump :- will create a jump depending on the ifx */
3604 /*-----------------------------------------------------------------*/
3606 note: May need to add parameter to indicate when a variable is in bit space.
3608 static void genIfxJump (iCode *ic, char *jval)
3612 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3613 /* if true label then we jump if condition
3615 if ( IC_TRUE(ic) ) {
3617 if(strcmp(jval,"a") == 0)
3619 else if (strcmp(jval,"c") == 0)
3622 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3623 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3626 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3627 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3631 /* false label is present */
3632 if(strcmp(jval,"a") == 0)
3634 else if (strcmp(jval,"c") == 0)
3637 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3638 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3641 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3642 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3647 /* mark the icode as generated */
3651 /*-----------------------------------------------------------------*/
3653 /*-----------------------------------------------------------------*/
3654 static void genSkip(iCode *ifx,int status_bit)
3660 if ( IC_TRUE(ifx) ) {
3661 switch(status_bit) {
3676 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3677 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3681 switch(status_bit) {
3695 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3696 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3702 /*-----------------------------------------------------------------*/
3704 /*-----------------------------------------------------------------*/
3705 static void genSkipc(resolvedIfx *rifx)
3716 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3717 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3718 rifx->generated = 1;
3721 /*-----------------------------------------------------------------*/
3723 /*-----------------------------------------------------------------*/
3724 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3730 if( (rifx->condition ^ invert_condition) & 1)
3735 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3736 rifx->generated = 1;
3739 /*-----------------------------------------------------------------*/
3741 /*-----------------------------------------------------------------*/
3742 static void genSkipz(iCode *ifx, int condition)
3754 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3756 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3759 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3761 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3766 /*-----------------------------------------------------------------*/
3768 /*-----------------------------------------------------------------*/
3769 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3776 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3778 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3781 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3782 rifx->generated = 1;
3787 /*-----------------------------------------------------------------*/
3788 /* genChkZeroes :- greater or less than comparison */
3789 /* For each byte in a literal that is zero, inclusive or the */
3790 /* the corresponding byte in the operand with W */
3791 /* returns true if any of the bytes are zero */
3792 /*-----------------------------------------------------------------*/
3793 static int genChkZeroes(operand *op, int lit, int size)
3800 i = (lit >> (size*8)) & 0xff;
3804 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3806 emitpcode(POC_IORFW, popGet(AOP(op),size));
3816 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3817 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3818 #define DEBUGpc emitpComment
3820 /*-----------------------------------------------------------------*/
3821 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3822 /* aop (if it's NOT a literal) or from lit (if */
3823 /* aop is a literal) */
3824 /*-----------------------------------------------------------------*/
3825 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3826 if (aop->type == AOP_LIT) {
3827 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3829 emitpcode (POC_MOVFW, popGet (aop, offset));
3833 /* genCmp performs a left < right comparison, stores
3834 * the outcome in result (if != NULL) and generates
3835 * control flow code for the ifx (if != NULL).
3837 * This version leaves in sequences like
3838 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3839 * which should be optmized by the peephole
3840 * optimizer - RN 2005-01-01 */
3841 static void genCmp (operand *left,operand *right,
3842 operand *result, iCode *ifx, int sign)
3852 int invert_result = 0;
3856 assert (AOP_SIZE(left) == AOP_SIZE(right));
3857 assert (left && right);
3859 size = AOP_SIZE(right) - 1;
3860 mask = (0x100UL << (size*8)) - 1;
3861 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3866 resolveIfx (&rIfx, ifx);
3868 /**********************************************************************
3869 * handle bits - bit compares are promoted to int compares seemingly! *
3870 **********************************************************************/
3872 // THIS IS COMPLETELY UNTESTED!
3873 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3874 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3875 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3876 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3879 // 1 < {0,1} is false --> clear C by skipping the next instruction
3880 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3881 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3882 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3883 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3884 emitCLRC; // only skipped for left=0 && right=1
3886 goto correct_result_in_carry;
3890 /*************************************************
3891 * make sure that left is register (or the like) *
3892 *************************************************/
3893 if (!isAOP_REGlike(left)) {
3894 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3895 assert (isAOP_LIT(left));
3896 assert (isAOP_REGlike(right));
3897 // swap left and right
3898 // left < right <==> right > left <==> (right >= left + 1)
3899 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3901 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3902 // MAXVALUE < right? always false
3903 if (performedLt) emitCLRC; else emitSETC;
3904 goto correct_result_in_carry;
3907 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3908 // that's why we handled it above.
3915 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3916 } else if (isAOP_LIT(right)) {
3917 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3920 assert (isAOP_REGlike(left)); // left must be register or the like
3921 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3923 /*************************************************
3924 * special cases go here *
3925 *************************************************/
3927 if (isAOP_LIT(right)) {
3929 // unsigned comparison to a literal
3930 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3932 // unsigned left < 0? always false
3933 if (performedLt) emitCLRC; else emitSETC;
3934 goto correct_result_in_carry;
3937 // signed comparison to a literal
3938 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3939 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3940 // signed left < 0x80000000? always false
3941 if (performedLt) emitCLRC; else emitSETC;
3942 goto correct_result_in_carry;
3943 } else if (lit == 0) {
3944 // compare left < 0; set CARRY if SIGNBIT(left) is set
3945 if (performedLt) emitSETC; else emitCLRC;
3946 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3947 if (performedLt) emitCLRC; else emitSETC;
3948 goto correct_result_in_carry;
3951 } // right is literal
3953 /*************************************************
3954 * perform a general case comparison *
3955 * make sure we get CARRY==1 <==> left >= right *
3956 *************************************************/
3957 // compare most significant bytes
3958 //DEBUGpc ("comparing bytes at offset %d", size);
3960 // unsigned comparison
3961 pic14_mov2w_regOrLit (AOP(right), lit, size);
3962 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3964 // signed comparison
3965 // (add 2^n to both operands then perform an unsigned comparison)
3966 if (isAOP_LIT(right)) {
3967 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3968 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3970 if (litbyte == 0x80) {
3971 // left >= 0x80 -- always true, but more bytes to come
3972 mov2w (AOP(left), size);
3973 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3976 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3977 mov2w (AOP(left), size);
3978 emitpcode (POC_ADDLW, popGetLit (0x80));
3979 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3982 pCodeOp *pctemp = popGetTempReg();
3983 mov2w (AOP(left), size);
3984 emitpcode (POC_ADDLW, popGetLit (0x80));
3985 emitpcode (POC_MOVWF, pctemp);
3986 mov2w (AOP(right), size);
3987 emitpcode (POC_ADDLW, popGetLit (0x80));
3988 emitpcode (POC_SUBFW, pctemp);
3989 popReleaseTempReg(pctemp);
3993 // compare remaining bytes (treat as unsigned case from above)
3994 templbl = newiTempLabel ( NULL );
3997 //DEBUGpc ("comparing bytes at offset %d", offs);
3999 emitpcode (POC_GOTO, popGetLabel (templbl->key));
4000 pic14_mov2w_regOrLit (AOP(right), lit, offs);
4001 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4003 emitpLabel (templbl->key);
4004 goto result_in_carry;
4008 /****************************************************
4009 * now CARRY contains the result of the comparison: *
4010 * SUBWF sets CARRY iff *
4011 * F-W >= 0 <==> F >= W <==> !(F < W) *
4012 * (F=left, W=right) *
4013 ****************************************************/
4017 // value will be used in the following genSkipc()
4018 rIfx.condition ^= 1;
4021 correct_result_in_carry:
4023 // assign result to variable (if neccessary)
4024 if (result && AOP_TYPE(result) != AOP_CRY) {
4025 //DEBUGpc ("assign result");
4026 size = AOP_SIZE(result);
4028 emitpcode (POC_CLRF, popGet (AOP(result), size));
4030 if (invert_result) {
4032 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4034 emitpcode (POC_RLF, popGet (AOP(result), 0));
4038 // perform conditional jump
4040 //DEBUGpc ("generate control flow");
4048 /* OLD VERSION -- BUGGY, DO NOT USE */
4050 /*-----------------------------------------------------------------*/
4051 /* genCmp :- greater or less than comparison */
4052 /*-----------------------------------------------------------------*/
4053 static void genCmp (operand *left,operand *right,
4054 operand *result, iCode *ifx, int sign)
4056 int size; //, offset = 0 ;
4057 unsigned long lit = 0L,i = 0;
4058 resolvedIfx rFalseIfx;
4059 // resolvedIfx rTrueIfx;
4063 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4066 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4067 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4071 resolveIfx(&rFalseIfx,ifx);
4072 truelbl = newiTempLabel(NULL);
4073 size = max(AOP_SIZE(left),AOP_SIZE(right));
4075 DEBUGpic14_AopType(__LINE__,left,right,result);
4079 /* if literal is on the right then swap with left */
4080 if ((AOP_TYPE(right) == AOP_LIT)) {
4081 operand *tmp = right ;
4082 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4083 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4086 lit = (lit - 1) & mask;
4089 rFalseIfx.condition ^= 1;
4092 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4093 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4097 //if(IC_TRUE(ifx) == NULL)
4098 /* if left & right are bit variables */
4099 if (AOP_TYPE(left) == AOP_CRY &&
4100 AOP_TYPE(right) == AOP_CRY ) {
4101 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4102 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4104 /* subtract right from left if at the
4105 end the carry flag is set then we know that
4106 left is greater than right */
4108 symbol *lbl = newiTempLabel(NULL);
4111 if(AOP_TYPE(right) == AOP_LIT) {
4113 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4115 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4122 genSkipCond(&rFalseIfx,left,size-1,7);
4124 /* no need to compare to 0...*/
4125 /* NOTE: this is a de-generate compare that most certainly
4126 * creates some dead code. */
4127 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4129 if(ifx) ifx->generated = 1;
4136 //i = (lit >> (size*8)) & 0xff;
4137 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4139 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4141 i = ((0-lit) & 0xff);
4144 /* lit is 0x7f, all signed chars are less than
4145 * this except for 0x7f itself */
4146 emitpcode(POC_XORLW, popGetLit(0x7f));
4147 genSkipz2(&rFalseIfx,0);
4149 emitpcode(POC_ADDLW, popGetLit(0x80));
4150 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4151 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4156 genSkipz2(&rFalseIfx,1);
4158 emitpcode(POC_ADDLW, popGetLit(i));
4159 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4163 if(ifx) ifx->generated = 1;
4167 /* chars are out of the way. now do ints and longs */
4170 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4177 genSkipCond(&rFalseIfx,left,size,7);
4178 if(ifx) ifx->generated = 1;
4183 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4185 //rFalseIfx.condition ^= 1;
4186 //genSkipCond(&rFalseIfx,left,size,7);
4187 //rFalseIfx.condition ^= 1;
4189 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4190 if(rFalseIfx.condition)
4191 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4193 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4195 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4196 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4197 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4200 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4202 if(rFalseIfx.condition) {
4204 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4210 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4211 emitpLabel(truelbl->key);
4212 if(ifx) ifx->generated = 1;
4219 if( (lit & 0xff) == 0) {
4220 /* lower byte is zero */
4221 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4222 i = ((lit >> 8) & 0xff) ^0x80;
4223 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4224 emitpcode(POC_ADDLW, popGetLit( 0x80));
4225 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4226 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4229 if(ifx) ifx->generated = 1;
4234 /* Special cases for signed longs */
4235 if( (lit & 0xffffff) == 0) {
4236 /* lower byte is zero */
4237 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4238 i = ((lit >> 8*3) & 0xff) ^0x80;
4239 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4240 emitpcode(POC_ADDLW, popGetLit( 0x80));
4241 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4242 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4245 if(ifx) ifx->generated = 1;
4253 if(lit & (0x80 << (size*8))) {
4254 /* lit is negative */
4255 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4257 //genSkipCond(&rFalseIfx,left,size,7);
4259 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4261 if(rFalseIfx.condition)
4262 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4264 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4268 /* lit is positive */
4269 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4270 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4271 if(rFalseIfx.condition)
4272 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4274 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4278 /* There are no more special cases, so perform a general compare */
4280 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4281 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4285 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4287 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4289 //rFalseIfx.condition ^= 1;
4290 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4292 emitpLabel(truelbl->key);
4294 if(ifx) ifx->generated = 1;
4301 /* sign is out of the way. So now do an unsigned compare */
4302 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4305 /* General case - compare to an unsigned literal on the right.*/
4307 i = (lit >> (size*8)) & 0xff;
4308 emitpcode(POC_MOVLW, popGetLit(i));
4309 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4311 i = (lit >> (size*8)) & 0xff;
4314 emitpcode(POC_MOVLW, popGetLit(i));
4316 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4318 /* this byte of the lit is zero,
4319 *if it's not the last then OR in the variable */
4321 emitpcode(POC_IORFW, popGet(AOP(left),size));
4326 emitpLabel(lbl->key);
4327 //if(emitFinalCheck)
4328 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4330 emitpLabel(truelbl->key);
4332 if(ifx) ifx->generated = 1;
4339 if(AOP_TYPE(left) == AOP_LIT) {
4340 //symbol *lbl = newiTempLabel(NULL);
4342 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4345 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4348 if((lit == 0) && (sign == 0)){
4351 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4353 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4355 genSkipz2(&rFalseIfx,0);
4356 if(ifx) ifx->generated = 1;
4363 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4364 /* degenerate compare can never be true */
4365 if(rFalseIfx.condition == 0)
4366 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4368 if(ifx) ifx->generated = 1;
4373 /* signed comparisons to a literal byte */
4375 int lp1 = (lit+1) & 0xff;
4377 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4380 rFalseIfx.condition ^= 1;
4381 genSkipCond(&rFalseIfx,right,0,7);
4384 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4385 emitpcode(POC_XORLW, popGetLit(0x7f));
4386 genSkipz2(&rFalseIfx,1);
4389 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4390 emitpcode(POC_ADDLW, popGetLit(0x80));
4391 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4392 rFalseIfx.condition ^= 1;
4393 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4396 if(ifx) ifx->generated = 1;
4398 /* unsigned comparisons to a literal byte */
4400 switch(lit & 0xff ) {
4402 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4403 genSkipz2(&rFalseIfx,0);
4404 if(ifx) ifx->generated = 1;
4407 genSkipCond(&rFalseIfx,right,0,7);
4408 if(ifx) ifx->generated = 1;
4412 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4413 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4414 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4415 rFalseIfx.condition ^= 1;
4416 if (AOP_TYPE(result) == AOP_CRY) {
4417 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4418 if(ifx) ifx->generated = 1;
4420 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4421 emitpcode(POC_CLRF, popGet(AOP(result),0));
4422 emitpcode(POC_RLF, popGet(AOP(result),0));
4423 emitpcode(POC_MOVLW, popGetLit(0x01));
4424 emitpcode(POC_XORWF, popGet(AOP(result),0));
4435 /* Size is greater than 1 */
4443 /* this means lit = 0xffffffff, or -1 */
4446 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4447 rFalseIfx.condition ^= 1;
4448 genSkipCond(&rFalseIfx,right,size,7);
4449 if(ifx) ifx->generated = 1;
4456 if(rFalseIfx.condition) {
4457 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4458 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4461 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4463 emitpcode(POC_IORFW, popGet(AOP(right),size));
4467 if(rFalseIfx.condition) {
4468 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4469 emitpLabel(truelbl->key);
4471 rFalseIfx.condition ^= 1;
4472 genSkipCond(&rFalseIfx,right,s,7);
4475 if(ifx) ifx->generated = 1;
4479 if((size == 1) && (0 == (lp1&0xff))) {
4480 /* lower byte of signed word is zero */
4481 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4482 i = ((lp1 >> 8) & 0xff) ^0x80;
4483 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4484 emitpcode(POC_ADDLW, popGetLit( 0x80));
4485 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4486 rFalseIfx.condition ^= 1;
4487 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4490 if(ifx) ifx->generated = 1;
4494 if(lit & (0x80 << (size*8))) {
4495 /* Lit is less than zero */
4496 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4497 //rFalseIfx.condition ^= 1;
4498 //genSkipCond(&rFalseIfx,left,size,7);
4499 //rFalseIfx.condition ^= 1;
4500 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4501 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4503 if(rFalseIfx.condition)
4504 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4506 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4510 /* Lit is greater than or equal to zero */
4511 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4512 //rFalseIfx.condition ^= 1;
4513 //genSkipCond(&rFalseIfx,right,size,7);
4514 //rFalseIfx.condition ^= 1;
4516 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4517 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4519 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4520 if(rFalseIfx.condition)
4521 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4523 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4528 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4529 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4533 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4535 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4537 rFalseIfx.condition ^= 1;
4538 //rFalseIfx.condition = 1;
4539 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4541 emitpLabel(truelbl->key);
4543 if(ifx) ifx->generated = 1;
4548 /* compare word or long to an unsigned literal on the right.*/
4553 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4556 break; /* handled above */
4559 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4561 emitpcode(POC_IORFW, popGet(AOP(right),size));
4562 genSkipz2(&rFalseIfx,0);
4566 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4568 emitpcode(POC_IORFW, popGet(AOP(right),size));
4571 if(rFalseIfx.condition)
4572 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4574 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4577 emitpcode(POC_MOVLW, popGetLit(lit+1));
4578 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4580 rFalseIfx.condition ^= 1;
4581 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4584 emitpLabel(truelbl->key);
4586 if(ifx) ifx->generated = 1;
4592 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4593 i = (lit >> (size*8)) & 0xff;
4595 emitpcode(POC_MOVLW, popGetLit(i));
4596 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4599 i = (lit >> (size*8)) & 0xff;
4602 emitpcode(POC_MOVLW, popGetLit(i));
4604 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4606 /* this byte of the lit is zero,
4607 *if it's not the last then OR in the variable */
4609 emitpcode(POC_IORFW, popGet(AOP(right),size));
4614 emitpLabel(lbl->key);
4616 rFalseIfx.condition ^= 1;
4617 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4621 emitpLabel(truelbl->key);
4622 if(ifx) ifx->generated = 1;
4626 /* Compare two variables */
4628 DEBUGpic14_emitcode(";sign","%d",sign);
4632 /* Sigh. thus sucks... */
4634 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4635 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4636 emitpcode(POC_MOVLW, popGetLit(0x80));
4637 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4638 emitpcode(POC_XORFW, popGet(AOP(right),size));
4639 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4641 /* Signed char comparison */
4642 /* Special thanks to Nikolai Golovchenko for this snippet */
4643 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4644 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4645 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4646 emitpcode(POC_XORFW, popGet(AOP(left),0));
4647 emitpcode(POC_XORFW, popGet(AOP(right),0));
4648 emitpcode(POC_ADDLW, popGetLit(0x80));
4650 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4651 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4653 if(ifx) ifx->generated = 1;
4659 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4660 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4664 /* The rest of the bytes of a multi-byte compare */
4668 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4671 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4672 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4677 emitpLabel(lbl->key);
4679 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4680 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4681 (AOP_TYPE(result) == AOP_REG)) {
4682 emitpcode(POC_CLRF, popGet(AOP(result),0));
4683 emitpcode(POC_RLF, popGet(AOP(result),0));
4685 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4687 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4688 if(ifx) ifx->generated = 1;
4695 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4697 pic14_outBitC(result);
4699 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4700 /* if the result is used in the next
4701 ifx conditional branch then generate
4702 code a little differently */
4704 genIfxJump (ifx,"c");
4706 pic14_outBitC(result);
4707 /* leave the result in acc */
4713 /*-----------------------------------------------------------------*/
4714 /* genCmpGt :- greater than comparison */
4715 /*-----------------------------------------------------------------*/
4716 static void genCmpGt (iCode *ic, iCode *ifx)
4718 operand *left, *right, *result;
4719 sym_link *letype , *retype;
4723 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4725 right= IC_RIGHT(ic);
4726 result = IC_RESULT(ic);
4728 letype = getSpec(operandType(left));
4729 retype =getSpec(operandType(right));
4730 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4731 /* assign the amsops */
4732 aopOp (left,ic,FALSE);
4733 aopOp (right,ic,FALSE);
4734 aopOp (result,ic,TRUE);
4736 genCmp(right, left, result, ifx, sign);
4738 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4739 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4740 freeAsmop(result,NULL,ic,TRUE);
4743 /*-----------------------------------------------------------------*/
4744 /* genCmpLt - less than comparisons */
4745 /*-----------------------------------------------------------------*/
4746 static void genCmpLt (iCode *ic, iCode *ifx)
4748 operand *left, *right, *result;
4749 sym_link *letype , *retype;
4753 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4755 right= IC_RIGHT(ic);
4756 result = IC_RESULT(ic);
4758 letype = getSpec(operandType(left));
4759 retype =getSpec(operandType(right));
4760 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4762 /* assign the amsops */
4763 aopOp (left,ic,FALSE);
4764 aopOp (right,ic,FALSE);
4765 aopOp (result,ic,TRUE);
4767 genCmp(left, right, result, ifx, sign);
4769 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4770 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4771 freeAsmop(result,NULL,ic,TRUE);
4774 /*-----------------------------------------------------------------*/
4775 /* genc16bit2lit - compare a 16 bit value to a literal */
4776 /*-----------------------------------------------------------------*/
4777 static void genc16bit2lit(operand *op, int lit, int offset)
4782 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4783 if( (lit&0xff) == 0)
4788 switch( BYTEofLONG(lit,i)) {
4790 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4793 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4796 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4799 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4800 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4805 switch( BYTEofLONG(lit,i)) {
4807 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4811 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4815 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4818 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4820 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4826 /*-----------------------------------------------------------------*/
4827 /* gencjneshort - compare and jump if not equal */
4828 /*-----------------------------------------------------------------*/
4829 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4831 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4836 //unsigned long lit = 0L;
4838 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4839 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4842 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4843 DEBUGpic14_AopType(__LINE__,left,right,result);
4845 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4846 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4847 if (AOP_SIZE(result)) {
4848 for (offset = 0; offset < AOP_SIZE(result); offset++)
4849 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4852 assert (AOP_SIZE(left) == AOP_SIZE(right));
4853 //resolveIfx(&rIfx,ifx);
4854 lbl = newiTempLabel (NULL);
4857 mov2w (AOP(right),size);
4858 emitpcode (POC_XORFW, popGet (AOP(left), size));
4862 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4865 emitpLabel (lbl->key);
4866 if (AOP_SIZE(result)) {
4868 emitpcode (POC_INCF, popGet (AOP(result), 0));
4871 genSkipz (ifx, NULL != IC_TRUE(ifx));
4878 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4879 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4880 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4881 for (offset=0; offset < AOP_SIZE(result); offset++)
4883 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4888 /* if the left side is a literal or
4889 if the right is in a pointer register and left
4891 if ((AOP_TYPE(left) == AOP_LIT) ||
4892 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4897 if(AOP_TYPE(right) == AOP_LIT)
4898 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4900 /* if the right side is a literal then anything goes */
4901 if (AOP_TYPE(right) == AOP_LIT &&
4902 AOP_TYPE(left) != AOP_DIR ) {
4905 genc16bit2lit(left, lit, 0);
4907 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4913 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4914 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4916 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4920 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4928 /* if the right side is in a register or in direct space or
4929 if the left is a pointer register & right is not */
4930 else if (AOP_TYPE(right) == AOP_REG ||
4931 AOP_TYPE(right) == AOP_DIR ||
4932 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4933 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4934 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4935 int lbl_key = lbl->key;
4938 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4939 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4940 __FUNCTION__,__LINE__);
4944 /* switch(size) { */
4946 /* genc16bit2lit(left, lit, 0); */
4948 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4954 if((AOP_TYPE(left) == AOP_DIR) &&
4955 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4957 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4958 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4960 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4962 switch (lit & 0xff) {
4964 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4967 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4968 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4969 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4973 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4974 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4975 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4976 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4980 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4981 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4986 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4989 if(AOP_TYPE(result) == AOP_CRY) {
4990 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4995 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4997 /* fix me. probably need to check result size too */
4998 //emitpcode(POC_CLRF,popGet(AOP(result),0));
5003 emitpcode(POC_GOTO,popGetLabel(lbl_key));
5013 } else if(AOP_TYPE(right) == AOP_REG &&
5014 AOP_TYPE(left) != AOP_DIR){
5018 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5019 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5020 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5025 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5030 /* right is a pointer reg need both a & b */
5033 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5035 pic14_emitcode("mov","b,%s",l);
5036 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5037 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5042 emitpcode(POC_INCF,popGet(AOP(result),0));
5044 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5046 emitpLabel(lbl->key);
5048 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5056 /*-----------------------------------------------------------------*/
5057 /* gencjne - compare and jump if not equal */
5058 /*-----------------------------------------------------------------*/
5059 static void gencjne(operand *left, operand *right, iCode *ifx)
5061 symbol *tlbl = newiTempLabel(NULL);
5063 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5064 gencjneshort(left, right, lbl);
5066 pic14_emitcode("mov","a,%s",one);
5067 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5068 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5069 pic14_emitcode("clr","a");
5070 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5072 emitpLabel(lbl->key);
5073 emitpLabel(tlbl->key);
5078 /*-----------------------------------------------------------------*/
5079 /* genCmpEq - generates code for equal to */
5080 /*-----------------------------------------------------------------*/
5081 static void genCmpEq (iCode *ic, iCode *ifx)
5083 operand *left, *right, *result;
5084 unsigned long lit = 0L;
5088 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5091 DEBUGpic14_emitcode ("; ifx is non-null","");
5093 DEBUGpic14_emitcode ("; ifx is null","");
5095 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5096 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5097 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5099 size = max(AOP_SIZE(left),AOP_SIZE(right));
5101 DEBUGpic14_AopType(__LINE__,left,right,result);
5103 /* if literal, literal on the right or
5104 if the right is in a pointer register and left
5106 if (aop_isLitLike (AOP(IC_LEFT(ic)))
5107 || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5108 operand *tmp = right ;
5114 if(ifx && !AOP_SIZE(result)){
5116 /* if they are both bit variables */
5117 if (AOP_TYPE(left) == AOP_CRY &&
5118 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5119 if(AOP_TYPE(right) == AOP_LIT){
5120 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5122 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5123 pic14_emitcode("cpl","c");
5124 } else if(lit == 1L) {
5125 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5127 pic14_emitcode("clr","c");
5129 /* AOP_TYPE(right) == AOP_CRY */
5131 symbol *lbl = newiTempLabel(NULL);
5132 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5133 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5134 pic14_emitcode("cpl","c");
5135 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5137 /* if true label then we jump if condition
5139 tlbl = newiTempLabel(NULL);
5140 if ( IC_TRUE(ifx) ) {
5141 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
5142 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5144 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
5145 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5147 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5150 /* left and right are both bit variables, result is carry */
5153 resolveIfx(&rIfx,ifx);
5155 emitpcode(POC_MOVLW,popGet(AOP(left),0));
5156 emitpcode(POC_ANDFW,popGet(AOP(left),0));
5157 emitpcode(POC_BTFSC,popGet(AOP(right),0));
5158 emitpcode(POC_ANDLW,popGet(AOP(left),0));
5163 /* They're not both bit variables. Is the right a literal? */
5164 if(AOP_TYPE(right) == AOP_LIT) {
5165 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5170 switch(lit & 0xff) {
5172 if ( IC_TRUE(ifx) ) {
5173 emitpcode(POC_DECFW,popGet(AOP(left),offset));
5175 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5177 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5178 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5182 if ( IC_TRUE(ifx) ) {
5183 emitpcode(POC_INCFW,popGet(AOP(left),offset));
5185 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5187 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5188 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5192 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5194 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5199 /* end of size == 1 */
5203 genc16bit2lit(left,lit,offset);
5206 /* end of size == 2 */
5211 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5212 emitpcode(POC_IORFW,popGet(AOP(left),1));
5213 emitpcode(POC_IORFW,popGet(AOP(left),2));
5214 emitpcode(POC_IORFW,popGet(AOP(left),3));
5218 /* search for patterns that can be optimized */
5220 genc16bit2lit(left,lit,0);
5223 genSkipz(ifx,IC_TRUE(ifx) == NULL);
5225 genc16bit2lit(left,lit,2);
5227 emitpcode(POC_IORFW,popGet(AOP(left),2));
5228 emitpcode(POC_IORFW,popGet(AOP(left),3));
5241 } else if(AOP_TYPE(right) == AOP_CRY ) {
5242 /* we know the left is not a bit, but that the right is */
5243 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5244 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5245 popGet(AOP(right),offset));
5246 emitpcode(POC_XORLW,popGetLit(1));
5248 /* if the two are equal, then W will be 0 and the Z bit is set
5249 * we could test Z now, or go ahead and check the high order bytes if
5250 * the variable we're comparing is larger than a byte. */
5253 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5255 if ( IC_TRUE(ifx) ) {
5257 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5258 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5261 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5262 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5266 /* They're both variables that are larger than bits */
5269 tlbl = newiTempLabel(NULL);
5272 mov2w (AOP(right),offset); /* right might be litLike() */
5273 emitpcode(POC_XORFW,popGet(AOP(left),offset));
5275 if ( IC_TRUE(ifx) ) {
5278 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5279 pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5282 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5283 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5287 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5288 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5292 if(s>1 && IC_TRUE(ifx)) {
5293 emitpLabel(tlbl->key);
5294 pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5298 /* mark the icode as generated */
5303 /* if they are both bit variables */
5304 if (AOP_TYPE(left) == AOP_CRY &&
5305 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5306 if(AOP_TYPE(right) == AOP_LIT){
5307 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5309 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5310 pic14_emitcode("cpl","c");
5311 } else if(lit == 1L) {
5312 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5314 pic14_emitcode("clr","c");
5316 /* AOP_TYPE(right) == AOP_CRY */
5318 symbol *lbl = newiTempLabel(NULL);
5319 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5320 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5321 pic14_emitcode("cpl","c");
5322 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5325 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5326 pic14_outBitC(result);
5330 genIfxJump (ifx,"c");
5333 /* if the result is used in an arithmetic operation
5334 then put the result in place */
5335 pic14_outBitC(result);
5338 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5339 gencjne(left,right,result,ifx);
5342 gencjne(left,right,newiTempLabel(NULL));
5344 if(IC_TRUE(ifx)->key)
5345 gencjne(left,right,IC_TRUE(ifx)->key);
5347 gencjne(left,right,IC_FALSE(ifx)->key);
5351 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5352 aopPut(AOP(result),"a",0);
5357 genIfxJump (ifx,"a");
5361 /* if the result is used in an arithmetic operation
5362 then put the result in place */
5364 if (AOP_TYPE(result) != AOP_CRY)
5365 pic14_outAcc(result);
5367 /* leave the result in acc */
5371 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5372 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5373 freeAsmop(result,NULL,ic,TRUE);
5376 /*-----------------------------------------------------------------*/
5377 /* ifxForOp - returns the icode containing the ifx for operand */
5378 /*-----------------------------------------------------------------*/
5379 static iCode *ifxForOp ( operand *op, iCode *ic )
5382 /* if true symbol then needs to be assigned */
5383 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5384 if (IS_TRUE_SYMOP(op))
5387 /* if this has register type condition and
5388 the next instruction is ifx with the same operand
5389 and live to of the operand is upto the ifx only then */
5391 ic->next->op == IFX &&
5392 IC_COND(ic->next)->key == op->key &&
5393 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5397 ic->next->op == IFX &&
5398 IC_COND(ic->next)->key == op->key) {
5399 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5403 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5405 ic->next->op == IFX)
5406 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5409 ic->next->op == IFX &&
5410 IC_COND(ic->next)->key == op->key) {
5411 DEBUGpic14_emitcode ("; "," key is okay");
5412 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5413 OP_SYMBOL(op)->liveTo,
5420 /*-----------------------------------------------------------------*/
5421 /* genAndOp - for && operation */
5422 /*-----------------------------------------------------------------*/
5423 static void genAndOp (iCode *ic)
5425 operand *left,*right, *result;
5429 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5430 /* note here that && operations that are in an
5431 if statement are taken away by backPatchLabels
5432 only those used in arthmetic operations remain */
5433 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5434 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5435 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5437 DEBUGpic14_AopType(__LINE__,left,right,result);
5439 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5440 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5441 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5443 /* if both are bit variables */
5444 /* if (AOP_TYPE(left) == AOP_CRY && */
5445 /* AOP_TYPE(right) == AOP_CRY ) { */
5446 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5447 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5448 /* pic14_outBitC(result); */
5450 /* tlbl = newiTempLabel(NULL); */
5451 /* pic14_toBoolean(left); */
5452 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5453 /* pic14_toBoolean(right); */
5454 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5455 /* pic14_outBitAcc(result); */
5458 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5459 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5460 freeAsmop(result,NULL,ic,TRUE);
5464 /*-----------------------------------------------------------------*/
5465 /* genOrOp - for || operation */
5466 /*-----------------------------------------------------------------*/
5469 modified this code, but it doesn't appear to ever get called
5472 static void genOrOp (iCode *ic)
5474 operand *left,*right, *result;
5477 /* note here that || operations that are in an
5478 if statement are taken away by backPatchLabels
5479 only those used in arthmetic operations remain */
5481 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5482 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5483 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5484 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5486 DEBUGpic14_AopType(__LINE__,left,right,result);
5488 /* if both are bit variables */
5489 if (AOP_TYPE(left) == AOP_CRY &&
5490 AOP_TYPE(right) == AOP_CRY ) {
5491 pic14_emitcode("clrc","");
5492 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5493 AOP(left)->aopu.aop_dir,
5494 AOP(left)->aopu.aop_dir);
5495 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5496 AOP(right)->aopu.aop_dir,
5497 AOP(right)->aopu.aop_dir);
5498 pic14_emitcode("setc","");
5501 tlbl = newiTempLabel(NULL);
5502 pic14_toBoolean(left);
5504 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5505 pic14_toBoolean(right);
5506 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5508 pic14_outBitAcc(result);
5511 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5512 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5513 freeAsmop(result,NULL,ic,TRUE);
5516 /*-----------------------------------------------------------------*/
5517 /* isLiteralBit - test if lit == 2^n */
5518 /*-----------------------------------------------------------------*/
5519 static int isLiteralBit(unsigned long lit)
5521 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5522 0x100L,0x200L,0x400L,0x800L,
5523 0x1000L,0x2000L,0x4000L,0x8000L,
5524 0x10000L,0x20000L,0x40000L,0x80000L,
5525 0x100000L,0x200000L,0x400000L,0x800000L,
5526 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5527 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5531 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5532 for(idx = 0; idx < 32; idx++)
5538 /*-----------------------------------------------------------------*/
5539 /* continueIfTrue - */
5540 /*-----------------------------------------------------------------*/
5541 static void continueIfTrue (iCode *ic)
5544 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5546 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5550 /*-----------------------------------------------------------------*/
5552 /*-----------------------------------------------------------------*/
5553 static void jumpIfTrue (iCode *ic)
5556 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5558 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5562 /*-----------------------------------------------------------------*/
5563 /* jmpTrueOrFalse - */
5564 /*-----------------------------------------------------------------*/
5565 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5568 // ugly but optimized by peephole
5569 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5571 symbol *nlbl = newiTempLabel(NULL);
5572 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5573 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5574 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5575 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5578 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5579 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5584 /*-----------------------------------------------------------------*/
5585 /* genAnd - code for and */
5586 /*-----------------------------------------------------------------*/
5587 static void genAnd (iCode *ic, iCode *ifx)
5589 operand *left, *right, *result;
5591 unsigned long lit = 0L;
5596 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5597 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5598 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5599 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5601 resolveIfx(&rIfx,ifx);
5603 /* if left is a literal & right is not then exchange them */
5604 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5605 AOP_NEEDSACC(left)) {
5606 operand *tmp = right ;
5611 /* if result = right then exchange them */
5612 if(pic14_sameRegs(AOP(result),AOP(right))){
5613 operand *tmp = right ;
5618 /* if right is bit then exchange them */
5619 if (AOP_TYPE(right) == AOP_CRY &&
5620 AOP_TYPE(left) != AOP_CRY){
5621 operand *tmp = right ;
5625 if(AOP_TYPE(right) == AOP_LIT)
5626 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5628 size = AOP_SIZE(result);
5630 DEBUGpic14_AopType(__LINE__,left,right,result);
5633 // result = bit & yy;
5634 if (AOP_TYPE(left) == AOP_CRY){
5635 // c = bit & literal;
5636 if(AOP_TYPE(right) == AOP_LIT){
5638 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5641 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5644 if(size && (AOP_TYPE(result) == AOP_CRY)){
5645 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5648 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5652 pic14_emitcode("clr","c");
5655 if (AOP_TYPE(right) == AOP_CRY){
5657 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5658 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5661 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5663 pic14_emitcode("rrc","a");
5664 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5670 pic14_outBitC(result);
5672 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5673 genIfxJump(ifx, "c");
5677 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5678 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5679 if((AOP_TYPE(right) == AOP_LIT) &&
5680 (AOP_TYPE(result) == AOP_CRY) &&
5681 (AOP_TYPE(left) != AOP_CRY)){
5682 int posbit = isLiteralBit(lit);
5686 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5689 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5694 while (posbit > 7) {
5698 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5699 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5700 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5707 symbol *tlbl = newiTempLabel(NULL);
5708 int sizel = AOP_SIZE(left);
5710 pic14_emitcode("setb","c");
5712 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5713 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5715 if((posbit = isLiteralBit(bytelit)) != 0)
5716 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5718 if(bytelit != 0x0FFL)
5719 pic14_emitcode("anl","a,%s",
5720 aopGet(AOP(right),offset,FALSE,TRUE));
5721 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5726 // bit = left & literal
5728 pic14_emitcode("clr","c");
5729 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5731 // if(left & literal)
5734 jmpTrueOrFalse(ifx, tlbl);
5738 pic14_outBitC(result);
5742 /* if left is same as result */
5743 if(pic14_sameRegs(AOP(result),AOP(left))){
5745 for(;size--; offset++,lit>>=8) {
5746 if(AOP_TYPE(right) == AOP_LIT){
5747 switch(lit & 0xff) {
5749 /* and'ing with 0 has clears the result */
5750 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5753 /* and'ing with 0xff is a nop when the result and left are the same */
5758 int p = my_powof2( (~lit) & 0xff );
5760 /* only one bit is set in the literal, so use a bcf instruction */
5761 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5764 if(know_W != (int)(lit&0xff))
5765 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5767 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5772 if (AOP_TYPE(left) == AOP_ACC) {
5773 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5775 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5776 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5783 // left & result in different registers
5784 if(AOP_TYPE(result) == AOP_CRY){
5786 // if(size), result in bit
5787 // if(!size && ifx), conditional oper: if(left & right)
5788 symbol *tlbl = newiTempLabel(NULL);
5789 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5791 pic14_emitcode("setb","c");
5793 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5794 pic14_emitcode("anl","a,%s",
5795 aopGet(AOP(left),offset,FALSE,FALSE));
5796 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5801 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5802 pic14_outBitC(result);
5804 jmpTrueOrFalse(ifx, tlbl);
5806 for(;(size--);offset++) {
5808 // result = left & right
5809 if(AOP_TYPE(right) == AOP_LIT){
5810 int t = (lit >> (offset*8)) & 0x0FFL;
5813 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5816 if(AOP_TYPE(left) != AOP_ACC) {
5817 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5819 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5822 if(AOP_TYPE(left) == AOP_ACC) {
5823 emitpcode(POC_ANDLW, popGetLit(t));
5825 emitpcode(POC_MOVLW, popGetLit(t));
5826 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5828 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5833 if (AOP_TYPE(left) == AOP_ACC) {
5834 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5836 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5837 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5839 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5845 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5846 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5847 freeAsmop(result,NULL,ic,TRUE);
5850 /*-----------------------------------------------------------------*/
5851 /* genOr - code for or */
5852 /*-----------------------------------------------------------------*/
5853 static void genOr (iCode *ic, iCode *ifx)
5855 operand *left, *right, *result;
5857 unsigned long lit = 0L;
5860 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5862 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5863 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5864 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5866 DEBUGpic14_AopType(__LINE__,left,right,result);
5868 /* if left is a literal & right is not then exchange them */
5869 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5870 AOP_NEEDSACC(left)) {
5871 operand *tmp = right ;
5876 /* if result = right then exchange them */
5877 if(pic14_sameRegs(AOP(result),AOP(right))){
5878 operand *tmp = right ;
5883 /* if right is bit then exchange them */
5884 if (AOP_TYPE(right) == AOP_CRY &&
5885 AOP_TYPE(left) != AOP_CRY){
5886 operand *tmp = right ;
5891 DEBUGpic14_AopType(__LINE__,left,right,result);
5893 if(AOP_TYPE(right) == AOP_LIT)
5894 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5896 size = AOP_SIZE(result);
5900 if (AOP_TYPE(left) == AOP_CRY){
5901 if(AOP_TYPE(right) == AOP_LIT){
5902 // c = bit & literal;
5904 // lit != 0 => result = 1
5905 if(AOP_TYPE(result) == AOP_CRY){
5907 emitpcode(POC_BSF, popGet(AOP(result),0));
5908 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5909 // AOP(result)->aopu.aop_dir,
5910 // AOP(result)->aopu.aop_dir);
5912 continueIfTrue(ifx);
5916 // lit == 0 => result = left
5917 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5919 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5922 if (AOP_TYPE(right) == AOP_CRY){
5923 if(pic14_sameRegs(AOP(result),AOP(left))){
5925 emitpcode(POC_BCF, popGet(AOP(result),0));
5926 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5927 emitpcode(POC_BSF, popGet(AOP(result),0));
5929 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5930 AOP(result)->aopu.aop_dir,
5931 AOP(result)->aopu.aop_dir);
5932 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5933 AOP(right)->aopu.aop_dir,
5934 AOP(right)->aopu.aop_dir);
5935 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5936 AOP(result)->aopu.aop_dir,
5937 AOP(result)->aopu.aop_dir);
5939 if( AOP_TYPE(result) == AOP_ACC) {
5940 emitpcode(POC_MOVLW, popGetLit(0));
5941 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5942 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5943 emitpcode(POC_MOVLW, popGetLit(1));
5947 emitpcode(POC_BCF, popGet(AOP(result),0));
5948 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5949 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5950 emitpcode(POC_BSF, popGet(AOP(result),0));
5952 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5953 AOP(result)->aopu.aop_dir,
5954 AOP(result)->aopu.aop_dir);
5955 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5956 AOP(right)->aopu.aop_dir,
5957 AOP(right)->aopu.aop_dir);
5958 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5959 AOP(left)->aopu.aop_dir,
5960 AOP(left)->aopu.aop_dir);
5961 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5962 AOP(result)->aopu.aop_dir,
5963 AOP(result)->aopu.aop_dir);
5968 symbol *tlbl = newiTempLabel(NULL);
5969 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5972 emitpcode(POC_BCF, popGet(AOP(result),0));
5973 if( AOP_TYPE(right) == AOP_ACC) {
5974 emitpcode(POC_IORLW, popGetLit(0));
5976 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5977 emitpcode(POC_BSF, popGet(AOP(result),0));
5982 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5983 pic14_emitcode(";XXX setb","c");
5984 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5985 AOP(left)->aopu.aop_dir,tlbl->key+100);
5986 pic14_toBoolean(right);
5987 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5988 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5989 jmpTrueOrFalse(ifx, tlbl);
5993 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6000 pic14_outBitC(result);
6002 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6003 genIfxJump(ifx, "c");
6007 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6008 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6009 if((AOP_TYPE(right) == AOP_LIT) &&
6010 (AOP_TYPE(result) == AOP_CRY) &&
6011 (AOP_TYPE(left) != AOP_CRY)){
6013 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6016 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6018 continueIfTrue(ifx);
6021 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6022 // lit = 0, result = boolean(left)
6024 pic14_emitcode(";XXX setb","c");
6025 pic14_toBoolean(right);
6027 symbol *tlbl = newiTempLabel(NULL);
6028 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6030 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6032 genIfxJump (ifx,"a");
6036 pic14_outBitC(result);
6040 /* if left is same as result */
6041 if(pic14_sameRegs(AOP(result),AOP(left))){
6043 for(;size--; offset++,lit>>=8) {
6044 if(AOP_TYPE(right) == AOP_LIT){
6045 if((lit & 0xff) == 0)
6046 /* or'ing with 0 has no effect */
6049 int p = my_powof2(lit & 0xff);
6051 /* only one bit is set in the literal, so use a bsf instruction */
6053 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6055 if(know_W != (int)(lit & 0xff))
6056 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6057 know_W = lit & 0xff;
6058 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6063 if (AOP_TYPE(left) == AOP_ACC) {
6064 emitpcode(POC_IORFW, popGet(AOP(right),offset));
6065 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6067 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
6068 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6070 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6071 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6077 // left & result in different registers
6078 if(AOP_TYPE(result) == AOP_CRY){
6080 // if(size), result in bit
6081 // if(!size && ifx), conditional oper: if(left | right)
6082 symbol *tlbl = newiTempLabel(NULL);
6083 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6084 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6088 pic14_emitcode(";XXX setb","c");
6090 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6091 pic14_emitcode(";XXX orl","a,%s",
6092 aopGet(AOP(left),offset,FALSE,FALSE));
6093 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6098 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6099 pic14_outBitC(result);
6101 jmpTrueOrFalse(ifx, tlbl);
6102 } else for(;(size--);offset++){
6104 // result = left | right
6105 if(AOP_TYPE(right) == AOP_LIT){
6106 int t = (lit >> (offset*8)) & 0x0FFL;
6109 if (AOP_TYPE(left) != AOP_ACC) {
6110 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
6112 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6116 if (AOP_TYPE(left) == AOP_ACC) {
6117 emitpcode(POC_IORLW, popGetLit(t));
6119 emitpcode(POC_MOVLW, popGetLit(t));
6120 emitpcode(POC_IORFW, popGet(AOP(left),offset));
6122 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6127 // faster than result <- left, anl result,right
6128 // and better if result is SFR
6129 if (AOP_TYPE(left) == AOP_ACC) {
6130 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6132 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6133 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6135 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6140 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6141 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6142 freeAsmop(result,NULL,ic,TRUE);
6145 /*-----------------------------------------------------------------*/
6146 /* genXor - code for xclusive or */
6147 /*-----------------------------------------------------------------*/
6148 static void genXor (iCode *ic, iCode *ifx)
6150 operand *left, *right, *result;
6152 unsigned long lit = 0L;
6155 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6157 aopOp((left = IC_LEFT(ic)),ic,FALSE);
6158 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6159 aopOp((result=IC_RESULT(ic)),ic,TRUE);
6161 /* if left is a literal & right is not ||
6162 if left needs acc & right does not */
6163 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6164 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6165 operand *tmp = right ;
6170 /* if result = right then exchange them */
6171 if(pic14_sameRegs(AOP(result),AOP(right))){
6172 operand *tmp = right ;
6177 /* if right is bit then exchange them */
6178 if (AOP_TYPE(right) == AOP_CRY &&
6179 AOP_TYPE(left) != AOP_CRY){
6180 operand *tmp = right ;
6184 if(AOP_TYPE(right) == AOP_LIT)
6185 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6187 size = AOP_SIZE(result);
6191 if (AOP_TYPE(left) == AOP_CRY){
6192 if(AOP_TYPE(right) == AOP_LIT){
6193 // c = bit & literal;
6195 // lit>>1 != 0 => result = 1
6196 if(AOP_TYPE(result) == AOP_CRY){
6198 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6199 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6201 continueIfTrue(ifx);
6204 pic14_emitcode("setb","c");
6208 // lit == 0, result = left
6209 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6211 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6213 // lit == 1, result = not(left)
6214 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6215 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6216 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6217 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6220 assert ( !"incomplete genXor" );
6221 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6222 pic14_emitcode("cpl","c");
6229 symbol *tlbl = newiTempLabel(NULL);
6230 if (AOP_TYPE(right) == AOP_CRY){
6232 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6235 int sizer = AOP_SIZE(right);
6237 // if val>>1 != 0, result = 1
6238 pic14_emitcode("setb","c");
6240 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6242 // test the msb of the lsb
6243 pic14_emitcode("anl","a,#0xfe");
6244 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6248 pic14_emitcode("rrc","a");
6250 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6251 pic14_emitcode("cpl","c");
6252 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6257 pic14_outBitC(result);
6259 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6260 genIfxJump(ifx, "c");
6264 if(pic14_sameRegs(AOP(result),AOP(left))){
6265 /* if left is same as result */
6266 for(;size--; offset++) {
6267 if(AOP_TYPE(right) == AOP_LIT){
6268 int t = (lit >> (offset*8)) & 0x0FFL;
6272 if (IS_AOP_PREG(left)) {
6273 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6274 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6275 aopPut(AOP(result),"a",offset);
6277 emitpcode(POC_MOVLW, popGetLit(t));
6278 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6279 pic14_emitcode("xrl","%s,%s",
6280 aopGet(AOP(left),offset,FALSE,TRUE),
6281 aopGet(AOP(right),offset,FALSE,FALSE));
6284 if (AOP_TYPE(left) == AOP_ACC)
6285 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6287 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6288 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6290 if (IS_AOP_PREG(left)) {
6291 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6292 aopPut(AOP(result),"a",offset);
6294 pic14_emitcode("xrl","%s,a",
6295 aopGet(AOP(left),offset,FALSE,TRUE));
6301 // left & result in different registers
6302 if(AOP_TYPE(result) == AOP_CRY){
6304 // if(size), result in bit
6305 // if(!size && ifx), conditional oper: if(left ^ right)
6306 symbol *tlbl = newiTempLabel(NULL);
6307 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6309 pic14_emitcode("setb","c");
6311 if((AOP_TYPE(right) == AOP_LIT) &&
6312 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6313 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6315 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6316 pic14_emitcode("xrl","a,%s",
6317 aopGet(AOP(left),offset,FALSE,FALSE));
6319 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6324 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6325 pic14_outBitC(result);
6327 jmpTrueOrFalse(ifx, tlbl);
6328 } else for(;(size--);offset++){
6330 // result = left & right
6331 if(AOP_TYPE(right) == AOP_LIT){
6332 int t = (lit >> (offset*8)) & 0x0FFL;
6335 if (AOP_TYPE(left) != AOP_ACC) {
6336 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6338 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6339 pic14_emitcode("movf","%s,w",
6340 aopGet(AOP(left),offset,FALSE,FALSE));
6341 pic14_emitcode("movwf","%s",
6342 aopGet(AOP(result),offset,FALSE,FALSE));
6345 if (AOP_TYPE(left) == AOP_ACC) {
6346 emitpcode(POC_XORLW, popGetLit(t));
6348 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6350 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6353 if (AOP_TYPE(left) == AOP_ACC) {
6354 emitpcode(POC_XORLW, popGetLit(t));
6356 emitpcode(POC_MOVLW, popGetLit(t));
6357 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6359 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6360 pic14_emitcode("movlw","0x%x",t);
6361 pic14_emitcode("xorwf","%s,w",
6362 aopGet(AOP(left),offset,FALSE,FALSE));
6363 pic14_emitcode("movwf","%s",
6364 aopGet(AOP(result),offset,FALSE,FALSE));
6370 // faster than result <- left, anl result,right
6371 // and better if result is SFR
6372 if (AOP_TYPE(left) == AOP_ACC) {
6373 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6375 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6376 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6378 if ( AOP_TYPE(result) != AOP_ACC){
6379 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6385 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6386 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6387 freeAsmop(result,NULL,ic,TRUE);
6390 /*-----------------------------------------------------------------*/
6391 /* genInline - write the inline code out */
6392 /*-----------------------------------------------------------------*/
6393 static void genInline (iCode *ic)
6395 char *buffer, *bp, *bp1;
6398 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6400 _G.inLine += (!options.asmpeep);
6402 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6403 strcpy(buffer,IC_INLINE(ic));
6405 /* emit each line as a code */
6411 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6419 /* print label, use this special format with NULL directive
6420 * to denote that the argument should not be indented with tab */
6421 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6428 if ((bp1 != bp) && *bp1)
6429 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6433 _G.inLine -= (!options.asmpeep);
6436 /*-----------------------------------------------------------------*/
6437 /* genRRC - rotate right with carry */
6438 /*-----------------------------------------------------------------*/
6439 static void genRRC (iCode *ic)
6441 operand *left , *result ;
6442 int size, offset = 0, same;
6445 /* rotate right with carry */
6447 result=IC_RESULT(ic);
6448 aopOp (left,ic,FALSE);
6449 aopOp (result,ic,FALSE);
6451 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6453 same = pic14_sameRegs(AOP(result),AOP(left));
6455 size = AOP_SIZE(result);
6457 /* get the lsb and put it into the carry */
6458 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6465 emitpcode(POC_RRF, popGet(AOP(left),offset));
6467 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6468 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6474 freeAsmop(left,NULL,ic,TRUE);
6475 freeAsmop(result,NULL,ic,TRUE);
6478 /*-----------------------------------------------------------------*/
6479 /* genRLC - generate code for rotate left with carry */
6480 /*-----------------------------------------------------------------*/
6481 static void genRLC (iCode *ic)
6483 operand *left , *result ;
6484 int size, offset = 0;
6488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6489 /* rotate right with carry */
6491 result=IC_RESULT(ic);
6492 aopOp (left,ic,FALSE);
6493 aopOp (result,ic,FALSE);
6495 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6497 same = pic14_sameRegs(AOP(result),AOP(left));
6499 /* move it to the result */
6500 size = AOP_SIZE(result);
6502 /* get the msb and put it into the carry */
6503 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6510 emitpcode(POC_RLF, popGet(AOP(left),offset));
6512 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6513 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6520 freeAsmop(left,NULL,ic,TRUE);
6521 freeAsmop(result,NULL,ic,TRUE);
6524 /*-----------------------------------------------------------------*/
6525 /* genGetHbit - generates code get highest order bit */
6526 /*-----------------------------------------------------------------*/
6527 static void genGetHbit (iCode *ic)
6529 operand *left, *result;
6531 result=IC_RESULT(ic);
6532 aopOp (left,ic,FALSE);
6533 aopOp (result,ic,FALSE);
6536 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6537 /* get the highest order byte into a */
6538 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6539 if(AOP_TYPE(result) == AOP_CRY){
6540 pic14_emitcode("rlc","a");
6541 pic14_outBitC(result);
6544 pic14_emitcode("rl","a");
6545 pic14_emitcode("anl","a,#0x01");
6546 pic14_outAcc(result);
6550 freeAsmop(left,NULL,ic,TRUE);
6551 freeAsmop(result,NULL,ic,TRUE);
6554 /*-----------------------------------------------------------------*/
6555 /* AccRol - rotate left accumulator by known count */
6556 /*-----------------------------------------------------------------*/
6557 static void AccRol (operand *op,int offset,int shCount)
6560 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6561 shCount &= 0x0007; // shCount : 0..7
6566 pic14_emitcode("rl","a");
6567 emitpcode(POC_RLF,popGet(AOP(op),offset));
6570 pic14_emitcode("rl","a");
6571 pic14_emitcode("rl","a");
6572 emitpcode(POC_RLF,popGet(AOP(op),offset));
6573 emitpcode(POC_RLF,popGet(AOP(op),offset));
6576 pic14_emitcode("swap","a");
6577 pic14_emitcode("rr","a");
6578 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6579 emitpcode(POC_RRF,popGet(AOP(op),offset));
6582 pic14_emitcode("swap","a");
6583 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6586 pic14_emitcode("swap","a");
6587 pic14_emitcode("rl","a");
6588 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6589 emitpcode(POC_RLF,popGet(AOP(op),offset));
6592 pic14_emitcode("rr","a");
6593 pic14_emitcode("rr","a");
6594 emitpcode(POC_RRF,popGet(AOP(op),offset));
6595 emitpcode(POC_RRF,popGet(AOP(op),offset));
6598 pic14_emitcode("rr","a");
6599 emitpcode(POC_RRF,popGet(AOP(op),offset));
6604 /*-----------------------------------------------------------------*/
6605 /* AccLsh - left shift accumulator by known count */
6606 /*-----------------------------------------------------------------*/
6607 static void AccLsh (operand *op,int offset,int shCount)
6610 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6615 emitpcode (POC_RLF, popGet (AOP(op), 0));
6617 /* rotate left accumulator */
6618 AccRol(op,offset,shCount);
6619 /* and kill the lower order bits */
6620 emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6621 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6626 /*-----------------------------------------------------------------*/
6627 /* AccRsh - right shift accumulator by known count */
6628 /*-----------------------------------------------------------------*/
6629 static void AccRsh (operand *op,int offset,int shCount)
6632 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6636 emitpcode (POC_RRF, popGet (AOP(op), 0));
6638 /* rotate right accumulator */
6639 AccRol(op,offset,8 - shCount);
6640 /* and kill the higher order bits */
6641 emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6642 emitpcode (POC_ANDWF, popGet (AOP(op),0));
6648 /*-----------------------------------------------------------------*/
6649 /* AccSRsh - signed right shift accumulator by known count */
6650 /*-----------------------------------------------------------------*/
6651 static void AccSRsh (int shCount)
6654 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6657 pic14_emitcode("mov","c,acc.7");
6658 pic14_emitcode("rrc","a");
6659 } else if(shCount == 2){
6660 pic14_emitcode("mov","c,acc.7");
6661 pic14_emitcode("rrc","a");
6662 pic14_emitcode("mov","c,acc.7");
6663 pic14_emitcode("rrc","a");
6665 tlbl = newiTempLabel(NULL);
6666 /* rotate right accumulator */
6667 AccRol(8 - shCount);
6668 /* and kill the higher order bits */
6669 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6670 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6671 pic14_emitcode("orl","a,#0x%02x",
6672 (unsigned char)~SRMask[shCount]);
6673 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6678 /*-----------------------------------------------------------------*/
6679 /* shiftR1Left2Result - shift right one byte from left to result */
6680 /*-----------------------------------------------------------------*/
6681 static void shiftR1Left2ResultSigned (operand *left, int offl,
6682 operand *result, int offr,
6688 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6690 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6694 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6696 emitpcode(POC_RRF, popGet(AOP(result),offr));
6698 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6699 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6705 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6707 emitpcode(POC_RRF, popGet(AOP(result),offr));
6709 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6710 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6712 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6713 emitpcode(POC_RRF, popGet(AOP(result),offr));
6719 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6721 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6725 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6726 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6727 emitpcode(POC_ANDLW, popGetLit(0x1f));
6729 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6730 emitpcode(POC_IORLW, popGetLit(0xe0));
6732 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6736 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6737 emitpcode(POC_ANDLW, popGetLit(0x0f));
6738 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6739 emitpcode(POC_IORLW, popGetLit(0xf0));
6740 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6746 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6747 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6749 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6750 emitpcode(POC_ANDLW, popGetLit(0x07));
6751 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6752 emitpcode(POC_IORLW, popGetLit(0xf8));
6753 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6758 emitpcode(POC_MOVLW, popGetLit(0x00));
6759 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6760 emitpcode(POC_MOVLW, popGetLit(0xfe));
6761 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6762 emitpcode(POC_IORLW, popGetLit(0x01));
6763 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6765 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6766 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6767 emitpcode(POC_DECF, popGet(AOP(result),offr));
6768 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6769 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6775 emitpcode(POC_MOVLW, popGetLit(0x00));
6776 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6777 emitpcode(POC_MOVLW, popGetLit(0xff));
6778 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6780 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6781 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6782 emitpcode(POC_DECF, popGet(AOP(result),offr));
6790 /*-----------------------------------------------------------------*/
6791 /* shiftR1Left2Result - shift right one byte from left to result */
6792 /*-----------------------------------------------------------------*/
6793 static void shiftR1Left2Result (operand *left, int offl,
6794 operand *result, int offr,
6795 int shCount, int sign)
6800 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6802 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6804 /* Copy the msb into the carry if signed. */
6806 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6816 emitpcode(POC_RRF, popGet(AOP(result),offr));
6818 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6819 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825 emitpcode(POC_RRF, popGet(AOP(result),offr));
6827 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6828 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6831 emitpcode(POC_RRF, popGet(AOP(result),offr));
6836 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6838 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6839 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6842 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6843 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6844 emitpcode(POC_ANDLW, popGetLit(0x1f));
6845 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6849 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6850 emitpcode(POC_ANDLW, popGetLit(0x0f));
6851 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6855 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6856 emitpcode(POC_ANDLW, popGetLit(0x0f));
6857 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6859 emitpcode(POC_RRF, popGet(AOP(result),offr));
6864 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6865 emitpcode(POC_ANDLW, popGetLit(0x80));
6866 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6867 emitpcode(POC_RLF, popGet(AOP(result),offr));
6868 emitpcode(POC_RLF, popGet(AOP(result),offr));
6873 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6874 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6875 emitpcode(POC_RLF, popGet(AOP(result),offr));
6884 /*-----------------------------------------------------------------*/
6885 /* shiftL1Left2Result - shift left one byte from left to result */
6886 /*-----------------------------------------------------------------*/
6887 static void shiftL1Left2Result (operand *left, int offl,
6888 operand *result, int offr, int shCount)
6894 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6896 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6897 DEBUGpic14_emitcode ("; ***","same = %d",same);
6898 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6900 /* shift left accumulator */
6901 //AccLsh(shCount); // don't comment out just yet...
6902 // aopPut(AOP(result),"a",offr);
6906 /* Shift left 1 bit position */
6907 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6909 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6911 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6912 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6916 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6917 emitpcode(POC_ANDLW,popGetLit(0x7e));
6918 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6919 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6922 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6923 emitpcode(POC_ANDLW,popGetLit(0x3e));
6924 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6925 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6926 emitpcode(POC_RLF, popGet(AOP(result),offr));
6929 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6930 emitpcode(POC_ANDLW, popGetLit(0xf0));
6931 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6934 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6935 emitpcode(POC_ANDLW, popGetLit(0xf0));
6936 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6937 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6940 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6941 emitpcode(POC_ANDLW, popGetLit(0x30));
6942 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6943 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6944 emitpcode(POC_RLF, popGet(AOP(result),offr));
6947 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6948 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6949 emitpcode(POC_RRF, popGet(AOP(result),offr));
6953 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6959 /*-----------------------------------------------------------------*/
6960 /* movLeft2Result - move byte from left to result */
6961 /*-----------------------------------------------------------------*/
6962 static void movLeft2Result (operand *left, int offl,
6963 operand *result, int offr)
6967 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6968 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6969 l = aopGet(AOP(left),offl,FALSE,FALSE);
6971 if (*l == '@' && (IS_AOP_PREG(result))) {
6972 pic14_emitcode("mov","a,%s",l);
6973 aopPut(AOP(result),"a",offr);
6975 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6976 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6981 /*-----------------------------------------------------------------*/
6982 /* shiftLeft_Left2ResultLit - shift left by known count */
6983 /*-----------------------------------------------------------------*/
6985 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6987 int size, same, offr, i;
6989 size = AOP_SIZE(left);
6990 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6992 same = pic14_sameRegs (AOP(left), AOP(result));
6995 shCount = shCount & 0x07;
7001 case 0: /* takes 0 or 2N cycles (for offr==0) */
7002 if (!same || offr) {
7003 for (i=size-1; i >= 0; i--)
7004 movLeft2Result (left, i, result, offr + i);
7008 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7010 shiftLeft_Left2ResultLit (left, result, 8 * offr);
7011 shiftLeft_Left2ResultLit (result, result, shCount);
7012 return; /* prevent clearing result again */
7015 for (i=0; i < size; i++) {
7016 if (same && !offr) {
7017 emitpcode (POC_RLF, popGet (AOP(left), i));
7019 emitpcode (POC_RLFW, popGet (AOP(left), i));
7020 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7026 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7027 /* works in-place/with offr as well */
7028 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7029 emitpcode (POC_ANDLW, popGetLit (0xF0));
7030 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7032 for (i = size - 2; i >= 0; i--)
7034 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7035 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7036 emitpcode (POC_ANDLW, popGetLit (0x0F));
7037 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7038 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7042 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7043 /* works in-place/with offr as well */
7044 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7045 for (i = size-2; i >= 0; i--) {
7046 emitpcode (POC_RRFW, popGet (AOP(left), i));
7047 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7049 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7050 emitpcode (POC_RRF, popGet (AOP(result), offr));
7054 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7055 shiftLeft_Left2ResultLit (result, result, 1);
7056 return; /* prevent clearing result again */
7062 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7066 /*-----------------------------------------------------------------*/
7067 /* shiftRight_Left2ResultLit - shift right by known count */
7068 /*-----------------------------------------------------------------*/
7070 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7072 int size, same, offr, i;
7074 size = AOP_SIZE(left);
7075 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7077 same = pic14_sameRegs (AOP(left), AOP(result));
7080 shCount = shCount & 0x07;
7088 case 0: /* takes 0 or 2N cycles (for offr==0) */
7089 if (!same || offr) {
7090 for (i=0; i < size; i++)
7091 movLeft2Result (left, i + offr, result, i);
7095 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7096 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7098 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7099 shiftRight_Left2ResultLit (result, result, shCount, sign);
7100 return; /* prevent sign-extending result again */
7104 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7107 for (i = size-1; i >= 0; i--) {
7108 if (same && !offr) {
7109 emitpcode (POC_RRF, popGet (AOP(left), i));
7111 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7112 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7118 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7119 /* works in-place/with offr as well */
7120 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7121 emitpcode (POC_ANDLW, popGetLit (0x0F));
7122 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7124 for (i = 1; i < size; i++)
7126 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7127 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7128 emitpcode (POC_ANDLW, popGetLit (0xF0));
7129 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7130 emitpcode (POC_XORWF, popGet (AOP(result), i));
7135 emitpcode (POC_MOVLW, popGetLit (0xF0));
7136 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7137 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7141 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7142 /* works in-place/with offr as well */
7143 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7144 for (i = 0; i < size-1; i++) {
7145 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7146 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7148 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7150 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7153 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7158 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7159 shiftRight_Left2ResultLit (result, result, 1, sign);
7160 return; /* prevent sign extending result again */
7165 addSign (result, size, sign);
7169 /*-----------------------------------------------------------------*/
7170 /* shiftL2Left2Result - shift left two bytes from left to result */
7171 /*-----------------------------------------------------------------*/
7172 static void shiftL2Left2Result (operand *left, int offl,
7173 operand *result, int offr, int shCount)
7177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7179 if(pic14_sameRegs(AOP(result), AOP(left))) {
7187 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7188 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7189 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7193 emitpcode(POC_RLF, popGet(AOP(result),offr));
7194 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7200 emitpcode(POC_MOVLW, popGetLit(0x0f));
7201 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7202 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7203 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7204 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7205 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7206 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7208 emitpcode(POC_RLF, popGet(AOP(result),offr));
7209 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7213 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7214 emitpcode(POC_RRF, popGet(AOP(result),offr));
7215 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7216 emitpcode(POC_RRF, popGet(AOP(result),offr));
7217 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7218 emitpcode(POC_ANDLW,popGetLit(0xc0));
7219 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7220 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7221 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7222 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7225 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7226 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7227 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7228 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7229 emitpcode(POC_RRF, popGet(AOP(result),offr));
7239 /* note, use a mov/add for the shift since the mov has a
7240 chance of getting optimized out */
7241 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7242 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7243 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7244 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7245 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7249 emitpcode(POC_RLF, popGet(AOP(result),offr));
7250 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7256 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7257 emitpcode(POC_ANDLW, popGetLit(0xF0));
7258 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7259 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7260 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7261 emitpcode(POC_ANDLW, popGetLit(0xF0));
7262 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7263 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7267 emitpcode(POC_RLF, popGet(AOP(result),offr));
7268 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7272 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7273 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7274 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7275 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7277 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7278 emitpcode(POC_RRF, popGet(AOP(result),offr));
7279 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7280 emitpcode(POC_ANDLW,popGetLit(0xc0));
7281 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7282 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7283 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7284 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7287 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7288 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7289 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7290 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7291 emitpcode(POC_RRF, popGet(AOP(result),offr));
7297 /*-----------------------------------------------------------------*/
7298 /* shiftR2Left2Result - shift right two bytes from left to result */
7299 /*-----------------------------------------------------------------*/
7300 static void shiftR2Left2Result (operand *left, int offl,
7301 operand *result, int offr,
7302 int shCount, int sign)
7307 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7308 same = pic14_sameRegs(AOP(result), AOP(left));
7310 if(same && ((offl + MSB16) == offr)){
7312 /* don't crash result[offr] */
7313 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7314 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7317 movLeft2Result(left,offl, result, offr);
7318 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7321 /* a:x >> shCount (x = lsb(result))*/
7324 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7326 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7335 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7340 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7341 emitpcode(POC_RRF,popGet(AOP(result),offr));
7343 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7344 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7345 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7346 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7351 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7354 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7355 emitpcode(POC_RRF,popGet(AOP(result),offr));
7362 emitpcode(POC_MOVLW, popGetLit(0xf0));
7363 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7364 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7366 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7367 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7368 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7369 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7371 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7372 emitpcode(POC_ANDLW, popGetLit(0x0f));
7373 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7375 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7376 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7377 emitpcode(POC_ANDLW, popGetLit(0xf0));
7378 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7379 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7383 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7384 emitpcode(POC_RRF, popGet(AOP(result),offr));
7388 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7389 emitpcode(POC_BTFSC,
7390 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7391 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7399 emitpcode(POC_RLF, popGet(AOP(result),offr));
7400 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7402 emitpcode(POC_RLF, popGet(AOP(result),offr));
7403 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7404 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7405 emitpcode(POC_ANDLW,popGetLit(0x03));
7407 emitpcode(POC_BTFSC,
7408 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7409 emitpcode(POC_IORLW,popGetLit(0xfc));
7411 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7412 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7413 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7414 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7416 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7417 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7418 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7419 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7420 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7421 emitpcode(POC_RLF, popGet(AOP(result),offr));
7422 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7423 emitpcode(POC_ANDLW,popGetLit(0x03));
7425 emitpcode(POC_BTFSC,
7426 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7427 emitpcode(POC_IORLW,popGetLit(0xfc));
7429 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7430 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7437 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7438 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7439 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7440 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7443 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7445 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7449 /*-----------------------------------------------------------------*/
7450 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7451 /*-----------------------------------------------------------------*/
7452 static void shiftLLeftOrResult (operand *left, int offl,
7453 operand *result, int offr, int shCount)
7456 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7458 /* shift left accumulator */
7459 AccLsh(left,offl,shCount);
7460 /* or with result */
7461 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7462 assert ( !"broken (modifies left, fails for left==result))" );
7465 /*-----------------------------------------------------------------*/
7466 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7467 /*-----------------------------------------------------------------*/
7468 static void shiftRLeftOrResult (operand *left, int offl,
7469 operand *result, int offr, int shCount)
7472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7474 /* shift right accumulator */
7475 AccRsh(left,offl,shCount);
7476 /* or with result */
7477 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7478 assert ( !"broken (modifies left, fails for left==result))" );
7481 /*-----------------------------------------------------------------*/
7482 /* genlshOne - left shift a one byte quantity by known count */
7483 /*-----------------------------------------------------------------*/
7484 static void genlshOne (operand *result, operand *left, int shCount)
7487 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7488 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7491 /*-----------------------------------------------------------------*/
7492 /* genlshTwo - left shift two bytes by known amount != 0 */
7493 /*-----------------------------------------------------------------*/
7494 static void genlshTwo (operand *result,operand *left, int shCount)
7499 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7500 size = pic14_getDataSize(result);
7502 /* if shCount >= 8 */
7508 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7510 movLeft2Result(left, LSB, result, MSB16);
7512 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7515 /* 1 <= shCount <= 7 */
7518 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7520 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7524 /*-----------------------------------------------------------------*/
7525 /* shiftLLong - shift left one long from left to result */
7526 /* offl = LSB or MSB16 */
7527 /*-----------------------------------------------------------------*/
7528 static void shiftLLong (operand *left, operand *result, int offr )
7531 int size = AOP_SIZE(result);
7534 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7535 if(size >= LSB+offr){
7536 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7538 pic14_emitcode("add","a,acc");
7539 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7540 size >= MSB16+offr && offr != LSB )
7541 pic14_emitcode("xch","a,%s",
7542 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7544 aopPut(AOP(result),"a",LSB+offr);
7547 if(size >= MSB16+offr){
7548 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7549 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7552 pic14_emitcode("rlc","a");
7553 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7554 size >= MSB24+offr && offr != LSB)
7555 pic14_emitcode("xch","a,%s",
7556 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7558 aopPut(AOP(result),"a",MSB16+offr);
7561 if(size >= MSB24+offr){
7562 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7563 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7566 pic14_emitcode("rlc","a");
7567 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7568 size >= MSB32+offr && offr != LSB )
7569 pic14_emitcode("xch","a,%s",
7570 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7572 aopPut(AOP(result),"a",MSB24+offr);
7575 if(size > MSB32+offr){
7576 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7577 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7580 pic14_emitcode("rlc","a");
7581 aopPut(AOP(result),"a",MSB32+offr);
7584 aopPut(AOP(result),zero,LSB);
7587 /*-----------------------------------------------------------------*/
7588 /* genlshFour - shift four byte by a known amount != 0 */
7589 /*-----------------------------------------------------------------*/
7590 static void genlshFour (operand *result, operand *left, int shCount)
7595 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7596 size = AOP_SIZE(result);
7598 /* if shifting more that 3 bytes */
7599 if (shCount >= 24 ) {
7602 /* lowest order of left goes to the highest
7603 order of the destination */
7604 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7606 movLeft2Result(left, LSB, result, MSB32);
7607 aopPut(AOP(result),zero,LSB);
7608 aopPut(AOP(result),zero,MSB16);
7609 aopPut(AOP(result),zero,MSB32);
7613 /* more than two bytes */
7614 else if ( shCount >= 16 ) {
7615 /* lower order two bytes goes to higher order two bytes */
7617 /* if some more remaining */
7619 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7621 movLeft2Result(left, MSB16, result, MSB32);
7622 movLeft2Result(left, LSB, result, MSB24);
7624 aopPut(AOP(result),zero,MSB16);
7625 aopPut(AOP(result),zero,LSB);
7629 /* if more than 1 byte */
7630 else if ( shCount >= 8 ) {
7631 /* lower order three bytes goes to higher order three bytes */
7635 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7637 movLeft2Result(left, LSB, result, MSB16);
7639 else{ /* size = 4 */
7641 movLeft2Result(left, MSB24, result, MSB32);
7642 movLeft2Result(left, MSB16, result, MSB24);
7643 movLeft2Result(left, LSB, result, MSB16);
7644 aopPut(AOP(result),zero,LSB);
7646 else if(shCount == 1)
7647 shiftLLong(left, result, MSB16);
7649 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7650 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7651 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7652 aopPut(AOP(result),zero,LSB);
7657 /* 1 <= shCount <= 7 */
7658 else if(shCount <= 2){
7659 shiftLLong(left, result, LSB);
7661 shiftLLong(result, result, LSB);
7663 /* 3 <= shCount <= 7, optimize */
7665 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7666 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7667 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7673 /*-----------------------------------------------------------------*/
7674 /* genLeftShiftLiteral - left shifting by known count */
7675 /*-----------------------------------------------------------------*/
7676 static void genLeftShiftLiteral (operand *left,
7681 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7685 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7686 freeAsmop(right,NULL,ic,TRUE);
7688 aopOp(left,ic,FALSE);
7689 aopOp(result,ic,FALSE);
7691 size = getSize(operandType(result));
7694 pic14_emitcode("; shift left ","result %d, left %d",size,
7698 /* I suppose that the left size >= result size */
7701 movLeft2Result(left, size, result, size);
7705 else if(shCount >= (size * 8))
7707 aopPut(AOP(result),zero,size);
7711 genlshOne (result,left,shCount);
7716 genlshTwo (result,left,shCount);
7720 genlshFour (result,left,shCount);
7724 freeAsmop(left,NULL,ic,TRUE);
7725 freeAsmop(result,NULL,ic,TRUE);
7729 /*-----------------------------------------------------------------*
7730 * genMultiAsm - repeat assembly instruction for size of register.
7731 * if endian == 1, then the high byte (i.e base address + size of
7732 * register) is used first else the low byte is used first;
7733 *-----------------------------------------------------------------*/
7734 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7740 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7753 emitpcode(poc, popGet(AOP(reg),offset));
7758 /*-----------------------------------------------------------------*/
7759 /* genLeftShift - generates code for left shifting */
7760 /*-----------------------------------------------------------------*/
7761 static void genLeftShift (iCode *ic)
7763 operand *left,*right, *result;
7765 unsigned long lit = 0L;
7767 symbol *tlbl , *tlbl1;
7771 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7773 right = IC_RIGHT(ic);
7775 result = IC_RESULT(ic);
7777 aopOp(right,ic,FALSE);
7778 aopOp(left,ic,FALSE);
7779 aopOp(result,ic,FALSE);
7782 /* if the shift count is known then do it
7783 as efficiently as possible */
7784 if (AOP_TYPE(right) == AOP_LIT) {
7785 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7789 /* shift count is unknown then we have to form
7790 a loop get the loop count in B : Note: we take
7791 only the lower order byte since shifting
7792 more that 32 bits make no sense anyway, ( the
7793 largest size of an object can be only 32 bits ) */
7795 /* this code fails for RIGHT == RESULT */
7796 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7798 /* now move the left to the result if they are not the
7800 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7801 AOP_SIZE(result) > 1) {
7803 size = AOP_SIZE(result);
7806 l = aopGet(AOP(left),offset,FALSE,TRUE);
7807 if (*l == '@' && (IS_AOP_PREG(result))) {
7809 pic14_emitcode("mov","a,%s",l);
7810 aopPut(AOP(result),"a",offset);
7812 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7813 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7814 //aopPut(AOP(result),l,offset);
7820 if(AOP_TYPE(left) == AOP_LIT)
7821 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7823 size = AOP_SIZE(result);
7825 /* if it is only one byte then */
7827 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7828 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7829 emitpcode(POC_ANDLW, popGetLit(0xf0));
7830 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7831 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7832 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7833 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7834 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7835 emitpcode(POC_RLFW, popGet(AOP(result),0));
7836 emitpcode(POC_ANDLW, popGetLit(0xfe));
7837 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7838 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7839 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7842 tlbl = newiTempLabel(NULL);
7843 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7844 mov2w (AOP(left), 0);
7845 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7848 emitpcode(POC_COMFW, popGet(AOP(right),0));
7849 emitpcode(POC_RRF, popGet(AOP(result),0));
7850 emitpLabel(tlbl->key);
7851 emitpcode(POC_RLF, popGet(AOP(result),0));
7852 emitpcode(POC_ADDLW, popGetLit(1));
7854 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7859 if (pic14_sameRegs(AOP(left),AOP(result))) {
7861 tlbl = newiTempLabel(NULL);
7862 emitpcode(POC_COMFW, popGet(AOP(right),0));
7863 genMultiAsm(POC_RRF, result, size,1);
7864 emitpLabel(tlbl->key);
7865 genMultiAsm(POC_RLF, result, size,0);
7866 emitpcode(POC_ADDLW, popGetLit(1));
7868 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7872 //tlbl = newiTempLabel(NULL);
7874 //tlbl1 = newiTempLabel(NULL);
7876 //reAdjustPreg(AOP(result));
7878 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7879 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7880 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7882 //pic14_emitcode("add","a,acc");
7883 //aopPut(AOP(result),"a",offset++);
7885 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7887 // pic14_emitcode("rlc","a");
7888 // aopPut(AOP(result),"a",offset++);
7890 //reAdjustPreg(AOP(result));
7892 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7893 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7896 tlbl = newiTempLabel(NULL);
7897 tlbl1= newiTempLabel(NULL);
7899 size = AOP_SIZE(result);
7902 pctemp = popGetTempReg(); /* grab a temporary working register. */
7904 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7906 /* offset should be 0, 1 or 3 */
7907 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7909 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7911 emitpcode(POC_MOVWF, pctemp);
7914 emitpLabel(tlbl->key);
7917 emitpcode(POC_RLF, popGet(AOP(result),0));
7919 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7921 emitpcode(POC_DECFSZ, pctemp);
7922 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7923 emitpLabel(tlbl1->key);
7925 popReleaseTempReg(pctemp);
7929 freeAsmop (right,NULL,ic,TRUE);
7930 freeAsmop(left,NULL,ic,TRUE);
7931 freeAsmop(result,NULL,ic,TRUE);
7935 /*-----------------------------------------------------------------*/
7936 /* genrshOne - right shift a one byte quantity by known count */
7937 /*-----------------------------------------------------------------*/
7938 static void genrshOne (operand *result, operand *left,
7939 int shCount, int sign)
7942 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7943 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7946 /*-----------------------------------------------------------------*/
7947 /* genrshTwo - right shift two bytes by known amount != 0 */
7948 /*-----------------------------------------------------------------*/
7949 static void genrshTwo (operand *result,operand *left,
7950 int shCount, int sign)
7953 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7954 /* if shCount >= 8 */
7958 shiftR1Left2Result(left, MSB16, result, LSB,
7961 movLeft2Result(left, MSB16, result, LSB);
7963 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7966 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7967 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7971 /* 1 <= shCount <= 7 */
7973 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7976 /*-----------------------------------------------------------------*/
7977 /* shiftRLong - shift right one long from left to result */
7978 /* offl = LSB or MSB16 */
7979 /*-----------------------------------------------------------------*/
7980 static void shiftRLong (operand *left, int offl,
7981 operand *result, int sign)
7986 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7988 size = AOP_SIZE(left);
7989 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7992 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7996 assert (offl >= 0 && offl < size);
7998 same = pic14_sameRegs (AOP(left), AOP(result));
8000 /* perform the shift */
8003 if (same && !offl) {
8004 emitpcode (POC_RRF, popGet (AOP(result), size));
8006 emitpcode (POC_RRFW, popGet (AOP(left), size));
8007 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8011 addSign (result, AOP_SIZE(left) - offl, sign);
8014 /*-----------------------------------------------------------------*/
8015 /* genrshFour - shift four byte by a known amount != 0 */
8016 /*-----------------------------------------------------------------*/
8017 static void genrshFour (operand *result, operand *left,
8018 int shCount, int sign)
8021 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8022 /* if shifting more that 3 bytes */
8023 if(shCount >= 24 ) {
8026 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8028 movLeft2Result(left, MSB32, result, LSB);
8030 addSign(result, MSB16, sign);
8032 else if(shCount >= 16){
8035 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8037 movLeft2Result(left, MSB24, result, LSB);
8038 movLeft2Result(left, MSB32, result, MSB16);
8040 addSign(result, MSB24, sign);
8042 else if(shCount >= 8){
8045 shiftRLong(left, MSB16, result, sign);
8046 else if(shCount == 0){
8047 movLeft2Result(left, MSB16, result, LSB);
8048 movLeft2Result(left, MSB24, result, MSB16);
8049 movLeft2Result(left, MSB32, result, MSB24);
8050 addSign(result, MSB32, sign);
8053 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8054 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8055 /* the last shift is signed */
8056 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8057 addSign(result, MSB32, sign);
8060 else{ /* 1 <= shCount <= 7 */
8062 shiftRLong(left, LSB, result, sign);
8064 shiftRLong(result, LSB, result, sign);
8067 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8068 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8069 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8074 /*-----------------------------------------------------------------*/
8075 /* genRightShiftLiteral - right shifting by known count */
8076 /*-----------------------------------------------------------------*/
8077 static void genRightShiftLiteral (operand *left,
8083 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8087 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8088 freeAsmop(right,NULL,ic,TRUE);
8090 aopOp(left,ic,FALSE);
8091 aopOp(result,ic,FALSE);
8094 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8098 lsize = pic14_getDataSize(left);
8099 res_size = pic14_getDataSize(result);
8100 /* test the LEFT size !!! */
8102 /* I suppose that the left size >= result size */
8105 movLeft2Result(left, res_size, result, res_size);
8108 else if(shCount >= (lsize * 8)){
8111 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8113 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8114 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8119 emitpcode(POC_MOVLW, popGetLit(0));
8120 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8121 emitpcode(POC_MOVLW, popGetLit(0xff));
8123 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8128 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8135 genrshOne (result,left,shCount,sign);
8139 genrshTwo (result,left,shCount,sign);
8143 genrshFour (result,left,shCount,sign);
8151 freeAsmop(left,NULL,ic,TRUE);
8152 freeAsmop(result,NULL,ic,TRUE);
8156 /*-----------------------------------------------------------------*/
8157 /* genSignedRightShift - right shift of signed number */
8158 /*-----------------------------------------------------------------*/
8159 static void genSignedRightShift (iCode *ic)
8161 operand *right, *left, *result;
8164 symbol *tlbl, *tlbl1 ;
8167 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8169 /* we do it the hard way put the shift count in b
8170 and loop thru preserving the sign */
8172 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8174 right = IC_RIGHT(ic);
8176 result = IC_RESULT(ic);
8178 aopOp(right,ic,FALSE);
8179 aopOp(left,ic,FALSE);
8180 aopOp(result,ic,FALSE);
8183 if ( AOP_TYPE(right) == AOP_LIT) {
8184 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8185 //genRightShiftLiteral (left,right,result,ic,1);
8188 /* shift count is unknown then we have to form
8189 a loop get the loop count in B : Note: we take
8190 only the lower order byte since shifting
8191 more that 32 bits make no sense anyway, ( the
8192 largest size of an object can be only 32 bits ) */
8194 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8195 //pic14_emitcode("inc","b");
8196 //freeAsmop (right,NULL,ic,TRUE);
8197 //aopOp(left,ic,FALSE);
8198 //aopOp(result,ic,FALSE);
8200 /* now move the left to the result if they are not the
8202 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8203 AOP_SIZE(result) > 1) {
8205 size = AOP_SIZE(result);
8209 l = aopGet(AOP(left),offset,FALSE,TRUE);
8210 if (*l == '@' && IS_AOP_PREG(result)) {
8211 pic14_emitcode("mov","a,%s",l);
8212 aopPut(AOP(result),"a",offset);
8214 aopPut(AOP(result),l,offset);
8216 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8217 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8223 /* mov the highest order bit to OVR */
8224 tlbl = newiTempLabel(NULL);
8225 tlbl1= newiTempLabel(NULL);
8227 size = AOP_SIZE(result);
8230 pctemp = popGetTempReg(); /* grab a temporary working register. */
8232 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8234 /* offset should be 0, 1 or 3 */
8235 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8237 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8239 emitpcode(POC_MOVWF, pctemp);
8242 emitpLabel(tlbl->key);
8244 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8245 emitpcode(POC_RRF, popGet(AOP(result),offset));
8248 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8251 emitpcode(POC_DECFSZ, pctemp);
8252 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8253 emitpLabel(tlbl1->key);
8255 popReleaseTempReg(pctemp);
8257 size = AOP_SIZE(result);
8259 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8260 pic14_emitcode("rlc","a");
8261 pic14_emitcode("mov","ov,c");
8262 /* if it is only one byte then */
8264 l = aopGet(AOP(left),0,FALSE,FALSE);
8266 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8267 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8268 pic14_emitcode("mov","c,ov");
8269 pic14_emitcode("rrc","a");
8270 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8271 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8272 aopPut(AOP(result),"a",0);
8276 reAdjustPreg(AOP(result));
8277 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8278 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8279 pic14_emitcode("mov","c,ov");
8281 l = aopGet(AOP(result),offset,FALSE,FALSE);
8283 pic14_emitcode("rrc","a");
8284 aopPut(AOP(result),"a",offset--);
8286 reAdjustPreg(AOP(result));
8287 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8288 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8293 freeAsmop(left,NULL,ic,TRUE);
8294 freeAsmop(result,NULL,ic,TRUE);
8295 freeAsmop(right,NULL,ic,TRUE);
8298 /*-----------------------------------------------------------------*/
8299 /* genRightShift - generate code for right shifting */
8300 /*-----------------------------------------------------------------*/
8301 static void genRightShift (iCode *ic)
8303 operand *right, *left, *result;
8307 symbol *tlbl, *tlbl1 ;
8310 /* if signed then we do it the hard way preserve the
8311 sign bit moving it inwards */
8312 retype = getSpec(operandType(IC_RESULT(ic)));
8313 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8315 if (!SPEC_USIGN(retype)) {
8316 genSignedRightShift (ic);
8320 /* signed & unsigned types are treated the same : i.e. the
8321 signed is NOT propagated inwards : quoting from the
8322 ANSI - standard : "for E1 >> E2, is equivalent to division
8323 by 2**E2 if unsigned or if it has a non-negative value,
8324 otherwise the result is implementation defined ", MY definition
8325 is that the sign does not get propagated */
8327 right = IC_RIGHT(ic);
8329 result = IC_RESULT(ic);
8331 aopOp(right,ic,FALSE);
8332 aopOp(left,ic,FALSE);
8333 aopOp(result,ic,FALSE);
8335 /* if the shift count is known then do it
8336 as efficiently as possible */
8337 if (AOP_TYPE(right) == AOP_LIT) {
8338 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8339 //genRightShiftLiteral (left,right,result,ic, 0);
8343 /* shift count is unknown then we have to form
8344 a loop get the loop count in B : Note: we take
8345 only the lower order byte since shifting
8346 more that 32 bits make no sense anyway, ( the
8347 largest size of an object can be only 32 bits ) */
8349 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8350 pic14_emitcode("inc","b");
8352 /* now move the left to the result if they are not the
8354 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8355 AOP_SIZE(result) > 1) {
8357 size = AOP_SIZE(result);
8360 l = aopGet(AOP(left),offset,FALSE,TRUE);
8361 if (*l == '@' && IS_AOP_PREG(result)) {
8363 pic14_emitcode("mov","a,%s",l);
8364 aopPut(AOP(result),"a",offset);
8366 aopPut(AOP(result),l,offset);
8371 tlbl = newiTempLabel(NULL);
8372 tlbl1= newiTempLabel(NULL);
8373 size = AOP_SIZE(result);
8376 /* if it is only one byte then */
8379 tlbl = newiTempLabel(NULL);
8380 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8381 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8382 emitpcode(POC_MOVWF, popGet(AOP(result),0));
8385 emitpcode(POC_COMFW, popGet(AOP(right),0));
8386 emitpcode(POC_RLF, popGet(AOP(result),0));
8387 emitpLabel(tlbl->key);
8388 emitpcode(POC_RRF, popGet(AOP(result),0));
8389 emitpcode(POC_ADDLW, popGetLit(1));
8391 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8396 reAdjustPreg(AOP(result));
8397 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8398 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8401 l = aopGet(AOP(result),offset,FALSE,FALSE);
8403 pic14_emitcode("rrc","a");
8404 aopPut(AOP(result),"a",offset--);
8406 reAdjustPreg(AOP(result));
8408 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8409 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8412 freeAsmop(left,NULL,ic,TRUE);
8413 freeAsmop (right,NULL,ic,TRUE);
8414 freeAsmop(result,NULL,ic,TRUE);
8417 /*-----------------------------------------------------------------*/
8418 /* genUnpackBits - generates code for unpacking bits */
8419 /*-----------------------------------------------------------------*/
8420 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8423 int offset = 0; /* result byte offset */
8424 int rsize; /* result size */
8425 int rlen = 0; /* remaining bitfield length */
8426 sym_link *etype; /* bitfield type information */
8427 int blen; /* bitfield length */
8428 int bstr; /* bitfield starting bit within byte */
8431 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8432 etype = getSpec(operandType(result));
8433 rsize = getSize (operandType (result));
8434 blen = SPEC_BLEN (etype);
8435 bstr = SPEC_BSTR (etype);
8437 /* single bit field case */
8439 if (ifx) { /* that is for an if statement */
8442 resolveIfx(&rIfx,ifx);
8443 if (ptype == -1) /* direct */
8444 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8446 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8447 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8448 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8453 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8454 for (i=0; i < AOP_SIZE(result); i++)
8455 emitpcode (POC_CLRF, popGet (AOP(result), i));
8456 if (ptype == -1) /* direct */
8457 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8459 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8460 emitpcode(POC_BTFSC,pcop);
8461 emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),0,0));
8467 static int has_warned=0;
8470 fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8475 /* read the first byte */
8480 // pic14_emitcode("mov","a,@%s",rname);
8481 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8485 pic14_emitcode("movx","a,@%s",rname);
8489 pic14_emitcode("movx","a,@dptr");
8493 pic14_emitcode("clr","a");
8494 pic14_emitcode("movc","a","@a+dptr");
8498 pic14_emitcode("lcall","__gptrget");
8502 /* if we have bitdisplacement then it fits */
8503 /* into this byte completely or if length is */
8504 /* less than a byte */
8505 if ((shCnt = SPEC_BSTR(etype)) || blen <= 8) {
8507 /* shift right acc */
8508 AccRsh(left,0,shCnt);
8510 pic14_emitcode("anl","a,#0x%02x",
8511 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8512 aopPut(AOP(result),"a",offset);
8516 /* bit field did not fit in a byte */
8517 rlen = SPEC_BLEN(etype) - 8;
8518 aopPut(AOP(result),"a",offset++);
8525 pic14_emitcode("inc","%s",rname);
8526 pic14_emitcode("mov","a,@%s",rname);
8530 pic14_emitcode("inc","%s",rname);
8531 pic14_emitcode("movx","a,@%s",rname);
8535 pic14_emitcode("inc","dptr");
8536 pic14_emitcode("movx","a,@dptr");
8540 pic14_emitcode("clr","a");
8541 pic14_emitcode("inc","dptr");
8542 pic14_emitcode("movc","a","@a+dptr");
8546 pic14_emitcode("inc","dptr");
8547 pic14_emitcode("lcall","__gptrget");
8552 /* if we are done */
8556 aopPut(AOP(result),"a",offset++);
8561 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8562 aopPut(AOP(result),"a",offset);
8569 /*-----------------------------------------------------------------*/
8570 /* genDataPointerGet - generates code when ptr offset is known */
8571 /*-----------------------------------------------------------------*/
8572 static void genDataPointerGet (operand *left,
8576 int size , offset = 0;
8579 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8582 /* optimization - most of the time, left and result are the same
8583 * address, but different types. for the pic code, we could omit
8586 aopOp(result,ic,TRUE);
8588 if (pic14_sameRegs (AOP(left), AOP(result)))
8591 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8593 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8595 size = AOP_SIZE(result);
8596 if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8599 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8600 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8604 freeAsmop(left,NULL,ic,TRUE);
8605 freeAsmop(result,NULL,ic,TRUE);
8608 /*-----------------------------------------------------------------*/
8609 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8610 /*-----------------------------------------------------------------*/
8611 static void genNearPointerGet (operand *left,
8616 sym_link *ltype = operandType(left);
8617 sym_link *rtype = operandType(result);
8618 sym_link *retype= getSpec(rtype); /* bitfield type information */
8622 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8625 aopOp(left,ic,FALSE);
8627 /* if left is rematerialisable and
8628 result is not bit variable type and
8629 the left is pointer to data space i.e
8630 lower 128 bytes of space */
8631 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8632 !IS_BITVAR(retype) &&
8633 DCL_TYPE(ltype) == POINTER) {
8634 genDataPointerGet (left,result,ic);
8638 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8639 aopOp (result,ic,FALSE);
8641 /* Check if can access directly instead of via a pointer */
8642 if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8646 /* If the pointer value is not in a the FSR then need to put it in */
8647 if (!AOP_INPREG(AOP(left)) && !direct) {
8648 /* otherwise get a free pointer register */
8649 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8650 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */
8651 emitpcode(POC_MOVLW, popGet(AOP(left),0));
8653 emitpcode(POC_MOVFW, popGet(AOP(left),0));
8654 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8659 /* if bitfield then unpack the bits */
8660 if (IS_BITFIELD(retype))
8661 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8663 /* we have can just get the values */
8664 int size = AOP_SIZE(result);
8667 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8671 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8673 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8674 if (AOP_TYPE(result) == AOP_LIT) {
8675 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8677 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8679 if (size && !direct)
8680 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8685 /* now some housekeeping stuff */
8687 /* we had to allocate for this iCode */
8688 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8689 freeAsmop(NULL,aop,ic,TRUE);
8691 /* we did not allocate which means left
8692 already in a pointer register, then
8693 if size > 0 && this could be used again
8694 we have to point it back to where it
8696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8697 if (AOP_SIZE(result) > 1 &&
8698 !OP_SYMBOL(left)->remat &&
8699 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8701 int size = AOP_SIZE(result) - 1;
8703 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8708 freeAsmop(left,NULL,ic,TRUE);
8709 freeAsmop(result,NULL,ic,TRUE);
8713 /*-----------------------------------------------------------------*/
8714 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8715 /*-----------------------------------------------------------------*/
8716 static void genPagedPointerGet (operand *left,
8723 sym_link *rtype, *retype;
8726 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8728 rtype = operandType(result);
8729 retype= getSpec(rtype);
8731 aopOp(left,ic,FALSE);
8733 /* if the value is already in a pointer register
8734 then don't need anything more */
8735 if (!AOP_INPREG(AOP(left))) {
8736 /* otherwise get a free pointer register */
8738 preg = getFreePtr(ic,&aop,FALSE);
8739 pic14_emitcode("mov","%s,%s",
8741 aopGet(AOP(left),0,FALSE,TRUE));
8742 rname = preg->name ;
8744 rname = aopGet(AOP(left),0,FALSE,FALSE);
8746 freeAsmop(left,NULL,ic,TRUE);
8747 aopOp (result,ic,FALSE);
8749 /* if bitfield then unpack the bits */
8750 if (IS_BITFIELD(retype))
8751 genUnpackBits (result,left,rname,PPOINTER,0);
8753 /* we have can just get the values */
8754 int size = AOP_SIZE(result);
8759 pic14_emitcode("movx","a,@%s",rname);
8760 aopPut(AOP(result),"a",offset);
8765 pic14_emitcode("inc","%s",rname);
8769 /* now some housekeeping stuff */
8771 /* we had to allocate for this iCode */
8772 freeAsmop(NULL,aop,ic,TRUE);
8774 /* we did not allocate which means left
8775 already in a pointer register, then
8776 if size > 0 && this could be used again
8777 we have to point it back to where it
8779 if (AOP_SIZE(result) > 1 &&
8780 !OP_SYMBOL(left)->remat &&
8781 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8783 int size = AOP_SIZE(result) - 1;
8785 pic14_emitcode("dec","%s",rname);
8790 freeAsmop(result,NULL,ic,TRUE);
8795 /*-----------------------------------------------------------------*/
8796 /* genFarPointerGet - gget value from far space */
8797 /*-----------------------------------------------------------------*/
8798 static void genFarPointerGet (operand *left,
8799 operand *result, iCode *ic)
8802 sym_link *retype = getSpec(operandType(result));
8805 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8807 aopOp(left,ic,FALSE);
8809 /* if the operand is already in dptr
8810 then we do nothing else we move the value to dptr */
8811 if (AOP_TYPE(left) != AOP_STR) {
8812 /* if this is remateriazable */
8813 if (AOP_TYPE(left) == AOP_IMMD)
8814 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8815 else { /* we need to get it byte by byte */
8816 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8817 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8818 if (options.model == MODEL_FLAT24)
8820 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8824 /* so dptr know contains the address */
8825 freeAsmop(left,NULL,ic,TRUE);
8826 aopOp(result,ic,FALSE);
8828 /* if bit then unpack */
8829 if (IS_BITFIELD(retype))
8830 genUnpackBits(result,left,"dptr",FPOINTER,0);
8832 size = AOP_SIZE(result);
8836 pic14_emitcode("movx","a,@dptr");
8837 aopPut(AOP(result),"a",offset++);
8839 pic14_emitcode("inc","dptr");
8843 freeAsmop(result,NULL,ic,TRUE);
8846 /*-----------------------------------------------------------------*/
8847 /* genCodePointerGet - get value from code space */
8848 /*-----------------------------------------------------------------*/
8849 static void genCodePointerGet (operand *left,
8850 operand *result, iCode *ic)
8853 sym_link *retype = getSpec(operandType(result));
8855 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8857 aopOp(left,ic,FALSE);
8859 /* if the operand is already in dptr
8860 then we do nothing else we move the value to dptr */
8861 if (AOP_TYPE(left) != AOP_STR) {
8862 /* if this is remateriazable */
8863 if (AOP_TYPE(left) == AOP_IMMD)
8864 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8865 else { /* we need to get it byte by byte */
8866 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8867 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8868 if (options.model == MODEL_FLAT24)
8870 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8874 /* so dptr know contains the address */
8875 freeAsmop(left,NULL,ic,TRUE);
8876 aopOp(result,ic,FALSE);
8878 /* if bit then unpack */
8879 if (IS_BITFIELD(retype))
8880 genUnpackBits(result,left,"dptr",CPOINTER,0);
8882 size = AOP_SIZE(result);
8886 pic14_emitcode("clr","a");
8887 pic14_emitcode("movc","a,@a+dptr");
8888 aopPut(AOP(result),"a",offset++);
8890 pic14_emitcode("inc","dptr");
8894 freeAsmop(result,NULL,ic,TRUE);
8897 /*-----------------------------------------------------------------*/
8898 /* genGenPointerGet - gget value from generic pointer space */
8899 /*-----------------------------------------------------------------*/
8900 static void genGenPointerGet (operand *left,
8901 operand *result, iCode *ic)
8904 sym_link *retype = getSpec(operandType(result));
8907 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8908 aopOp(left,ic,FALSE);
8909 aopOp(result,ic,FALSE);
8912 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8914 /* if the operand is already in dptr
8915 then we do nothing else we move the value to dptr */
8916 // if (AOP_TYPE(left) != AOP_STR) {
8917 /* if this is remateriazable */
8918 if (AOP_TYPE(left) == AOP_IMMD) {
8919 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8920 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8922 else { /* we need to get it byte by byte */
8924 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8925 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8927 size = AOP_SIZE(result);
8931 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8932 emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8934 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8939 /* so dptr know contains the address */
8941 /* if bit then unpack */
8942 //if (IS_BITFIELD(retype))
8943 // genUnpackBits(result,"dptr",GPOINTER);
8946 freeAsmop(left,NULL,ic,TRUE);
8947 freeAsmop(result,NULL,ic,TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* genConstPointerGet - get value from const generic pointer space */
8953 /*-----------------------------------------------------------------*/
8954 static void genConstPointerGet (operand *left,
8955 operand *result, iCode *ic)
8957 //sym_link *retype = getSpec(operandType(result));
8958 symbol *albl, *blbl;//, *clbl;
8964 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8965 aopOp(left,ic,FALSE);
8966 aopOp(result,ic,FALSE);
8968 size = AOP_SIZE(result);
8970 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8972 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8974 lit = aop_isLitLike (AOP(left));
8975 poc = lit ? POC_MOVLW : POC_MOVFW;
8979 for (i = 0; i < size; i++)
8981 albl = newiTempLabel(NULL);
8982 blbl = newiTempLabel(NULL);
8984 emitpcode(POC_CALL,popGetLabel(albl->key));
8985 pcop = popGetLabel(blbl->key);
8986 emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8987 emitpcode(POC_GOTO,pcop);
8989 emitpLabel(albl->key);
8990 emitpcode(poc,popGetAddr(AOP(left),1,i));
8991 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8992 emitpcode(poc,popGetAddr(AOP(left),0,i));
8993 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8995 emitpLabel(blbl->key);
8996 emitpcode(POC_MOVWF,popGet(AOP(result),i));
8999 albl = newiTempLabel(NULL);
9000 blbl = newiTempLabel(NULL);
9001 //clbl = newiTempLabel(NULL);
9003 emitpcode (POC_GOTO, popGetLabel (blbl->key));
9005 emitpLabel(albl->key);
9006 emitpcode(poc,popGet(AOP(left),1));
9007 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
9008 emitpcode(poc,popGet(AOP(left),0));
9009 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
9011 emitpLabel(blbl->key);
9013 for (i = 0; i < size; i++)
9015 emitpcode(POC_CALL,popGetLabel(albl->key));
9016 /* the next two instructions (plus clbl) might be useless... */
9017 //pcop = popGetLabel(clbl->key);
9018 //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
9019 //emitpcode(POC_GOTO,pcop);
9020 //emitpLabel(clbl->key);
9023 emitpcode (POC_INCF, popGet (AOP(left), 0));
9025 emitpcode (POC_INCF, popGet (AOP(left), 1));
9027 emitpcode(POC_MOVWF,popGet(AOP(result),i));
9030 /* restore left's value */
9031 emitpcode (POC_MOVLW, popGetLit (size-1));
9032 emitpcode (POC_SUBWF, popGet (AOP(left), 0));
9034 emitpcode (POC_DECF, popGet (AOP(left), 1));
9038 freeAsmop(left,NULL,ic,TRUE);
9039 freeAsmop(result,NULL,ic,TRUE);
9042 /*-----------------------------------------------------------------*/
9043 /* genPointerGet - generate code for pointer get */
9044 /*-----------------------------------------------------------------*/
9045 static void genPointerGet (iCode *ic)
9047 operand *left, *result ;
9048 sym_link *type, *etype;
9052 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9055 result = IC_RESULT(ic) ;
9057 /* depending on the type of pointer we need to
9058 move it to the correct pointer register */
9059 type = operandType(left);
9060 etype = getSpec(type);
9062 if (IS_PTR_CONST(type))
9063 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9065 /* if left is of type of pointer then it is simple */
9066 if (IS_PTR(type) && !IS_FUNC(type->next))
9067 p_type = DCL_TYPE(type);
9069 /* we have to go by the storage class */
9070 p_type = PTR_TYPE(SPEC_OCLS(etype));
9072 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9074 if (SPEC_OCLS(etype)->codesp ) {
9075 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9076 //p_type = CPOINTER ;
9079 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9080 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9081 /*p_type = FPOINTER ;*/
9083 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9084 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9085 /* p_type = PPOINTER; */
9087 if (SPEC_OCLS(etype) == idata )
9088 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9089 /* p_type = IPOINTER; */
9091 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9092 /* p_type = POINTER ; */
9095 /* now that we have the pointer type we assign
9096 the pointer values */
9101 genNearPointerGet (left,result,ic);
9105 genPagedPointerGet(left,result,ic);
9109 genFarPointerGet (left,result,ic);
9113 genConstPointerGet (left,result,ic);
9114 //pic14_emitcodePointerGet (left,result,ic);
9118 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
9119 genConstPointerGet (left,result,ic);
9121 genGenPointerGet (left,result,ic);
9124 assert ( !"unhandled pointer type" );
9130 /*-----------------------------------------------------------------*/
9131 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into */
9132 /* A through a pointer register (R0, R1, or DPTR). The original */
9133 /* value of A can be preserved in B. */
9134 /* PIC has to use INDF register. */
9135 /*-----------------------------------------------------------------*/
9137 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9145 pic14_emitcode ("mov", "b,a");
9146 // pic14_emitcode ("mov", "a,@%s", rname);
9147 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
9152 pic14_emitcode ("mov", "b,a");
9153 pic14_emitcode ("movx", "a,@%s", rname);
9158 pic14_emitcode ("mov", "b,a");
9159 pic14_emitcode ("movx", "a,@dptr");
9164 pic14_emitcode ("mov", "b,a");
9165 pic14_emitcode ("clr", "a");
9166 pic14_emitcode ("movc", "a,@a+dptr");
9172 pic14_emitcode ("push", "b");
9173 pic14_emitcode ("push", "acc");
9175 pic14_emitcode ("lcall", "__gptrget");
9177 pic14_emitcode ("pop", "b");
9182 /*-----------------------------------------------------------------*/
9183 /* emitPtrByteSet - emits code to set a byte from src through a */
9184 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
9185 /*-----------------------------------------------------------------*/
9187 emitPtrByteSet (char *rname, int p_type, char *src)
9197 pic14_emitcode ("mov", "@%s,a", rname);
9200 // pic14_emitcode ("mov", "@%s,%s", rname, src);
9201 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9206 pic14_emitcode ("movx", "@%s,a", rname);
9211 pic14_emitcode ("movx", "@dptr,a");
9216 pic14_emitcode ("lcall", "__gptrput");
9221 /*-----------------------------------------------------------------*/
9222 /* genPackBits - generates code for packed bit storage */
9223 /*-----------------------------------------------------------------*/
9224 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
9226 int offset = 0; /* source byte offset */
9227 int rlen = 0; /* remaining bitfield length */
9228 int blen; /* bitfield length */
9229 int bstr; /* bitfield starting bit within byte */
9230 int litval; /* source literal value (if AOP_LIT) */
9231 unsigned char mask; /* bitmask within current byte */
9234 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9236 blen = SPEC_BLEN (etype);
9237 bstr = SPEC_BSTR (etype);
9239 /* If the bitfield length is less than a byte */
9242 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9243 (unsigned char) (0xFF >> (8 - bstr)));
9245 if (AOP_TYPE (right) == AOP_LIT)
9247 /* Case with a bitfield length <8 and literal source
9249 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9253 if (AOP(result)->type == AOP_PCODE)
9254 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9256 pcop = popGet(AOP(result),0);
9257 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9259 emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
9263 litval = lit << bstr;
9264 litval &= (~mask) & 0xff;
9266 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9268 emitPtrByteGet (rname, p_type, FALSE);
9269 if ((mask|litval)!=0xff)
9270 emitpcode(POC_ANDLW,popGetLit(mask));
9272 emitpcode(POC_IORLW,popGetLit(litval));
9279 /* 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 */
9280 emitpcode(POC_RRFW,popGet(AOP(right),0));
9282 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9284 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9286 } else if (p_type!=GPOINTER) {
9287 /* Case with a bitfield length == 1 and no generic pointer
9289 if (AOP_TYPE (right) == AOP_CRY)
9290 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9293 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9294 pic14_emitcode ("rrc","a");
9296 emitPtrByteGet (rname, p_type, FALSE);
9297 pic14_emitcode ("mov","acc.%d,c",bstr);
9303 /* Case with a bitfield length < 8 and arbitrary source
9305 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9306 /* shift and mask source value */
9307 AccLsh (right,0,bstr);
9308 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9309 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9311 //pushedB = pushB ();
9313 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9315 emitPtrByteGet (rname, p_type, TRUE);
9317 pic14_emitcode ("anl", "a,#0x%02x", mask);
9318 pic14_emitcode ("orl", "a,b");
9319 emitpcode(POC_ANDLW,popGetLit(mask));
9320 emitpcode(POC_IORFW,popGet(AOP(right),0));
9321 if (p_type == GPOINTER)
9322 pic14_emitcode ("pop", "b");
9329 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9331 emitPtrByteSet (rname, p_type, "a");
9335 /* Bit length is greater than 7 bits. In this case, copy */
9336 /* all except the partial byte at the end */
9337 for (rlen=blen;rlen>=8;rlen-=8)
9339 emitPtrByteSet (rname, p_type,
9340 aopGet (AOP (right), offset++, FALSE, TRUE) );
9342 pic14_emitcode ("inc", "%s", rname);
9345 /* If there was a partial byte at the end */
9348 mask = (((unsigned char) -1 << rlen) & 0xff);
9350 if (AOP_TYPE (right) == AOP_LIT)
9352 /* Case with partial byte and literal source
9354 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9355 litval >>= (blen-rlen);
9356 litval &= (~mask) & 0xff;
9357 emitPtrByteGet (rname, p_type, FALSE);
9358 if ((mask|litval)!=0xff)
9359 pic14_emitcode ("anl","a,#0x%02x", mask);
9361 pic14_emitcode ("orl","a,#0x%02x", litval);
9366 /* Case with partial byte and arbitrary source
9368 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9369 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9371 //pushedB = pushB ();
9372 /* transfer A to B and get next byte */
9373 emitPtrByteGet (rname, p_type, TRUE);
9375 pic14_emitcode ("anl", "a,#0x%02x", mask);
9376 pic14_emitcode ("orl", "a,b");
9377 if (p_type == GPOINTER)
9378 pic14_emitcode ("pop", "b");
9382 emitPtrByteSet (rname, p_type, "a");
9387 /*-----------------------------------------------------------------*/
9388 /* SetIrp - Set IRP bit */
9389 /*-----------------------------------------------------------------*/
9390 void SetIrp(operand *result) {
9392 if (AOP_TYPE(result) == AOP_LIT) {
9393 unsigned lit = (unsigned)operandLitValue(result);
9394 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9396 if (PCOP(AOP(result))->type == PO_LITERAL) {
9397 int addrs = PCOL(AOP(result))->lit;
9398 emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9400 emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9401 if(AOP_SIZE(result) > 1) {
9402 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9403 emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9409 /*-----------------------------------------------------------------*/
9410 /* genDataPointerSet - remat pointer to data space */
9411 /*-----------------------------------------------------------------*/
9412 static void genDataPointerSet(operand *right,
9416 int size, offset = 0 ;
9419 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9420 aopOp(right,ic,FALSE);
9421 aopOp(result,ic,FALSE);
9423 size = AOP_SIZE(right);
9425 if ( AOP_TYPE(result) == AOP_PCODE) {
9426 fprintf(stderr,"genDataPointerSet %s, %d\n",
9427 AOP(result)->aopu.pcop->name,
9428 PCOI(AOP(result)->aopu.pcop)->offset);
9432 // tsd, was l+1 - the underline `_' prefix was being stripped
9434 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9436 if (AOP_TYPE(right) == AOP_LIT) {
9437 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9438 lit = lit >> (8*offset);
9440 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9441 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9443 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9446 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9447 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9453 freeAsmop(right,NULL,ic,TRUE);
9454 freeAsmop(result,NULL,ic,TRUE);
9457 /*-----------------------------------------------------------------*/
9458 /* genNearPointerSet - pic14_emitcode for near pointer put */
9459 /*-----------------------------------------------------------------*/
9460 static void genNearPointerSet (operand *right,
9465 sym_link *ptype = operandType(result);
9466 sym_link *retype = getSpec(operandType(right));
9467 sym_link *letype = getSpec(ptype);
9472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9473 aopOp(result,ic,FALSE);
9476 /* if the result is rematerializable &
9477 in data space & not a bit variable */
9478 //if (AOP_TYPE(result) == AOP_IMMD &&
9479 if (AOP_TYPE(result) == AOP_PCODE &&
9480 DCL_TYPE(ptype) == POINTER &&
9481 !IS_BITVAR (retype) &&
9482 !IS_BITVAR (letype)) {
9483 genDataPointerSet (right,result,ic);
9484 freeAsmop(result,NULL,ic,TRUE);
9488 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9489 aopOp(right,ic,FALSE);
9490 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9492 /* Check if can access directly instead of via a pointer */
9493 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9497 /* If the pointer value is not in a the FSR then need to put it in */
9498 if (!AOP_INPREG(AOP(result)) && !direct) {
9499 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9500 if (PCOP(AOP(result))->type == PO_LITERAL)
9501 emitpcode(POC_MOVLW, popGet(AOP(result),0));
9503 emitpcode(POC_MOVFW, popGet(AOP(result),0));
9504 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9507 /* Must set/reset IRP bit for use with FSR. */
9508 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9512 /* if bitfield then unpack the bits */
9513 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9514 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9516 /* we have can just get the values */
9517 int size = AOP_SIZE(right);
9520 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9524 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9526 if (AOP_TYPE(right) == AOP_LIT) {
9527 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9529 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9532 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9534 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9536 if (size && !direct)
9537 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9542 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9543 /* now some housekeeping stuff */
9545 /* we had to allocate for this iCode */
9546 freeAsmop(NULL,aop,ic,TRUE);
9548 /* we did not allocate which means left
9549 already in a pointer register, then
9550 if size > 0 && this could be used again
9551 we have to point it back to where it
9553 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9554 if (AOP_SIZE(right) > 1 &&
9555 !OP_SYMBOL(result)->remat &&
9556 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9558 int size = AOP_SIZE(right) - 1;
9560 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9564 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9567 freeAsmop(right,NULL,ic,TRUE);
9568 freeAsmop(result,NULL,ic,TRUE);
9571 /*-----------------------------------------------------------------*/
9572 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9573 /*-----------------------------------------------------------------*/
9574 static void genPagedPointerSet (operand *right,
9584 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9586 retype= getSpec(operandType(right));
9588 aopOp(result,ic,FALSE);
9590 /* if the value is already in a pointer register
9591 then don't need anything more */
9592 if (!AOP_INPREG(AOP(result))) {
9593 /* otherwise get a free pointer register */
9595 preg = getFreePtr(ic,&aop,FALSE);
9596 pic14_emitcode("mov","%s,%s",
9598 aopGet(AOP(result),0,FALSE,TRUE));
9599 rname = preg->name ;
9601 rname = aopGet(AOP(result),0,FALSE,FALSE);
9603 freeAsmop(result,NULL,ic,TRUE);
9604 aopOp (right,ic,FALSE);
9606 /* if bitfield then unpack the bits */
9607 if (IS_BITFIELD(retype))
9608 genPackBits (retype,result,right,rname,PPOINTER);
9610 /* we have can just get the values */
9611 int size = AOP_SIZE(right);
9615 l = aopGet(AOP(right),offset,FALSE,TRUE);
9618 pic14_emitcode("movx","@%s,a",rname);
9621 pic14_emitcode("inc","%s",rname);
9627 /* now some housekeeping stuff */
9629 /* we had to allocate for this iCode */
9630 freeAsmop(NULL,aop,ic,TRUE);
9632 /* we did not allocate which means left
9633 already in a pointer register, then
9634 if size > 0 && this could be used again
9635 we have to point it back to where it
9637 if (AOP_SIZE(right) > 1 &&
9638 !OP_SYMBOL(result)->remat &&
9639 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9641 int size = AOP_SIZE(right) - 1;
9643 pic14_emitcode("dec","%s",rname);
9648 freeAsmop(right,NULL,ic,TRUE);
9653 /*-----------------------------------------------------------------*/
9654 /* genFarPointerSet - set value from far space */
9655 /*-----------------------------------------------------------------*/
9656 static void genFarPointerSet (operand *right,
9657 operand *result, iCode *ic)
9660 sym_link *retype = getSpec(operandType(right));
9663 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9664 aopOp(result,ic,FALSE);
9666 /* if the operand is already in dptr
9667 then we do nothing else we move the value to dptr */
9668 if (AOP_TYPE(result) != AOP_STR) {
9669 /* if this is remateriazable */
9670 if (AOP_TYPE(result) == AOP_IMMD)
9671 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9672 else { /* we need to get it byte by byte */
9673 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9674 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9675 if (options.model == MODEL_FLAT24)
9677 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9681 /* so dptr know contains the address */
9682 freeAsmop(result,NULL,ic,TRUE);
9683 aopOp(right,ic,FALSE);
9685 /* if bit then unpack */
9686 if (IS_BITFIELD(retype))
9687 genPackBits(retype,result,right,"dptr",FPOINTER);
9689 size = AOP_SIZE(right);
9693 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9695 pic14_emitcode("movx","@dptr,a");
9697 pic14_emitcode("inc","dptr");
9701 freeAsmop(right,NULL,ic,TRUE);
9704 /*-----------------------------------------------------------------*/
9705 /* genGenPointerSet - set value from generic pointer space */
9706 /*-----------------------------------------------------------------*/
9707 static void genGenPointerSet (operand *right,
9708 operand *result, iCode *ic)
9710 sym_link *ptype = operandType(result);
9711 sym_link *retype = getSpec(operandType(right));
9712 sym_link *letype = getSpec (ptype);
9715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9717 aopOp(result,ic,FALSE);
9718 aopOp(right,ic,FALSE);
9720 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9722 /* if the operand is already in dptr
9723 then we do nothing else we move the value to dptr */
9724 if (AOP_TYPE(result) != AOP_STR) {
9725 /* if this is remateriazable */
9726 if (AOP_TYPE(result) == AOP_IMMD) {
9727 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9728 pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9731 emitpcode(POC_MOVFW,popGet(AOP(result),0));
9732 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9734 /* Must set/reset IRP bit for use with FSR. */
9735 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9740 /* if bitfield then unpack the bits */
9741 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9742 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9744 /* we have can just get the values */
9745 int size = AOP_SIZE(right);
9748 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9750 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9752 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9754 if (AOP_TYPE(right) == AOP_LIT) {
9755 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9757 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9759 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9762 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9767 freeAsmop(right,NULL,ic,TRUE);
9768 freeAsmop(result,NULL,ic,TRUE);
9771 /*-----------------------------------------------------------------*/
9772 /* genPointerSet - stores the value into a pointer location */
9773 /*-----------------------------------------------------------------*/
9774 static void genPointerSet (iCode *ic)
9776 operand *right, *result ;
9777 sym_link *type, *etype;
9781 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9783 right = IC_RIGHT(ic);
9784 result = IC_RESULT(ic) ;
9786 /* depending on the type of pointer we need to
9787 move it to the correct pointer register */
9788 type = operandType(result);
9789 etype = getSpec(type);
9790 /* if left is of type of pointer then it is simple */
9791 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9792 p_type = DCL_TYPE(type);
9795 /* we have to go by the storage class */
9796 p_type = PTR_TYPE(SPEC_OCLS(etype));
9798 /* if (SPEC_OCLS(etype)->codesp ) { */
9799 /* p_type = CPOINTER ; */
9802 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9803 /* p_type = FPOINTER ; */
9805 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9806 /* p_type = PPOINTER ; */
9808 /* if (SPEC_OCLS(etype) == idata ) */
9809 /* p_type = IPOINTER ; */
9811 /* p_type = POINTER ; */
9814 /* now that we have the pointer type we assign
9815 the pointer values */
9820 genNearPointerSet (right,result,ic);
9824 genPagedPointerSet (right,result,ic);
9828 genFarPointerSet (right,result,ic);
9832 genGenPointerSet (right,result,ic);
9836 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9837 "genPointerSet: illegal pointer type");
9841 /*-----------------------------------------------------------------*/
9842 /* genIfx - generate code for Ifx statement */
9843 /*-----------------------------------------------------------------*/
9844 static void genIfx (iCode *ic, iCode *popIc)
9846 operand *cond = IC_COND(ic);
9850 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9852 aopOp(cond,ic,FALSE);
9854 /* get the value into acc */
9855 if (AOP_TYPE(cond) != AOP_CRY)
9856 pic14_toBoolean(cond);
9859 /* the result is now in the accumulator */
9860 freeAsmop(cond,NULL,ic,TRUE);
9862 /* if there was something to be popped then do it */
9866 /* if the condition is a bit variable */
9867 if (isbit && IS_ITEMP(cond) &&
9869 genIfxJump(ic,SPIL_LOC(cond)->rname);
9870 DEBUGpic14_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9873 if (isbit && !IS_ITEMP(cond))
9874 genIfxJump(ic,OP_SYMBOL(cond)->rname);
9882 /*-----------------------------------------------------------------*/
9883 /* genAddrOf - generates code for address of */
9884 /*-----------------------------------------------------------------*/
9885 static void genAddrOf (iCode *ic)
9887 operand *right, *result, *left;
9891 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9894 //aopOp(IC_RESULT(ic),ic,FALSE);
9896 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9897 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9898 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9900 DEBUGpic14_AopType(__LINE__,left,right,result);
9901 assert (IS_SYMOP (left));
9903 /* sanity check: generic pointers to code space are not yet supported,
9904 * pionters to codespace must not be assigned addresses of __data values. */
9906 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9907 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)));
9908 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)));
9909 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)));
9910 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)));
9913 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9914 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9915 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9916 OP_SYMBOL(left)->name);
9917 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9918 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9919 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9920 OP_SYMBOL(left)->name);
9923 size = AOP_SIZE(IC_RESULT(ic));
9927 /* fixing bug #863624, reported from (errolv) */
9928 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9929 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9932 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9933 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9938 freeAsmop(left,NULL,ic,FALSE);
9939 freeAsmop(result,NULL,ic,TRUE);
9944 /*-----------------------------------------------------------------*/
9945 /* genFarFarAssign - assignment when both are in far space */
9946 /*-----------------------------------------------------------------*/
9947 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9949 int size = AOP_SIZE(right);
9952 /* first push the right side on to the stack */
9954 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9956 pic14_emitcode ("push","acc");
9959 freeAsmop(right,NULL,ic,FALSE);
9960 /* now assign DPTR to result */
9961 aopOp(result,ic,FALSE);
9962 size = AOP_SIZE(result);
9964 pic14_emitcode ("pop","acc");
9965 aopPut(AOP(result),"a",--offset);
9967 freeAsmop(result,NULL,ic,FALSE);
9972 /*-----------------------------------------------------------------*/
9973 /* genAssign - generate code for assignment */
9974 /*-----------------------------------------------------------------*/
9975 static void genAssign (iCode *ic)
9977 operand *result, *right;
9978 int size, offset,know_W;
9979 unsigned long lit = 0L;
9981 result = IC_RESULT(ic);
9982 right = IC_RIGHT(ic) ;
9985 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9987 /* if they are the same */
9988 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9991 aopOp(right,ic,FALSE);
9992 aopOp(result,ic,TRUE);
9994 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9996 /* if they are the same registers */
9997 if (pic14_sameRegs(AOP(right),AOP(result)))
10000 /* special case: assign from __code */
10001 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
10002 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10003 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
10004 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
10005 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10007 emitpComment ("genAssign from CODESPACE");
10008 genConstPointerGet (right, result, ic);
10012 /* just for symmetry reasons... */
10013 if (!IS_ITEMP(result)
10014 && IS_SYMOP (result)
10015 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10017 assert ( !"cannot write to CODESPACE" );
10020 /* if the result is a bit */
10021 if (AOP_TYPE(result) == AOP_CRY) {
10023 /* if the right size is a literal then
10024 we know what the value is */
10025 if (AOP_TYPE(right) == AOP_LIT) {
10027 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10028 popGet(AOP(result),0));
10030 if (((int) operandLitValue(right)))
10031 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10032 AOP(result)->aopu.aop_dir,
10033 AOP(result)->aopu.aop_dir);
10035 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10036 AOP(result)->aopu.aop_dir,
10037 AOP(result)->aopu.aop_dir);
10041 /* the right is also a bit variable */
10042 if (AOP_TYPE(right) == AOP_CRY) {
10043 emitpcode(POC_BCF, popGet(AOP(result),0));
10044 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10045 emitpcode(POC_BSF, popGet(AOP(result),0));
10047 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10048 AOP(result)->aopu.aop_dir,
10049 AOP(result)->aopu.aop_dir);
10050 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10051 AOP(right)->aopu.aop_dir,
10052 AOP(right)->aopu.aop_dir);
10053 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10054 AOP(result)->aopu.aop_dir,
10055 AOP(result)->aopu.aop_dir);
10059 /* we need to or */
10060 emitpcode(POC_BCF, popGet(AOP(result),0));
10061 pic14_toBoolean(right);
10063 emitpcode(POC_BSF, popGet(AOP(result),0));
10064 //aopPut(AOP(result),"a",0);
10068 /* bit variables done */
10070 size = AOP_SIZE(result);
10072 if(AOP_TYPE(right) == AOP_LIT)
10073 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10075 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10076 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10077 if(aopIdx(AOP(result),0) == 4) {
10078 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10079 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10080 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10083 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10088 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10089 if(AOP_TYPE(right) == AOP_LIT) {
10091 if(know_W != (int)(lit&0xff))
10092 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10094 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10096 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10100 } else if (AOP_TYPE(right) == AOP_CRY) {
10101 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10103 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10104 emitpcode(POC_INCF, popGet(AOP(result),0));
10107 mov2w (AOP(right), offset);
10108 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10116 freeAsmop (right,NULL,ic,FALSE);
10117 freeAsmop (result,NULL,ic,TRUE);
10120 /*-----------------------------------------------------------------*/
10121 /* genJumpTab - genrates code for jump table */
10122 /*-----------------------------------------------------------------*/
10123 static void genJumpTab (iCode *ic)
10129 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10131 aopOp(IC_JTCOND(ic),ic,FALSE);
10132 /* get the condition into accumulator */
10133 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10135 /* multiply by three */
10136 pic14_emitcode("add","a,acc");
10137 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10139 jtab = newiTempLabel(NULL);
10140 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10141 pic14_emitcode("jmp","@a+dptr");
10142 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10144 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10145 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10146 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10147 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10149 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10150 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10151 emitpLabel(jtab->key);
10153 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10155 /* now generate the jump labels */
10156 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10157 jtab = setNextItem(IC_JTLABELS(ic))) {
10158 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10159 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10165 /*-----------------------------------------------------------------*/
10166 /* genMixedOperation - gen code for operators between mixed types */
10167 /*-----------------------------------------------------------------*/
10169 TSD - Written for the PIC port - but this unfortunately is buggy.
10170 This routine is good in that it is able to efficiently promote
10171 types to different (larger) sizes. Unfortunately, the temporary
10172 variables that are optimized out by this routine are sometimes
10173 used in other places. So until I know how to really parse the
10174 iCode tree, I'm going to not be using this routine :(.
10176 static int genMixedOperation (iCode *ic)
10180 operand *result = IC_RESULT(ic);
10181 sym_link *ctype = operandType(IC_LEFT(ic));
10182 operand *right = IC_RIGHT(ic);
10188 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10190 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10196 nextright = IC_RIGHT(nextic);
10197 nextleft = IC_LEFT(nextic);
10198 nextresult = IC_RESULT(nextic);
10200 aopOp(right,ic,FALSE);
10201 aopOp(result,ic,FALSE);
10202 aopOp(nextright, nextic, FALSE);
10203 aopOp(nextleft, nextic, FALSE);
10204 aopOp(nextresult, nextic, FALSE);
10206 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10208 operand *t = right;
10212 pic14_emitcode(";remove right +","");
10214 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10216 operand *t = right;
10220 pic14_emitcode(";remove left +","");
10224 big = AOP_SIZE(nextleft);
10225 small = AOP_SIZE(nextright);
10227 switch(nextic->op) {
10230 pic14_emitcode(";optimize a +","");
10231 /* if unsigned or not an integral type */
10232 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10233 pic14_emitcode(";add a bit to something","");
10236 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10238 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10239 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10240 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10242 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10250 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10251 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10252 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10255 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10257 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10258 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10259 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10260 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10261 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10264 pic14_emitcode("rlf","known_zero,w");
10271 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10272 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10273 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10275 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10285 freeAsmop(right,NULL,ic,TRUE);
10286 freeAsmop(result,NULL,ic,TRUE);
10287 freeAsmop(nextright,NULL,ic,TRUE);
10288 freeAsmop(nextleft,NULL,ic,TRUE);
10290 nextic->generated = 1;
10297 /*-----------------------------------------------------------------*/
10298 /* genCast - gen code for casting */
10299 /*-----------------------------------------------------------------*/
10300 static void genCast (iCode *ic)
10302 operand *result = IC_RESULT(ic);
10303 sym_link *ctype = operandType(IC_LEFT(ic));
10304 sym_link *rtype = operandType(IC_RIGHT(ic));
10305 operand *right = IC_RIGHT(ic);
10309 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10310 /* if they are equivalent then do nothing */
10311 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10314 aopOp(right,ic,FALSE) ;
10315 aopOp(result,ic,FALSE);
10317 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10319 /* if the result is a bit */
10320 if (AOP_TYPE(result) == AOP_CRY) {
10321 /* if the right size is a literal then
10322 we know what the value is */
10323 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10324 if (AOP_TYPE(right) == AOP_LIT) {
10326 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10327 popGet(AOP(result),0));
10329 if (((int) operandLitValue(right)))
10330 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10331 AOP(result)->aopu.aop_dir,
10332 AOP(result)->aopu.aop_dir);
10334 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10335 AOP(result)->aopu.aop_dir,
10336 AOP(result)->aopu.aop_dir);
10341 /* the right is also a bit variable */
10342 if (AOP_TYPE(right) == AOP_CRY) {
10345 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10347 pic14_emitcode("clrc","");
10348 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10349 AOP(right)->aopu.aop_dir,
10350 AOP(right)->aopu.aop_dir);
10351 aopPut(AOP(result),"c",0);
10355 /* we need to or */
10356 if (AOP_TYPE(right) == AOP_REG) {
10357 emitpcode(POC_BCF, popGet(AOP(result),0));
10358 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10359 emitpcode(POC_BSF, popGet(AOP(result),0));
10361 pic14_toBoolean(right);
10362 aopPut(AOP(result),"a",0);
10366 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10368 size = AOP_SIZE(result);
10370 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10372 emitpcode(POC_CLRF, popGet(AOP(result),0));
10373 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10374 emitpcode(POC_INCF, popGet(AOP(result),0));
10377 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10382 /* if they are the same size : or less */
10383 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10385 /* if they are in the same place */
10386 if (pic14_sameRegs(AOP(right),AOP(result)))
10389 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10390 if (IS_PTR_CONST(rtype))
10391 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10392 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10393 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10395 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10396 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10397 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10398 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10399 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10400 if(AOP_SIZE(result) <2)
10401 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10405 /* if they in different places then copy */
10406 size = AOP_SIZE(result);
10409 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10410 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10412 //aopPut(AOP(result),
10413 // aopGet(AOP(right),offset,FALSE,FALSE),
10423 /* if the result is of type pointer */
10424 if (IS_PTR(ctype)) {
10427 sym_link *type = operandType(right);
10428 sym_link *etype = getSpec(type);
10429 DEBUGpic14_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10431 /* pointer to generic pointer */
10432 if (IS_GENPTR(ctype)) {
10436 p_type = DCL_TYPE(type);
10438 /* we have to go by the storage class */
10439 p_type = PTR_TYPE(SPEC_OCLS(etype));
10441 /* if (SPEC_OCLS(etype)->codesp ) */
10442 /* p_type = CPOINTER ; */
10444 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10445 /* p_type = FPOINTER ; */
10447 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10448 /* p_type = PPOINTER; */
10450 /* if (SPEC_OCLS(etype) == idata ) */
10451 /* p_type = IPOINTER ; */
10453 /* p_type = POINTER ; */
10456 /* the first two bytes are known */
10457 DEBUGpic14_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10458 size = GPTRSIZE - 1;
10461 if(offset < AOP_SIZE(right)) {
10462 DEBUGpic14_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10463 if ((AOP_TYPE(right) == AOP_PCODE) &&
10464 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10465 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10466 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10468 aopPut(AOP(result),
10469 aopGet(AOP(right),offset,FALSE,FALSE),
10473 emitpcode(POC_CLRF,popGet(AOP(result),offset));
10476 /* the last byte depending on type */
10480 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10483 pic14_emitcode(";BUG!? ","%d",__LINE__);
10487 pic14_emitcode(";BUG!? ","%d",__LINE__);
10491 pic14_emitcode(";BUG!? ","%d",__LINE__);
10496 /* this should never happen */
10497 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10498 "got unknown pointer type");
10501 //aopPut(AOP(result),l, GPTRSIZE - 1);
10505 /* just copy the pointers */
10506 size = AOP_SIZE(result);
10509 aopPut(AOP(result),
10510 aopGet(AOP(right),offset,FALSE,FALSE),
10519 /* so we now know that the size of destination is greater
10520 than the size of the source.
10521 Now, if the next iCode is an operator then we might be
10522 able to optimize the operation without performing a cast.
10524 if(genMixedOperation(ic))
10527 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10529 /* we move to result for the size of source */
10530 size = AOP_SIZE(right);
10533 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10534 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10538 /* now depending on the sign of the destination */
10539 size = AOP_SIZE(result) - AOP_SIZE(right);
10540 /* if unsigned or not an integral type */
10541 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10543 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10545 /* we need to extend the sign :{ */
10548 /* Save one instruction of casting char to int */
10549 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10550 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10551 emitpcode(POC_DECF, popGet(AOP(result),offset));
10553 emitpcodeNULLop(POC_CLRW);
10556 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10558 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10560 emitpcode(POC_MOVLW, popGetLit(0xff));
10563 emitpcode(POC_MOVWF, popGet(AOP(result),offset++));
10568 freeAsmop(right,NULL,ic,TRUE);
10569 freeAsmop(result,NULL,ic,TRUE);
10573 /*-----------------------------------------------------------------*/
10574 /* genDjnz - generate decrement & jump if not zero instrucion */
10575 /*-----------------------------------------------------------------*/
10576 static int genDjnz (iCode *ic, iCode *ifx)
10578 symbol *lbl, *lbl1;
10580 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10585 /* if the if condition has a false label
10586 then we cannot save */
10590 /* if the minus is not of the form
10592 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10593 !IS_OP_LITERAL(IC_RIGHT(ic)))
10596 if (operandLitValue(IC_RIGHT(ic)) != 1)
10599 /* if the size of this greater than one then no
10601 if (getSize(operandType(IC_RESULT(ic))) > 1)
10604 /* otherwise we can save BIG */
10605 lbl = newiTempLabel(NULL);
10606 lbl1= newiTempLabel(NULL);
10608 aopOp(IC_RESULT(ic),ic,FALSE);
10610 if (IS_AOP_PREG(IC_RESULT(ic))) {
10611 pic14_emitcode("dec","%s",
10612 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10613 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10614 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10618 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10619 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10621 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10622 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10625 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10626 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10627 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10628 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10631 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10632 ifx->generated = 1;
10636 /*-----------------------------------------------------------------*/
10637 /* genReceive - generate code for a receive iCode */
10638 /*-----------------------------------------------------------------*/
10639 static void genReceive (iCode *ic)
10642 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10644 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10645 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10646 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10648 int size = getSize(operandType(IC_RESULT(ic)));
10649 int offset = fReturnSizePic - size;
10651 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10652 fReturn[fReturnSizePic - offset - 1] : "acc"));
10655 aopOp(IC_RESULT(ic),ic,FALSE);
10656 size = AOP_SIZE(IC_RESULT(ic));
10659 pic14_emitcode ("pop","acc");
10660 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10665 aopOp(IC_RESULT(ic),ic,FALSE);
10667 assignResultValue(IC_RESULT(ic));
10670 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10673 /*-----------------------------------------------------------------*/
10674 /* genDummyRead - generate code for dummy read of volatiles */
10675 /*-----------------------------------------------------------------*/
10677 genDummyRead (iCode * ic)
10680 pic14_emitcode ("; genDummyRead","");
10681 pic14_emitcode ("; not implemented","");
10686 /*-----------------------------------------------------------------*/
10687 /* genpic14Code - generate code for pic14 based controllers */
10688 /*-----------------------------------------------------------------*/
10690 * At this point, ralloc.c has gone through the iCode and attempted
10691 * to optimize in a way suitable for a PIC. Now we've got to generate
10692 * PIC instructions that correspond to the iCode.
10694 * Once the instructions are generated, we'll pass through both the
10695 * peep hole optimizer and the pCode optimizer.
10696 *-----------------------------------------------------------------*/
10698 void genpic14Code (iCode *lic)
10705 lineHead = lineCurr = NULL;
10707 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10710 /* if debug information required */
10711 if (options.debug && currFunc) {
10713 debugFile->writeFunction (currFunc, lic);
10718 for (ic = lic ; ic ; ic = ic->next ) {
10720 //DEBUGpic14_emitcode(";ic","");
10721 //fprintf (stderr, "in ic loop\n");
10722 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10723 //ic->lineno, printCLine(ic->filename, ic->lineno));
10725 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10727 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10728 cline = printCLine (ic->filename, ic->lineno);
10729 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10730 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10731 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10734 if (options.iCodeInAsm) {
10735 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10737 /* if the result is marked as
10738 spilt and rematerializable or code for
10739 this has already been generated then
10741 if (resultRemat(ic) || ic->generated )
10744 /* depending on the operation */
10763 /* IPOP happens only when trying to restore a
10764 spilt live range, if there is an ifx statement
10765 following this pop then the if statement might
10766 be using some of the registers being popped which
10767 would destory the contents of the register so
10768 we need to check for this condition and handle it */
10770 ic->next->op == IFX &&
10771 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10772 genIfx (ic->next,ic);
10790 genEndFunction (ic);
10810 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10827 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10831 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10838 /* note these two are xlated by algebraic equivalence
10839 during parsing SDCC.y */
10840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10841 "got '>=' or '<=' shouldn't have come here");
10845 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10857 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10861 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10865 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10889 genRightShift (ic);
10892 case GET_VALUE_AT_ADDRESS:
10897 if (POINTER_SET(ic))
10924 addSet(&_G.sendSet,ic);
10927 case DUMMY_READ_VOLATILE:
10937 /* now we are ready to call the
10938 peep hole optimizer */
10939 if (!options.nopeep) {
10940 peepHole (&lineHead);
10942 /* now do the actual printing */
10943 printLine (lineHead,codeOutFile);
10946 DFPRINTF((stderr,"printing pBlock\n\n"));
10947 printpBlock(stdout,pb);
10954 aop_isLitLike (asmop *aop)
10957 if (aop->type == AOP_LIT) return 1;
10958 if (aop->type == AOP_IMMD) return 1;
10959 if ((aop->type == AOP_PCODE) &&
10960 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10962 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10963 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10970 op_isLitLike (operand *op)
10973 if (aop_isLitLike (AOP(op))) return 1;