1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 cont'd - Raphael Neider <rneider AT web.de> (2005)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
29 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
30 Made everything static
31 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
47 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
56 static int labelOffset=0;
57 extern int debug_verbose;
58 extern int pic14_hasInterrupt;
59 //static int optimized_for_speed = 0;
61 /* max_key keeps track of the largest label number used in
62 a function. This is then used to adjust the label offset
63 for the next function.
66 static int GpsuedoStkPtr=0;
67 static int pic14_inISR = 0;
69 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
70 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
71 const char *AopType(short type);
73 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
75 /* this is the down and dirty file with all kinds of
76 kludgy & hacky stuff. This is what it is all about
77 CODE GENERATION for a specific MCU . some of the
78 routines may be reusable, will have to see */
80 static char *zero = "0x00";
81 static char *one = "0x01";
82 static char *spname = "sp";
84 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
85 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
86 static char **fReturn = fReturnpic14;
88 //static char *accUse[] = {"a","b"};
90 //static short rbank = -1;
102 /* Resolved ifx structure. This structure stores information
103 about an iCode ifx that makes it easier to generate code.
105 typedef struct resolvedIfx {
106 symbol *lbl; /* pointer to a label */
107 int condition; /* true or false ifx */
108 int generated; /* set true when the code associated with the ifx
112 extern int pic14_ptrRegReq ;
113 extern int pic14_nRegs;
114 extern struct dbuf_s *codeOutBuf;
115 static void saverbank (int, iCode *,bool);
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
124 0x07, 0x03, 0x01, 0x00};
129 /*-----------------------------------------------------------------*/
130 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
131 /* exponent of 2 is returned, otherwise -1 is */
133 /* note that this is similar to the function `powof2' in SDCCsymt */
137 /*-----------------------------------------------------------------*/
138 static int my_powof2 (unsigned long num)
141 if( (num & (num-1)) == 0) {
154 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
157 DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
159 ((result) ? AopType(AOP_TYPE(result)) : "-"),
160 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
161 ((result) ? AOP_SIZE(result) : 0),
162 ((left) ? AopType(AOP_TYPE(left)) : "-"),
163 ((left) ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
164 ((left) ? AOP_SIZE(left) : 0),
165 ((right) ? AopType(AOP_TYPE(right)) : "-"),
166 ((right) ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
167 ((right) ? AOP_SIZE(right) : 0));
171 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
174 DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
176 ((result) ? AopType(AOP_TYPE(result)) : "-"),
177 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
178 ((left) ? AopType(AOP_TYPE(left)) : "-"),
179 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
180 ((right) ? AopType(AOP_TYPE(right)) : "-"),
181 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
185 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
188 char lb[INITIAL_INLINEASM];
189 unsigned char *lbp = (unsigned char *)lb;
191 if(!debug_verbose && !options.debug)
198 sprintf(lb,"%s\t",inst);
200 sprintf(lb,"%s",inst);
201 vsprintf(lb+(strlen(lb)),fmt,ap);
205 while (isspace(*lbp)) lbp++;
208 lineCurr = (lineCurr ?
209 connectLine(lineCurr,newLineNode(lb)) :
210 (lineHead = newLineNode(lb)));
211 lineCurr->isInline = _G.inLine;
212 lineCurr->isDebug = _G.debugLine;
214 addpCode2pBlock(pb,newpCodeCharP(lb));
219 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
221 #if defined (HAVE_VSNPRINTF)
222 vsnprintf (buf, size, fmt, ap);
223 #elif defined (HAVE_VSPRINTF)
224 vsprintf (buf, size, fmt, ap);
225 if (strlen (buf) >= size)
227 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
229 #elif defined (HAVE_SNPRINTF)
230 snprintf (buf, size, "vs(n)printf required");
231 #elif defined (HAVE_SRINTF)
232 sprintf (buf, "vs(n)printf required");
233 if (strlen (buf) >= size)
235 fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
238 assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
242 void emitpComment (const char *fmt, ...)
249 Safe_vsnprintf (buffer, 4096, fmt, va);
250 //fprintf (stderr, "%s\n" ,buffer);
251 addpCode2pBlock (pb, newpCodeCharP (buffer));
254 Safe_vsnprintf (buffer, 4096, fmt, va);
255 fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
261 void emitpLabel(int key)
263 addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
266 /* gen.h defines a macro emitpcode that should be used to call emitpcode
267 * as this allows for easy debugging (ever asked the question: where was
268 * this instruction geenrated? Here is the answer... */
269 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
272 addpCode2pBlock(pb,newpCode(poc,pcop));
274 static int has_warned = 0;
276 DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
279 fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
284 void emitpcodeNULLop(PIC_OPCODE poc)
287 addpCode2pBlock(pb,newpCode(poc,NULL));
292 /*-----------------------------------------------------------------*/
293 /* pic14_emitcode - writes the code into a file : for now it is simple */
294 /*-----------------------------------------------------------------*/
295 void pic14_emitcode (char *inst,char *fmt, ...)
298 char lb[INITIAL_INLINEASM];
305 sprintf(lb,"%s\t",inst);
307 sprintf(lb,"%s",inst);
308 vsprintf(lb+(strlen(lb)),fmt,ap);
312 while (isspace(*lbp)) lbp++;
315 lineCurr = (lineCurr ?
316 connectLine(lineCurr,newLineNode(lb)) :
317 (lineHead = newLineNode(lb)));
318 lineCurr->isInline = _G.inLine;
319 lineCurr->isDebug = _G.debugLine;
320 lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
323 addpCode2pBlock(pb,newpCodeCharP(lb));
328 /*-----------------------------------------------------------------*/
329 /* pic14_emitDebuggerSymbol - associate the current code location */
330 /* with a debugger symbol */
331 /*-----------------------------------------------------------------*/
333 pic14_emitDebuggerSymbol (char * debugSym)
336 pic14_emitcode ("", ";%s ==.", debugSym);
341 /*-----------------------------------------------------------------*/
342 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
343 /*-----------------------------------------------------------------*/
344 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
346 bool r0iu = FALSE , r1iu = FALSE;
347 bool r0ou = FALSE , r1ou = FALSE;
349 /* the logic: if r0 & r1 used in the instruction
350 then we are in trouble otherwise */
352 /* first check if r0 & r1 are used by this
353 instruction, in which case we are in trouble */
354 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
355 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
360 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
361 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
363 /* if no usage of r0 then return it */
364 if (!r0iu && !r0ou) {
365 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
366 (*aopp)->type = AOP_R0;
368 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
371 /* if no usage of r1 then return it */
372 if (!r1iu && !r1ou) {
373 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
374 (*aopp)->type = AOP_R1;
376 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
379 /* now we know they both have usage */
380 /* if r0 not used in this instruction */
382 /* push it if not already pushed */
384 //pic14_emitcode ("push","%s",
385 // pic14_regWithIdx(R0_IDX)->dname);
389 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
390 (*aopp)->type = AOP_R0;
392 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
395 /* if r1 not used then */
398 /* push it if not already pushed */
400 //pic14_emitcode ("push","%s",
401 // pic14_regWithIdx(R1_IDX)->dname);
405 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
406 (*aopp)->type = AOP_R1;
407 return pic14_regWithIdx(R1_IDX);
411 /* I said end of world but not quite end of world yet */
412 /* if this is a result then we can push it on the stack*/
414 (*aopp)->type = AOP_STK;
418 /* other wise this is true end of the world */
419 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
420 "getFreePtr should never reach here");
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp */
427 /*-----------------------------------------------------------------*/
428 asmop *newAsmop (short type)
432 aop = Safe_calloc(1,sizeof(asmop));
437 static void genSetDPTR(int n)
441 pic14_emitcode(";", "Select standard DPTR");
442 pic14_emitcode("mov", "dps, #0x00");
446 pic14_emitcode(";", "Select alternate DPTR");
447 pic14_emitcode("mov", "dps, #0x01");
451 /*-----------------------------------------------------------------*/
452 /* resolveIfx - converts an iCode ifx into a form more useful for */
453 /* generating code */
454 /*-----------------------------------------------------------------*/
455 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
460 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
462 resIfx->condition = 1; /* assume that the ifx is true */
463 resIfx->generated = 0; /* indicate that the ifx has not been used */
466 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
468 DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
469 __FUNCTION__,__LINE__,resIfx->lbl->key);
473 resIfx->lbl = IC_TRUE(ifx);
475 resIfx->lbl = IC_FALSE(ifx);
476 resIfx->condition = 0;
480 DEBUGpic14_emitcode("; ***","ifx true is non-null");
482 DEBUGpic14_emitcode("; ***","ifx false is non-null");
486 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type */
491 /*-----------------------------------------------------------------*/
493 static int pointerCode (sym_link *etype)
496 return PTR_TYPE(SPEC_OCLS(etype));
501 /*-----------------------------------------------------------------*/
502 /* aopForSym - for a true symbol */
503 /*-----------------------------------------------------------------*/
504 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
507 memmap *space= SPEC_OCLS(sym->etype);
509 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
510 /* if already has one */
514 //DEBUGpic14_emitcode(";","%d",__LINE__);
515 /* if it is in direct space */
516 if (IN_DIRSPACE(space)) {
517 sym->aop = aop = newAsmop (AOP_DIR);
518 aop->aopu.aop_dir = sym->rname ;
519 aop->size = getSize(sym->type);
520 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
524 /* special case for a function */
525 if (IS_FUNC(sym->type)) {
527 sym->aop = aop = newAsmop(AOP_PCODE);
528 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530 PCOI(aop->aopu.pcop)->_function = 1;
531 PCOI(aop->aopu.pcop)->index = 0;
532 aop->size = FPTRSIZE;
534 sym->aop = aop = newAsmop(AOP_IMMD);
535 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536 strcpy(aop->aopu.aop_immd,sym->rname);
537 aop->size = FPTRSIZE;
539 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
543 if (IS_ARRAY(sym->type)) {
544 sym->aop = aop = newAsmop(AOP_PCODE);
545 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
546 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
547 PCOI(aop->aopu.pcop)->_function = 0;
548 PCOI(aop->aopu.pcop)->index = 0;
549 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
551 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
555 /* only remaining is far space */
556 /* in which case DPTR gets the address */
557 sym->aop = aop = newAsmop(AOP_PCODE);
559 aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
560 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561 PCOI(aop->aopu.pcop)->index = 0;
563 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
564 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
566 allocDirReg (IC_LEFT(ic));
568 aop->size = FPTRSIZE;
570 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571 sym->aop = aop = newAsmop(AOP_DPTR);
572 pic14_emitcode ("mov","dptr,#%s", sym->rname);
573 aop->size = getSize(sym->type);
575 DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
578 /* if it is in code space */
579 if (IN_CODESPACE(space))
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
590 symbol *sym = OP_SYMBOL(op);
592 asmop *aop = newAsmop(AOP_PCODE);
596 ic = sym->rematiCode;
598 DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599 if(IS_OP_POINTER(op)) {
600 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
604 val += (int) operandLitValue(IC_RIGHT(ic));
605 } else if (ic->op == '-') {
606 val -= (int) operandLitValue(IC_RIGHT(ic));
610 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
613 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614 aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
615 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616 PCOI(aop->aopu.pcop)->index = val;
618 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
619 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620 val, IS_PTR_CONST(operandType(op)));
622 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
624 allocDirReg (IC_LEFT(ic));
629 int aopIdx (asmop *aop, int offset)
634 if(aop->type != AOP_REG)
637 return aop->aopu.aop_reg[offset]->rIdx;
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
648 /* if they have registers in common */
649 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
652 sym1 = OP_SYMBOL(op1);
653 sym2 = OP_SYMBOL(op2);
655 if (sym1->nRegs == 0 || sym2->nRegs == 0)
658 for (i = 0 ; i < sym1->nRegs ; i++) {
663 for (j = 0 ; j < sym2->nRegs ;j++ ) {
667 if (sym2->regs[j] == sym1->regs[i])
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
682 /* if they not symbols */
683 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
686 sym1 = OP_SYMBOL(op1);
687 sym2 = OP_SYMBOL(op2);
689 /* if both are itemps & one is spilt
690 and the other is not then false */
691 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692 sym1->isspilt != sym2->isspilt )
695 /* if they are the same */
699 if (sym1->rname[0] && sym2->rname[0]
700 && strcmp (sym1->rname, sym2->rname) == 0)
704 /* if left is a tmp & right is not */
708 (sym1->usl.spillLoc == sym2))
715 (sym2->usl.spillLoc == sym1))
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
731 if (aop1->type != AOP_REG ||
732 aop2->type != AOP_REG )
735 if (aop1->size != aop2->size )
738 for (i = 0 ; i < aop1->size ; i++ )
739 if (aop1->aopu.aop_reg[i] !=
740 aop2->aopu.aop_reg[i] )
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand : */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
758 /* if this a literal */
759 if (IS_OP_LITERAL(op)) {
760 op->aop = aop = newAsmop(AOP_LIT);
761 aop->aopu.aop_lit = op->operand.valOperand;
762 aop->size = getSize(operandType(op));
767 sym_link *type = operandType(op);
768 if(IS_PTR_CONST(type))
769 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
772 /* if already has a asmop then continue */
776 /* if the underlying symbol has a aop */
777 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778 DEBUGpic14_emitcode(";","%d",__LINE__);
779 op->aop = OP_SYMBOL(op)->aop;
783 /* if this is a true symbol */
784 if (IS_TRUE_SYMOP(op)) {
785 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
786 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
790 /* this is a temporary : this has
796 e) can be a return use only */
801 /* if the type is a conditional */
802 if (sym->regType == REG_CND) {
803 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
808 /* if it is spilt then two situations
810 b) has a spill location */
811 if (sym->isspilt || sym->nRegs == 0) {
813 DEBUGpic14_emitcode(";","%d",__LINE__);
814 /* rematerialize it NOW */
817 sym->aop = op->aop = aop = aopForRemat (op);
818 aop->size = getSize(sym->type);
819 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
824 /* WREG is not usable as an ordinary operand with PIC architecture,
825 * one might introduce a scratch register that can be used to make
826 * WREG accesible as an operand... disable WREG for now */
829 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830 aop->size = getSize(sym->type);
831 for ( i = 0 ; i < 2 ; i++ )
832 aop->aopu.aop_str[i] = accUse[i];
833 DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
839 if(sym->isptr) { // && sym->uptr
840 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
841 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
843 //PCOI(aop->aopu.pcop)->_const = 0;
844 //PCOI(aop->aopu.pcop)->index = 0;
846 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
847 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
849 //allocDirReg (IC_LEFT(ic));
851 aop->size = getSize(sym->type);
852 DEBUGpic14_emitcode(";","%d",__LINE__);
859 aop = op->aop = sym->aop = newAsmop(AOP_STR);
860 aop->size = getSize(sym->type);
861 for ( i = 0 ; i < fReturnSizePic ; i++ )
862 aop->aopu.aop_str[i] = fReturn[i];
864 DEBUGpic14_emitcode(";","%d",__LINE__);
869 /* else spill location */
870 if (sym->usl.spillLoc)
872 asmop *oldAsmOp = NULL;
874 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
876 /* force a new aop if sizes differ */
877 oldAsmOp = sym->usl.spillLoc->aop;
878 sym->usl.spillLoc->aop = NULL;
880 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
881 __FUNCTION__,__LINE__,
882 sym->usl.spillLoc->rname,
883 sym->rname, sym->usl.spillLoc->offset);
885 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
888 /* Don't reuse the new aop, go with the last one */
889 sym->usl.spillLoc->aop = oldAsmOp;
891 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
892 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
894 sym->usl.spillLoc->offset);
895 aop->size = getSize(sym->type);
902 sym_link *type = operandType(op);
903 if(IS_PTR_CONST(type))
904 DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
907 /* must be in a register */
908 DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
909 sym->aop = op->aop = aop = newAsmop(AOP_REG);
910 aop->size = sym->nRegs;
911 for ( i = 0 ; i < sym->nRegs ;i++)
912 aop->aopu.aop_reg[i] = sym->regs[i];
915 /*-----------------------------------------------------------------*/
916 /* freeAsmop - free up the asmop given to an operand */
917 /*----------------------------------------------------------------*/
918 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
935 /* depending on the asmop type only three cases need work AOP_RO
936 , AOP_R1 && AOP_STK */
942 pic14_emitcode ("pop","ar0");
946 bitVectUnSetBit(ic->rUsed,R0_IDX);
952 pic14_emitcode ("pop","ar1");
956 bitVectUnSetBit(ic->rUsed,R1_IDX);
962 int stk = aop->aopu.aop_stk + aop->size;
963 bitVectUnSetBit(ic->rUsed,R0_IDX);
964 bitVectUnSetBit(ic->rUsed,R1_IDX);
966 getFreePtr(ic,&aop,FALSE);
968 if (options.stack10bit)
970 /* I'm not sure what to do here yet... */
973 "*** Warning: probably generating bad code for "
974 "10 bit stack mode.\n");
978 pic14_emitcode ("mov","a,_bp");
979 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
980 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
982 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
986 pic14_emitcode("pop","acc");
987 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
989 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
992 freeAsmop(op,NULL,ic,TRUE);
994 pic14_emitcode("pop","ar0");
999 pic14_emitcode("pop","ar1");
1007 /* all other cases just dealloc */
1011 OP_SYMBOL(op)->aop = NULL;
1012 /* if the symbol has a spill */
1014 SPIL_LOC(op)->aop = NULL;
1019 /*-----------------------------------------------------------------*/
1020 /* aopGet - for fetching value of the aop */
1021 /*-----------------------------------------------------------------*/
1022 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1027 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1028 /* offset is greater than
1031 if (offset > (aop->size - 1) &&
1032 aop->type != AOP_LIT)
1035 /* depending on type */
1036 switch (aop->type) {
1040 DEBUGpic14_emitcode(";","%d",__LINE__);
1041 /* if we need to increment it */
1042 while (offset > aop->coff) {
1043 pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1047 while (offset < aop->coff) {
1048 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1052 aop->coff = offset ;
1054 pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1055 return (dname ? "acc" : "a");
1057 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1058 rs = Safe_calloc(1,strlen(s)+1);
1064 DEBUGpic14_emitcode(";","%d",__LINE__);
1065 if (aop->type == AOP_DPTR2)
1070 while (offset > aop->coff) {
1071 pic14_emitcode ("inc","dptr");
1075 while (offset < aop->coff) {
1076 pic14_emitcode("lcall","__decdptr");
1082 pic14_emitcode("clr","a");
1083 pic14_emitcode("movc","a,@a+dptr");
1086 pic14_emitcode("movx","a,@dptr");
1089 if (aop->type == AOP_DPTR2)
1094 return (dname ? "acc" : "a");
1099 sprintf (s,"%s",aop->aopu.aop_immd);
1102 sprintf(s,"(%s >> %d)",
1107 aop->aopu.aop_immd);
1108 DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1109 rs = Safe_calloc(1,strlen(s)+1);
1115 sprintf(s,"(%s + %d)",
1118 DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1120 sprintf(s,"%s",aop->aopu.aop_dir);
1121 rs = Safe_calloc(1,strlen(s)+1);
1127 // return aop->aopu.aop_reg[offset]->dname;
1129 return aop->aopu.aop_reg[offset]->name;
1132 //pic14_emitcode(";","%d",__LINE__);
1133 return aop->aopu.aop_dir;
1136 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1137 return "AOP_accumulator_bug";
1140 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1141 rs = Safe_strdup(s);
1145 aop->coff = offset ;
1146 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1149 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1151 return aop->aopu.aop_str[offset];
1155 pCodeOp *pcop = aop->aopu.pcop;
1156 DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1158 if (pcop->type == PO_IMMEDIATE) {
1159 offset += PCOI(pcop)->index;
1162 DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1163 sprintf(s,"(%s+%d)", pcop->name,offset);
1165 DEBUGpic14_emitcode(";","%s",pcop->name);
1166 sprintf(s,"%s", pcop->name);
1169 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1172 rs = Safe_calloc(1,strlen(s)+1);
1178 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179 "aopget got unsupported aop->type");
1184 /*-----------------------------------------------------------------*/
1185 /* popGetTempReg - create a new temporary pCodeOp */
1186 /*-----------------------------------------------------------------*/
1187 pCodeOp *popGetTempReg(void)
1192 pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1193 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1194 PCOR(pcop)->r->wasUsed=1;
1195 PCOR(pcop)->r->isFree=0;
1201 /*-----------------------------------------------------------------*/
1202 /* popReleaseTempReg - create a new temporary pCodeOp */
1203 /*-----------------------------------------------------------------*/
1204 void popReleaseTempReg(pCodeOp *pcop)
1207 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1208 PCOR(pcop)->r->isFree = 1;
1211 /*-----------------------------------------------------------------*/
1212 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetLabel(unsigned int key)
1217 DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1219 if(key>(unsigned int)max_key)
1222 return newpCodeOpLabel(NULL,key+100+labelOffset);
1225 /*-------------------------------------------------------------------*/
1226 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1227 /*-------------------------------------------------------------------*/
1228 pCodeOp *popGetHighLabel(unsigned int key)
1231 pcop = popGetLabel(key);
1232 PCOLAB(pcop)->offset = 1;
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLit - asm operator to pcode operator conversion */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLit(unsigned int lit)
1242 return newpCodeOpLit((unsigned char)lit);
1245 /*-----------------------------------------------------------------*/
1246 /* popGetImmd - asm operator to pcode immediate conversion */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1251 return newpCodeOpImmd(name, offset,index, 0, is_func);
1254 extern set *externs;
1256 /*-----------------------------------------------------------------*/
1257 /* popGetWithString - asm operator to pcode operator conversion */
1258 /*-----------------------------------------------------------------*/
1259 pCodeOp *popGetWithString(char *str, int isExtern)
1265 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1269 pcop = newpCodeOp(str,PO_STR);
1270 PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1275 pCodeOp *popGetExternal (char *str, int isReg)
1280 pcop = newpCodeOpRegFromStr(str);
1282 pcop = popGetWithString (str, 1);
1288 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1290 if (!strcmp (str, sym->rname)) break;
1295 sym = newSymbol(str, 0);
1296 strncpy(sym->rname, str, SDCC_NAME_MAX);
1297 addSet (&externs, sym);
1304 /*-----------------------------------------------------------------*/
1305 /* popRegFromString - */
1306 /*-----------------------------------------------------------------*/
1307 pCodeOp *popRegFromString(char *str, int size, int offset)
1310 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1311 pcop->type = PO_DIR;
1313 DEBUGpic14_emitcode(";","%d",__LINE__);
1318 pcop->name = Safe_calloc(1,strlen(str)+1);
1319 strcpy(pcop->name,str);
1321 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1323 PCOR(pcop)->r = dirregWithName(pcop->name);
1324 if(PCOR(pcop)->r == NULL) {
1325 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1326 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1327 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1329 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1331 PCOR(pcop)->instance = offset;
1336 /*-----------------------------------------------------------------*/
1337 /*-----------------------------------------------------------------*/
1338 pCodeOp *popRegFromIdx(int rIdx)
1342 DEBUGpic14_emitcode ("; ***","%s,%d , rIdx=0x%x",
1343 __FUNCTION__,__LINE__,rIdx);
1345 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1347 PCOR(pcop)->rIdx = rIdx;
1348 PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1349 PCOR(pcop)->r->isFree = 0;
1350 PCOR(pcop)->r->wasUsed = 1;
1352 pcop->type = PCOR(pcop)->r->pc_type;
1358 /*-----------------------------------------------------------------*/
1359 /* popGet - asm operator to pcode operator conversion */
1360 /*-----------------------------------------------------------------*/
1361 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1363 //char *s = buffer ;
1368 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1369 /* offset is greater than
1375 /* XXX: still needed for BIT operands (AOP_CRY) */
1376 if (offset > (aop->size - 1) &&
1377 aop->type != AOP_LIT &&
1378 aop->type != AOP_PCODE)
1380 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1381 return NULL; //zero;
1384 /* depending on type */
1385 switch (aop->type) {
1392 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1396 DEBUGpic14_emitcode(";","%d",__LINE__);
1397 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1400 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1402 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1403 pcop->type = PO_DIR;
1405 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1406 strcpy(pcop->name,aop->aopu.aop_dir);
1407 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1408 if(PCOR(pcop)->r == NULL) {
1409 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1410 PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1411 DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1413 DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset);
1415 PCOR(pcop)->instance = offset;
1423 assert (offset < aop->size);
1424 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1426 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1427 PCOR(pcop)->rIdx = rIdx;
1428 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1429 PCOR(pcop)->r->wasUsed=1;
1430 PCOR(pcop)->r->isFree=0;
1432 PCOR(pcop)->instance = offset;
1433 pcop->type = PCOR(pcop)->r->pc_type;
1434 //rs = aop->aopu.aop_reg[offset]->name;
1435 DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1440 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1441 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1442 //if(PCOR(pcop)->r == NULL)
1443 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1447 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1450 DEBUGpic14_emitcode(";","%d %s",__LINE__,aop->aopu.aop_str[offset]);
1451 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1453 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1454 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1455 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1456 pcop->type = PCOR(pcop)->r->pc_type;
1457 pcop->name = PCOR(pcop)->r->name;
1464 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1466 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1467 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1468 switch (aop->aopu.pcop->type)
1471 pcop = pCodeOpCopy (aop->aopu.pcop);
1472 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1473 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1474 PCOI(pcop)->index += offset;
1475 //PCOI(pcop)->offset = 0;
1478 pcop = pCodeOpCopy (aop->aopu.pcop);
1479 PCOR(pcop)->instance = offset;
1482 assert ( !"unhandled pCode type" );
1488 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1489 "popGet got unsupported aop->type");
1493 /*-----------------------------------------------------------------*/
1494 /* popGetAddr - access the low/high word of a symbol (immediate) */
1495 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1496 /*-----------------------------------------------------------------*/
1497 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1499 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1501 pCodeOp *pcop = aop->aopu.pcop;
1502 assert (offset <= GPTRSIZE);
1504 /* special case: index >= 2 should return GPOINTER-style values */
1507 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1511 pcop = pCodeOpCopy (pcop);
1512 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1513 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1514 PCOI(pcop)->offset += offset;
1515 PCOI(pcop)->index += index;
1516 //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1519 return popGet (aop, offset + index);
1523 /*-----------------------------------------------------------------*/
1524 /* aopPut - puts a string for a aop */
1525 /*-----------------------------------------------------------------*/
1526 void aopPut (asmop *aop, char *s, int offset)
1531 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1533 if (aop->size && offset > ( aop->size - 1)) {
1534 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1535 "aopPut got offset > aop->size");
1539 /* will assign value to value */
1540 /* depending on where it is ofcourse */
1541 switch (aop->type) {
1544 sprintf(d,"(%s + %d)",
1545 aop->aopu.aop_dir,offset);
1546 fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1549 sprintf(d,"%s",aop->aopu.aop_dir);
1552 DEBUGpic14_emitcode(";","%d",__LINE__);
1554 pic14_emitcode("movf","%s,w",s);
1555 pic14_emitcode("movwf","%s",d);
1558 pic14_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1559 if(offset >= aop->size) {
1560 emitpcode(POC_CLRF,popGet(aop,offset));
1563 emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1566 emitpcode(POC_MOVWF,popGet(aop,offset));
1572 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1573 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1576 strcmp(s,"r0") == 0 ||
1577 strcmp(s,"r1") == 0 ||
1578 strcmp(s,"r2") == 0 ||
1579 strcmp(s,"r3") == 0 ||
1580 strcmp(s,"r4") == 0 ||
1581 strcmp(s,"r5") == 0 ||
1582 strcmp(s,"r6") == 0 ||
1583 strcmp(s,"r7") == 0 )
1584 pic14_emitcode("mov","%s,%s ; %d",
1585 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1589 if(strcmp(s,"W")==0 )
1590 pic14_emitcode("movf","%s,w ; %d",s,__LINE__);
1592 pic14_emitcode("movwf","%s",
1593 aop->aopu.aop_reg[offset]->name);
1595 if(strcmp(s,zero)==0) {
1596 emitpcode(POC_CLRF,popGet(aop,offset));
1598 } else if(strcmp(s,"W")==0) {
1599 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1600 pcop->type = PO_GPR_REGISTER;
1602 PCOR(pcop)->rIdx = -1;
1603 PCOR(pcop)->r = NULL;
1605 DEBUGpic14_emitcode(";","%d",__LINE__);
1606 pcop->name = Safe_strdup(s);
1607 emitpcode(POC_MOVFW,pcop);
1608 emitpcode(POC_MOVWF,popGet(aop,offset));
1609 } else if(strcmp(s,one)==0) {
1610 emitpcode(POC_CLRF,popGet(aop,offset));
1611 emitpcode(POC_INCF,popGet(aop,offset));
1613 emitpcode(POC_MOVWF,popGet(aop,offset));
1621 if (aop->type == AOP_DPTR2)
1627 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1628 "aopPut writting to code space");
1632 while (offset > aop->coff) {
1634 pic14_emitcode ("inc","dptr");
1637 while (offset < aop->coff) {
1639 pic14_emitcode("lcall","__decdptr");
1644 /* if not in accumulater */
1647 pic14_emitcode ("movx","@dptr,a");
1649 if (aop->type == AOP_DPTR2)
1657 while (offset > aop->coff) {
1659 pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1661 while (offset < aop->coff) {
1663 pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1669 pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1674 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1676 if (strcmp(s,"r0") == 0 ||
1677 strcmp(s,"r1") == 0 ||
1678 strcmp(s,"r2") == 0 ||
1679 strcmp(s,"r3") == 0 ||
1680 strcmp(s,"r4") == 0 ||
1681 strcmp(s,"r5") == 0 ||
1682 strcmp(s,"r6") == 0 ||
1683 strcmp(s,"r7") == 0 ) {
1685 sprintf(buffer,"a%s",s);
1686 pic14_emitcode("mov","@%s,%s",
1687 aop->aopu.aop_ptr->name,buffer);
1689 pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1694 if (strcmp(s,"a") == 0)
1695 pic14_emitcode("push","acc");
1697 pic14_emitcode("push","%s",s);
1702 /* if bit variable */
1703 if (!aop->aopu.aop_dir) {
1704 pic14_emitcode("clr","a");
1705 pic14_emitcode("rlc","a");
1708 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1711 pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1714 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1716 lbl = newiTempLabel(NULL);
1718 if (strcmp(s,"a")) {
1721 pic14_emitcode("clr","c");
1722 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1723 pic14_emitcode("cpl","c");
1724 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1725 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1732 if (strcmp(aop->aopu.aop_str[offset],s))
1733 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1738 if (!offset && (strcmp(s,"acc") == 0))
1741 if (strcmp(aop->aopu.aop_str[offset],s))
1742 pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1746 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1747 "aopPut got unsupported aop->type");
1753 /*-----------------------------------------------------------------*/
1754 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1755 /*-----------------------------------------------------------------*/
1756 static void mov2w_op (operand *op, int offset)
1761 /* for PO_IMMEDIATEs: use address or value? */
1762 if (op_isLitLike (op))
1764 /* access address of op */
1765 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1766 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1768 if (offset == GPTRSIZE-1)
1769 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1771 emitpcode (POC_MOVLW, popGetLit (0));
1774 emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1776 /* access value stored in op */
1777 mov2w (AOP(op), offset);
1782 /*-----------------------------------------------------------------*/
1783 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1784 /*-----------------------------------------------------------------*/
1785 void mov2w (asmop *aop, int offset)
1791 DEBUGpic14_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1793 if ( aop_isLitLike (aop) )
1794 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1796 emitpcode(POC_MOVFW,popGet(aop,offset));
1800 static void movwf (asmop *op, int offset)
1802 emitpcode (POC_MOVWF, popGet(op, offset));
1805 static pCodeOp *get_argument_pcop (int idx)
1807 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1808 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1811 static pCodeOp *get_return_val_pcop (int offset)
1813 assert (offset > 0 && "the most significant byte is returned via WREG");
1814 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1817 static void pass_argument (operand *op, int offset, int idx)
1820 mov2w_op (op, offset);
1822 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1825 static void get_returnvalue (operand *op, int offset, int idx)
1828 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1829 movwf(AOP(op), offset);
1832 static void call_libraryfunc (char *name)
1836 /* library code might reside in different page... */
1837 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1838 /* call the library function */
1839 emitpcode (POC_CALL, popGetExternal (name, 0));
1840 /* might return from different page... */
1841 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1843 /* create symbol, mark it as `extern' */
1844 sym = findSym(SymbolTab, NULL, name);
1846 sym = newSymbol(name, 0);
1847 strncpy(sym->rname, name, SDCC_NAME_MAX);
1848 addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
1849 addSet(&externs, sym);
1855 /*-----------------------------------------------------------------*/
1856 /* reAdjustPreg - points a register back to where it should */
1857 /*-----------------------------------------------------------------*/
1858 static void reAdjustPreg (asmop *aop)
1862 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1864 if ((size = aop->size) <= 1)
1867 switch (aop->type) {
1871 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1875 if (aop->type == AOP_DPTR2)
1881 pic14_emitcode("lcall","__decdptr");
1884 if (aop->type == AOP_DPTR2)
1897 /*-----------------------------------------------------------------*/
1898 /* opIsGptr: returns non-zero if the passed operand is */
1899 /* a generic pointer type. */
1900 /*-----------------------------------------------------------------*/
1901 static int opIsGptr(operand *op)
1903 sym_link *type = operandType(op);
1905 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1906 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1914 /*-----------------------------------------------------------------*/
1915 /* pic14_getDataSize - get the operand data size */
1916 /*-----------------------------------------------------------------*/
1917 int pic14_getDataSize(operand *op)
1921 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1924 size = getSize(OP_SYM_ETYPE(op));
1926 //return AOP_SIZE(op);
1928 // tsd- in the pic port, the genptr size is 1, so this code here
1929 // fails. ( in the 8051 port, the size was 4).
1931 size = AOP_SIZE(op);
1932 if (IS_GENPTR(OP_SYM_TYPE(op)))
1934 sym_link *type = operandType(op);
1935 if (IS_GENPTR(type))
1937 /* generic pointer; arithmetic operations
1938 * should ignore the high byte (pointer type).
1941 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1948 /*-----------------------------------------------------------------*/
1949 /* pic14_outAcc - output Acc */
1950 /*-----------------------------------------------------------------*/
1951 void pic14_outAcc(operand *result)
1954 DEBUGpic14_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
1955 DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1958 size = pic14_getDataSize(result);
1960 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1963 /* unsigned or positive */
1965 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1970 /*-----------------------------------------------------------------*/
1971 /* pic14_outBitC - output a bit C */
1972 /*-----------------------------------------------------------------*/
1973 void pic14_outBitC(operand *result)
1976 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1977 /* if the result is bit */
1978 if (AOP_TYPE(result) == AOP_CRY)
1979 aopPut(AOP(result),"c",0);
1981 pic14_emitcode("clr","a ; %d", __LINE__);
1982 pic14_emitcode("rlc","a");
1983 pic14_outAcc(result);
1987 /*-----------------------------------------------------------------*/
1988 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1989 /*-----------------------------------------------------------------*/
1990 void pic14_toBoolean(operand *oper)
1992 int size = AOP_SIZE(oper);
1995 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2000 /* MOVFW does not load the flags... */
2001 if (AOP_TYPE(oper) == AOP_ACC) {
2002 emitpcode(POC_IORLW, popGetLit(0));
2005 emitpcode(POC_MOVLW, popGetLit(0));
2009 if ( AOP_TYPE(oper) != AOP_ACC) {
2010 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2015 while (offset < size) {
2016 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2018 /* Z is set iff (oper == 0) */
2022 /*-----------------------------------------------------------------*/
2023 /* genNot - generate code for ! operation */
2024 /*-----------------------------------------------------------------*/
2025 static void genNot (iCode *ic)
2032 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2033 /* assign asmOps to operand & result */
2034 aopOp (IC_LEFT(ic),ic,FALSE);
2035 aopOp (IC_RESULT(ic),ic,TRUE);
2037 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2038 /* if in bit space then a special case */
2039 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2040 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2041 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2042 emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2044 emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2045 emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2046 emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2051 size = AOP_SIZE(IC_LEFT(ic));
2052 mov2w (AOP(IC_LEFT(ic)),0);
2055 if (op_isLitLike (IC_LEFT(ic)))
2056 emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2058 emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2060 emitpcode(POC_MOVLW, popGetLit (0));
2062 emitpcode(POC_MOVLW, popGetLit (1));
2063 movwf(AOP(IC_RESULT(ic)), 0);
2065 for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2067 emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2072 /* release the aops */
2073 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2074 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2078 /*-----------------------------------------------------------------*/
2079 /* genCpl - generate code for complement */
2080 /*-----------------------------------------------------------------*/
2081 static void genCpl (iCode *ic)
2083 operand *left, *result;
2088 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2089 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2090 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2092 /* if both are in bit space then
2094 if (AOP_TYPE(result) == AOP_CRY &&
2095 AOP_TYPE(left) == AOP_CRY ) {
2097 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir);
2098 pic14_emitcode("cpl","c");
2099 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir);
2103 size = AOP_SIZE(result);
2104 if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2107 if(AOP_TYPE(left) == AOP_ACC)
2108 emitpcode(POC_XORLW, popGetLit(0xff));
2110 emitpcode(POC_COMFW,popGet(AOP(left),offset));
2112 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2115 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2119 /* release the aops */
2120 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2121 freeAsmop(result,NULL,ic,TRUE);
2124 /*-----------------------------------------------------------------*/
2125 /* genUminusFloat - unary minus for floating points */
2126 /*-----------------------------------------------------------------*/
2127 static void genUminusFloat(operand *op,operand *result)
2129 int size ,offset =0 ;
2134 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2135 /* for this we just need to flip the
2136 first it then copy the rest in place */
2137 size = AOP_SIZE(op) - 1;
2138 l = aopGet(AOP(op),3,FALSE,FALSE);
2142 pic14_emitcode("cpl","acc.7");
2143 aopPut(AOP(result),"a",3);
2147 aopGet(AOP(op),offset,FALSE,FALSE),
2153 /*-----------------------------------------------------------------*/
2154 /* genUminus - unary minus code generation */
2155 /*-----------------------------------------------------------------*/
2156 static void genUminus (iCode *ic)
2159 sym_link *optype, *rtype;
2163 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2165 aopOp(IC_LEFT(ic),ic,FALSE);
2166 aopOp(IC_RESULT(ic),ic,TRUE);
2168 /* if both in bit space then special
2170 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2171 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2173 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
2174 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2175 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
2180 optype = operandType(IC_LEFT(ic));
2181 rtype = operandType(IC_RESULT(ic));
2183 /* if float then do float stuff */
2184 if (IS_FLOAT(optype)) {
2185 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2189 /* otherwise subtract from zero by taking the 2's complement */
2190 size = AOP_SIZE(IC_LEFT(ic));
2192 for(i=0; i<size; i++) {
2193 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2194 emitpcode(POC_COMF, popGet(AOP(IC_LEFT(ic)),i));
2196 emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2197 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2201 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
2202 for(i=1; i<size; i++) {
2204 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),i));
2208 /* release the aops */
2209 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2210 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2213 /*-----------------------------------------------------------------*/
2214 /* saveRegisters - will look for a call and save the registers */
2215 /*-----------------------------------------------------------------*/
2216 static void saveRegisters(iCode *lic)
2225 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2227 for (ic = lic ; ic ; ic = ic->next)
2228 if (ic->op == CALL || ic->op == PCALL)
2232 fprintf(stderr,"found parameter push with no function call\n");
2236 /* if the registers have been saved already then
2238 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2241 /* find the registers in use at this time
2242 and push them away to safety */
2243 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2247 if (options.useXstack) {
2248 if (bitVectBitValue(rsave,R0_IDX))
2249 pic14_emitcode("mov","b,r0");
2250 pic14_emitcode("mov","r0,%s",spname);
2251 for (i = 0 ; i < pic14_nRegs ; i++) {
2252 if (bitVectBitValue(rsave,i)) {
2254 pic14_emitcode("mov","a,b");
2256 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2257 pic14_emitcode("movx","@r0,a");
2258 pic14_emitcode("inc","r0");
2261 pic14_emitcode("mov","%s,r0",spname);
2262 if (bitVectBitValue(rsave,R0_IDX))
2263 pic14_emitcode("mov","r0,b");
2265 //for (i = 0 ; i < pic14_nRegs ; i++) {
2266 // if (bitVectBitValue(rsave,i))
2267 // pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2270 dtype = operandType(IC_LEFT(ic));
2271 if (currFunc && dtype &&
2272 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2273 IFFUNC_ISISR(currFunc->type) &&
2276 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2279 /*-----------------------------------------------------------------*/
2280 /* unsaveRegisters - pop the pushed registers */
2281 /*-----------------------------------------------------------------*/
2282 static void unsaveRegisters (iCode *ic)
2289 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2290 /* find the registers in use at this time
2291 and push them away to safety */
2292 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2295 if (options.useXstack) {
2296 pic14_emitcode("mov","r0,%s",spname);
2297 for (i = pic14_nRegs ; i >= 0 ; i--) {
2298 if (bitVectBitValue(rsave,i)) {
2299 pic14_emitcode("dec","r0");
2300 pic14_emitcode("movx","a,@r0");
2302 pic14_emitcode("mov","b,a");
2304 pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2308 pic14_emitcode("mov","%s,r0",spname);
2309 if (bitVectBitValue(rsave,R0_IDX))
2310 pic14_emitcode("mov","r0,b");
2312 //for (i = pic14_nRegs ; i >= 0 ; i--) {
2313 // if (bitVectBitValue(rsave,i))
2314 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2320 /*-----------------------------------------------------------------*/
2322 /*-----------------------------------------------------------------*/
2323 static void pushSide(operand * oper, int size)
2327 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2329 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2330 if (AOP_TYPE(oper) != AOP_REG &&
2331 AOP_TYPE(oper) != AOP_DIR &&
2333 pic14_emitcode("mov","a,%s",l);
2334 pic14_emitcode("push","acc");
2336 pic14_emitcode("push","%s",l);
2341 /*-----------------------------------------------------------------*/
2342 /* assignResultValue - */
2343 /*-----------------------------------------------------------------*/
2344 static void assignResultValue(operand * oper)
2346 int size = AOP_SIZE(oper);
2351 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2353 DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2355 /* assign MSB first (passed via WREG) */
2357 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2363 /*-----------------------------------------------------------------*/
2364 /* genIpush - genrate code for pushing this gets a little complex */
2365 /*-----------------------------------------------------------------*/
2366 static void genIpush (iCode *ic)
2370 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2372 int size, offset = 0 ;
2376 /* if this is not a parm push : ie. it is spill push
2377 and spill push is always done on the local stack */
2378 if (!ic->parmPush) {
2380 /* and the item is spilt then do nothing */
2381 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2384 aopOp(IC_LEFT(ic),ic,FALSE);
2385 size = AOP_SIZE(IC_LEFT(ic));
2386 /* push it on the stack */
2388 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2393 pic14_emitcode("push","%s",l);
2398 /* this is a paramter push: in this case we call
2399 the routine to find the call and save those
2400 registers that need to be saved */
2403 /* then do the push */
2404 aopOp(IC_LEFT(ic),ic,FALSE);
2407 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2408 size = AOP_SIZE(IC_LEFT(ic));
2411 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2412 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2413 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2415 pic14_emitcode("mov","a,%s",l);
2416 pic14_emitcode("push","acc");
2418 pic14_emitcode("push","%s",l);
2421 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2425 /*-----------------------------------------------------------------*/
2426 /* genIpop - recover the registers: can happen only for spilling */
2427 /*-----------------------------------------------------------------*/
2428 static void genIpop (iCode *ic)
2432 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2433 assert (!"genIpop -- unimplemented");
2438 /* if the temp was not pushed then */
2439 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2442 aopOp(IC_LEFT(ic),ic,FALSE);
2443 size = AOP_SIZE(IC_LEFT(ic));
2446 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2449 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2453 /*-----------------------------------------------------------------*/
2454 /* unsaverbank - restores the resgister bank from stack */
2455 /*-----------------------------------------------------------------*/
2456 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2460 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2466 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2468 if (options.useXstack) {
2470 r = getFreePtr(ic,&aop,FALSE);
2473 pic14_emitcode("mov","%s,_spx",r->name);
2474 pic14_emitcode("movx","a,@%s",r->name);
2475 pic14_emitcode("mov","psw,a");
2476 pic14_emitcode("dec","%s",r->name);
2479 pic14_emitcode ("pop","psw");
2482 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2483 if (options.useXstack) {
2484 pic14_emitcode("movx","a,@%s",r->name);
2485 //pic14_emitcode("mov","(%s+%d),a",
2486 // regspic14[i].base,8*bank+regspic14[i].offset);
2487 pic14_emitcode("dec","%s",r->name);
2490 pic14_emitcode("pop",""); //"(%s+%d)",
2491 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2494 if (options.useXstack) {
2496 pic14_emitcode("mov","_spx,%s",r->name);
2497 freeAsmop(NULL,aop,ic,TRUE);
2503 /*-----------------------------------------------------------------*/
2504 /* saverbank - saves an entire register bank on the stack */
2505 /*-----------------------------------------------------------------*/
2506 static void saverbank (int bank, iCode *ic, bool pushPsw)
2510 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2516 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2517 if (options.useXstack) {
2520 r = getFreePtr(ic,&aop,FALSE);
2521 pic14_emitcode("mov","%s,_spx",r->name);
2525 for (i = 0 ; i < pic14_nRegs ;i++) {
2526 if (options.useXstack) {
2527 pic14_emitcode("inc","%s",r->name);
2528 //pic14_emitcode("mov","a,(%s+%d)",
2529 // regspic14[i].base,8*bank+regspic14[i].offset);
2530 pic14_emitcode("movx","@%s,a",r->name);
2532 pic14_emitcode("push","");// "(%s+%d)",
2533 //regspic14[i].base,8*bank+regspic14[i].offset);
2537 if (options.useXstack) {
2538 pic14_emitcode("mov","a,psw");
2539 pic14_emitcode("movx","@%s,a",r->name);
2540 pic14_emitcode("inc","%s",r->name);
2541 pic14_emitcode("mov","_spx,%s",r->name);
2542 freeAsmop (NULL,aop,ic,TRUE);
2545 pic14_emitcode("push","psw");
2547 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2553 /*-----------------------------------------------------------------*/
2554 /* genCall - generates a call statement */
2555 /*-----------------------------------------------------------------*/
2556 static void genCall (iCode *ic)
2565 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2567 /* if caller saves & we have not saved then */
2571 /* if we are calling a function that is not using
2572 the same register bank then we need to save the
2573 destination registers on the stack */
2574 dtype = operandType(IC_LEFT(ic));
2575 if (currFunc && dtype &&
2576 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2577 IFFUNC_ISISR(currFunc->type) &&
2580 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2582 /* if send set is not empty the assign */
2585 /* For the Pic port, there is no data stack.
2586 * So parameters passed to functions are stored
2587 * in registers. (The pCode optimizer will get
2588 * rid of most of these :).
2590 int psuedoStkPtr=-1;
2591 int firstTimeThruLoop = 1;
2593 _G.sendSet = reverseSet(_G.sendSet);
2595 /* First figure how many parameters are getting passed */
2596 for (sic = setFirstItem(_G.sendSet) ; sic ;
2597 sic = setNextItem(_G.sendSet)) {
2599 aopOp(IC_LEFT(sic),sic,FALSE);
2600 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2601 freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2604 for (sic = setFirstItem(_G.sendSet) ; sic ;
2605 sic = setNextItem(_G.sendSet)) {
2606 int size, offset = 0;
2608 aopOp(IC_LEFT(sic),sic,FALSE);
2609 size = AOP_SIZE(IC_LEFT(sic));
2612 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2613 AopType(AOP_TYPE(IC_LEFT(sic))));
2615 if(!firstTimeThruLoop) {
2616 /* If this is not the first time we've been through the loop
2617 * then we need to save the parameter in a temporary
2618 * register. The last byte of the last parameter is
2620 emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2623 firstTimeThruLoop=0;
2625 mov2w_op (IC_LEFT(sic), offset);
2628 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2633 sym = OP_SYMBOL(IC_LEFT(ic));
2634 name = sym->rname[0] ? sym->rname : sym->name;
2636 * As SDCC emits code as soon as it reaches the end of each
2637 * function's definition, prototyped functions that are implemented
2638 * after the current one are always considered EXTERN, which
2639 * introduces many unneccessary PAGESEL instructions.
2640 * XXX: Use a post pass to iterate over all `CALL _name' statements
2641 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2642 * only iff there is no definition of the function in the whole
2643 * file (might include this in the PAGESEL pass).
2645 isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2647 /* Extern functions and ISRs maybe on a different page;
2648 * must call pagesel */
2649 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2651 emitpcode(POC_CALL,popGetWithString(name,isExtern));
2653 /* May have returned from a different page;
2654 * must use pagesel to restore PCLATH before next
2655 * goto or call instruction */
2656 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2659 /* if we need assign a result value */
2660 if ((IS_ITEMP(IC_RESULT(ic)) &&
2661 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2662 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2663 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2666 aopOp(IC_RESULT(ic),ic,FALSE);
2669 assignResultValue(IC_RESULT(ic));
2671 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2672 AopType(AOP_TYPE(IC_RESULT(ic))));
2674 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2677 /* if register bank was saved then pop them */
2679 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2681 /* if we hade saved some registers then unsave them */
2682 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2683 unsaveRegisters (ic);
2688 /*-----------------------------------------------------------------*/
2689 /* genPcall - generates a call by pointer statement */
2690 /*-----------------------------------------------------------------*/
2691 static void genPcall (iCode *ic)
2694 symbol *albl = newiTempLabel(NULL);
2695 symbol *blbl = newiTempLabel(NULL);
2702 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2703 /* if caller saves & we have not saved then */
2707 /* if we are calling a function that is not using
2708 the same register bank then we need to save the
2709 destination registers on the stack */
2710 dtype = operandType(IC_LEFT(ic));
2711 if (currFunc && dtype &&
2712 IFFUNC_ISISR(currFunc->type) &&
2713 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2714 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2717 aopOp(left,ic,FALSE);
2718 DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2720 poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2722 pushSide(IC_LEFT(ic), FPTRSIZE);
2724 /* if send set is not empty, assign parameters */
2727 DEBUGpic14_emitcode ("; ***","%s %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2728 /* no way to pass args - W always gets used to make the call */
2730 /* first idea - factor out a common helper function and call it.
2731 But don't know how to get it generated only once in its own block
2733 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2736 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2737 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2738 buffer = Safe_calloc(1,strlen(rname)+16);
2739 sprintf(buffer, "%s_goto_helper", rname);
2740 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2744 emitpcode(POC_CALL,popGetLabel(albl->key));
2745 pcop = popGetLabel(blbl->key);
2746 emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2747 emitpcode(POC_GOTO,pcop);
2748 emitpLabel(albl->key);
2750 emitpcode(poc,popGetAddr(AOP(left),1,0));
2751 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2752 emitpcode(poc,popGetAddr(AOP(left),0,0));
2753 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2755 emitpLabel(blbl->key);
2757 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2759 /* if we need to assign a result value */
2760 if ((IS_ITEMP(IC_RESULT(ic)) &&
2761 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2762 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2763 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2766 aopOp(IC_RESULT(ic),ic,FALSE);
2771 assignResultValue(IC_RESULT(ic));
2773 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2776 /* if register bank was saved then unsave them */
2777 if (currFunc && dtype &&
2778 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2779 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2781 /* if we hade saved some registers then
2784 unsaveRegisters (ic);
2788 /*-----------------------------------------------------------------*/
2789 /* resultRemat - result is rematerializable */
2790 /*-----------------------------------------------------------------*/
2791 static int resultRemat (iCode *ic)
2793 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2796 if (SKIP_IC(ic) || ic->op == IFX)
2799 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2800 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2801 if (sym->remat && !POINTER_SET(ic))
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list */
2811 /*-----------------------------------------------------------------*/
2812 static bool inExcludeList(char *s)
2814 DEBUGpic14_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2817 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2818 if (options.excludeRegs[i] &&
2819 STRCASECMP(options.excludeRegs[i],"none") == 0)
2822 for ( i = 0 ; options.excludeRegs[i]; i++) {
2823 if (options.excludeRegs[i] &&
2824 STRCASECMP(s,options.excludeRegs[i]) == 0)
2831 /*-----------------------------------------------------------------*/
2832 /* genFunction - generated code for function entry */
2833 /*-----------------------------------------------------------------*/
2834 static void genFunction (iCode *ic)
2841 DEBUGpic14_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2843 labelOffset += (max_key+4);
2847 /* create the function header */
2848 pic14_emitcode(";","-----------------------------------------");
2849 pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2850 pic14_emitcode(";","-----------------------------------------");
2852 /* prevent this symbol from being emitted as 'extern' */
2853 pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2855 pic14_emitcode("","%s:",sym->rname);
2856 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2858 /* mark symbol as NOT extern (even if it was declared so previously) */
2859 assert(IS_SPEC(sym->etype));
2860 SPEC_EXTR(sym->etype) = 0;
2862 if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
2863 addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
2865 ftype = operandType(IC_LEFT(ic));
2867 /* if critical function then turn interrupts off */
2868 if (IFFUNC_ISCRITICAL(ftype))
2869 pic14_emitcode("clr","ea");
2871 /* here we need to generate the equates for the
2872 register bank if required */
2874 if (FUNC_REGBANK(ftype) != rbank) {
2877 rbank = FUNC_REGBANK(ftype);
2878 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2879 if (strcmp(regspic14[i].base,"0") == 0)
2880 pic14_emitcode("","%s = 0x%02x",
2882 8*rbank+regspic14[i].offset);
2884 pic14_emitcode ("","%s = %s + 0x%02x",
2887 8*rbank+regspic14[i].offset);
2892 /* if this is an interrupt service routine */
2894 if (IFFUNC_ISISR(sym->type)) {
2896 emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
2897 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2898 /* XXX: Why? Does this assume that ssave and psave reside
2899 * in a shared bank or bank0? We cannot guarantee the
2902 emitpcode(POC_CLRF, popCopyReg(&pc_status));
2903 emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
2904 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2905 emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
2906 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2907 emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
2908 emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
2909 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2910 emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
2911 emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
2913 pBlockConvert2ISR(pb);
2914 pic14_hasInterrupt = 1;
2916 /* if callee-save to be used for this function
2917 then save the registers being used in this function */
2918 if (IFFUNC_CALLEESAVES(sym->type)) {
2921 /* if any registers used */
2922 if (sym->regsUsed) {
2923 /* save the registers used */
2924 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2925 if (bitVectBitValue(sym->regsUsed,i) ||
2926 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2927 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2935 /* set the register bank to the desired value */
2936 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2937 pic14_emitcode("push","psw");
2938 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);
2941 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2943 if (options.useXstack) {
2944 pic14_emitcode("mov","r0,%s",spname);
2945 pic14_emitcode("mov","a,_bp");
2946 pic14_emitcode("movx","@r0,a");
2947 pic14_emitcode("inc","%s",spname);
2951 /* set up the stack */
2952 pic14_emitcode ("push","_bp"); /* save the callers stack */
2954 pic14_emitcode ("mov","_bp,%s",spname);
2957 /* adjust the stack for the function */
2962 werror(W_STACK_OVERFLOW,sym->name);
2964 if (i > 3 && sym->recvSize < 4) {
2966 pic14_emitcode ("mov","a,sp");
2967 pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2968 pic14_emitcode ("mov","sp,a");
2973 pic14_emitcode("inc","sp");
2978 pic14_emitcode ("mov","a,_spx");
2979 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2980 pic14_emitcode ("mov","_spx,a");
2985 /*-----------------------------------------------------------------*/
2986 /* genEndFunction - generates epilogue for functions */
2987 /*-----------------------------------------------------------------*/
2988 static void genEndFunction (iCode *ic)
2990 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2994 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2996 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2998 pic14_emitcode ("mov","%s,_bp",spname);
3001 /* if use external stack but some variables were
3002 added to the local stack then decrement the
3004 if (options.useXstack && sym->stack) {
3005 pic14_emitcode("mov","a,sp");
3006 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3007 pic14_emitcode("mov","sp,a");
3011 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3012 if (options.useXstack) {
3013 pic14_emitcode("mov","r0,%s",spname);
3014 pic14_emitcode("movx","a,@r0");
3015 pic14_emitcode("mov","_bp,a");
3016 pic14_emitcode("dec","%s",spname);
3020 pic14_emitcode ("pop","_bp");
3024 /* restore the register bank */
3025 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3026 pic14_emitcode ("pop","psw");
3028 if (IFFUNC_ISISR(sym->type)) {
3030 /* now we need to restore the registers */
3031 /* if this isr has no bank i.e. is going to
3032 run with bank 0 , then we need to save more
3034 if (!FUNC_REGBANK(sym->type)) {
3036 /* if this function does not call any other
3037 function then we can be economical and
3038 save only those registers that are used */
3039 if (! IFFUNC_HASFCALL(sym->type)) {
3042 /* if any registers used */
3043 if (sym->regsUsed) {
3044 /* save the registers used */
3045 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3046 if (bitVectBitValue(sym->regsUsed,i) ||
3047 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3048 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3053 /* this function has a function call cannot
3054 determines register usage so we will have the
3056 unsaverbank(0,ic,FALSE);
3060 /* if debug then send end of function */
3061 if (options.debug && debugFile && currFunc) {
3062 debugFile->writeEndFunction (currFunc, ic, 1);
3065 emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
3066 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
3067 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
3068 emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
3069 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
3070 emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
3071 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
3072 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3073 emitpcode(POC_MOVWF, popCopyReg(&pc_status));
3074 emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
3075 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3076 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3077 emitpcodeNULLop(POC_RETFIE);
3080 if (IFFUNC_ISCRITICAL(sym->type))
3081 pic14_emitcode("setb","ea");
3083 if (IFFUNC_CALLEESAVES(sym->type)) {
3086 /* if any registers used */
3087 if (sym->regsUsed) {
3088 /* save the registers used */
3089 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3090 if (bitVectBitValue(sym->regsUsed,i) ||
3091 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3092 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3098 /* if debug then send end of function */
3099 if (options.debug && debugFile && currFunc) {
3100 debugFile->writeEndFunction (currFunc, ic, 1);
3103 pic14_emitcode ("return","");
3104 emitpcodeNULLop(POC_RETURN);
3106 /* Mark the end of a function */
3107 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3112 /*-----------------------------------------------------------------*/
3113 /* genRet - generate code for return statement */
3114 /*-----------------------------------------------------------------*/
3115 static void genRet (iCode *ic)
3117 int size,offset = 0;
3121 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3122 /* if we have no return value then
3123 just generate the "ret" */
3127 /* we have something to return then
3128 move the return value into place */
3129 aopOp(IC_LEFT(ic),ic,FALSE);
3130 size = AOP_SIZE(IC_LEFT(ic));
3132 for (offset = 0; offset < size; offset++)
3134 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3137 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3140 /* generate a jump to the return label
3141 if the next is not the return statement */
3142 if (!(ic->next && ic->next->op == LABEL &&
3143 IC_LABEL(ic->next) == returnLabel)) {
3145 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3150 /*-----------------------------------------------------------------*/
3151 /* genLabel - generates a label */
3152 /*-----------------------------------------------------------------*/
3153 static void genLabel (iCode *ic)
3157 /* special case never generate */
3158 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3159 if (IC_LABEL(ic) == entryLabel)
3162 emitpLabel(IC_LABEL(ic)->key);
3163 pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3166 /*-----------------------------------------------------------------*/
3167 /* genGoto - generates a goto */
3168 /*-----------------------------------------------------------------*/
3170 static void genGoto (iCode *ic)
3174 emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3175 pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3179 /*-----------------------------------------------------------------*/
3180 /* genMultbits :- multiplication of bits */
3181 /*-----------------------------------------------------------------*/
3182 static void genMultbits (operand *left,
3187 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3189 if(!pic14_sameRegs(AOP(result),AOP(right)))
3190 emitpcode(POC_BSF, popGet(AOP(result),0));
3192 emitpcode(POC_BTFSC,popGet(AOP(right),0));
3193 emitpcode(POC_BTFSS,popGet(AOP(left),0));
3194 emitpcode(POC_BCF, popGet(AOP(result),0));
3199 /*-----------------------------------------------------------------*/
3200 /* genMultOneByte : 8 bit multiplication & division */
3201 /*-----------------------------------------------------------------*/
3202 static void genMultOneByte (operand *left,
3206 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3214 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3215 DEBUGpic14_AopType(__LINE__,left,right,result);
3216 DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3218 /* (if two literals, the value is computed before) */
3219 /* if one literal, literal on the right */
3220 if (AOP_TYPE(left) == AOP_LIT){
3226 assert (AOP_SIZE(left) == AOP_SIZE(right));
3228 size = min(AOP_SIZE(result),AOP_SIZE(left));
3229 offset = Gstack_base_addr - (2*size - 1);
3231 /* pass right operand as argument */
3232 for (i=0; i < size; i++)
3234 mov2w (AOP(right), i);
3235 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3238 /* pass left operand as argument */
3239 for (i=0; i < size; i++)
3241 mov2w (AOP(left), i);
3242 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3244 assert (offset == Gstack_base_addr);
3246 /* call library routine */
3247 assert (size > 0 && size <= 4);
3248 call_libraryfunc (func[size]);
3251 movwf (AOP(result), size-1);
3252 for (i=0; i < size - 1; i++)
3254 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3255 movwf (AOP(result), size - 2 - i);
3258 /* now (zero-/sign) extend the result to its size */
3259 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3262 /*-----------------------------------------------------------------*/
3263 /* genMult - generates code for multiplication */
3264 /*-----------------------------------------------------------------*/
3265 static void genMult (iCode *ic)
3267 operand *left = IC_LEFT(ic);
3268 operand *right = IC_RIGHT(ic);
3269 operand *result= IC_RESULT(ic);
3273 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3274 /* assign the amsops */
3275 aopOp (left,ic,FALSE);
3276 aopOp (right,ic,FALSE);
3277 aopOp (result,ic,TRUE);
3279 DEBUGpic14_AopType(__LINE__,left,right,result);
3281 /* special cases first */
3283 if (AOP_TYPE(left) == AOP_CRY &&
3284 AOP_TYPE(right)== AOP_CRY) {
3285 genMultbits(left,right,result);
3289 /* if both are of size == 1 */
3290 if (AOP_SIZE(left) == 1 &&
3291 AOP_SIZE(right) == 1 ) {
3292 genMultOneByte(left,right,result);
3296 /* should have been converted to function call */
3300 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3301 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3302 freeAsmop(result,NULL,ic,TRUE);
3305 /*-----------------------------------------------------------------*/
3306 /* genDivbits :- division of bits */
3307 /*-----------------------------------------------------------------*/
3308 static void genDivbits (operand *left,
3317 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3318 /* the result must be bit */
3319 pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3320 l = aopGet(AOP(left),0,FALSE,FALSE);
3324 pic14_emitcode("div","ab");
3325 pic14_emitcode("rrc","a");
3326 aopPut(AOP(result),"c",0);
3329 /*-----------------------------------------------------------------*/
3330 /* genDivOneByte : 8 bit division */
3331 /*-----------------------------------------------------------------*/
3332 static void genDivOneByte (operand *left,
3340 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3342 assert (AOP_SIZE(right) == 1);
3343 assert (AOP_SIZE(left) == 1);
3345 size = min(AOP_SIZE(result),AOP_SIZE(left));
3346 sign = !(SPEC_USIGN(operandType(left))
3347 && SPEC_USIGN(operandType(right)));
3349 if (AOP_TYPE(right) == AOP_LIT)
3351 /* XXX: might add specialized code */
3356 /* unsigned division */
3358 mov2w(AOP(right),0);
3359 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3361 call_libraryfunc("__divuchar");
3362 movwf(AOP(result),0);
3367 temp = popGetTempReg();
3368 lbl = newiTempLabel(NULL);
3370 /* XXX: improve this naive approach:
3371 [result] = [a] / [b]
3372 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3376 movwf temp // temp <-- left
3377 movf right,W // W <-- right
3381 subwf temp,F // temp <-- temp - W
3382 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3384 decf result // we just subtract once too often
3387 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3388 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3391 emitpcode(POC_MOVWF, temp);
3392 mov2w(AOP(right),0);
3393 emitpcode(POC_CLRF, popGet(AOP(result),0));
3395 emitpLabel(lbl->key);
3396 emitpcode(POC_INCF, popGet(AOP(result),0));
3397 emitpcode(POC_SUBWF, temp);
3399 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3400 emitpcode(POC_DECF, popGet(AOP(result),0));
3401 popReleaseTempReg(temp);
3406 /* signed division */
3407 mov2w(AOP(right),0);
3408 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3410 call_libraryfunc("__divschar");
3411 movwf(AOP(result),0);
3414 /* now performed the signed/unsigned division -- extend result */
3415 addSign(result, 1, sign);
3418 /*-----------------------------------------------------------------*/
3419 /* genDiv - generates code for division */
3420 /*-----------------------------------------------------------------*/
3421 static void genDiv (iCode *ic)
3423 operand *left = IC_LEFT(ic);
3424 operand *right = IC_RIGHT(ic);
3425 operand *result= IC_RESULT(ic);
3428 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3429 /* assign the amsops */
3430 aopOp (left,ic,FALSE);
3431 aopOp (right,ic,FALSE);
3432 aopOp (result,ic,TRUE);
3434 /* special cases first */
3436 if (AOP_TYPE(left) == AOP_CRY &&
3437 AOP_TYPE(right)== AOP_CRY) {
3438 genDivbits(left,right,result);
3442 /* if both are of size == 1 */
3443 if (AOP_SIZE(left) == 1 &&
3444 AOP_SIZE(right) == 1 ) {
3445 genDivOneByte(left,right,result);
3449 /* should have been converted to function call */
3452 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3453 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3454 freeAsmop(result,NULL,ic,TRUE);
3457 /*-----------------------------------------------------------------*/
3458 /* genModOneByte : 8 bit modulus */
3459 /*-----------------------------------------------------------------*/
3460 static void genModOneByte (operand *left,
3468 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3470 assert (AOP_SIZE(right) == 1);
3471 assert (AOP_SIZE(left) == 1);
3473 size = min(AOP_SIZE(result),AOP_SIZE(left));
3474 sign = !(SPEC_USIGN(operandType(left))
3475 && SPEC_USIGN(operandType(right)));
3477 if (AOP_TYPE(right) == AOP_LIT)
3479 /* XXX: might add specialized code */
3484 /* unsigned division */
3486 mov2w(AOP(right),0);
3487 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3489 call_libraryfunc("__moduchar");
3490 movwf(AOP(result),0);
3495 lbl = newiTempLabel(NULL);
3497 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3499 /* XXX: improve this naive approach:
3500 [result] = [a] % [b]
3501 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3505 movwf result // result <-- left
3506 movf right,W // W <-- right
3508 subwf result,F // result <-- result - W
3509 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3511 addwf result, F // we just subtract once too often
3514 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3515 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3517 if (!pic14_sameRegs(AOP(left), AOP(result)))
3520 emitpcode(POC_MOVWF, popGet(AOP(result),0));
3522 mov2w(AOP(right),0);
3524 emitpLabel(lbl->key);
3525 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3527 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3528 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3533 /* signed division */
3534 mov2w(AOP(right),0);
3535 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3537 call_libraryfunc("__modschar");
3538 movwf(AOP(result),0);
3541 /* now we performed the signed/unsigned modulus -- extend result */
3542 addSign(result, 1, sign);
3545 /*-----------------------------------------------------------------*/
3546 /* genMod - generates code for division */
3547 /*-----------------------------------------------------------------*/
3548 static void genMod (iCode *ic)
3550 operand *left = IC_LEFT(ic);
3551 operand *right = IC_RIGHT(ic);
3552 operand *result= IC_RESULT(ic);
3555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3556 /* assign the amsops */
3557 aopOp (left,ic,FALSE);
3558 aopOp (right,ic,FALSE);
3559 aopOp (result,ic,TRUE);
3561 /* if both are of size == 1 */
3562 if (AOP_SIZE(left) == 1 &&
3563 AOP_SIZE(right) == 1 ) {
3564 genModOneByte(left,right,result);
3568 /* should have been converted to function call */
3572 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3573 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3574 freeAsmop(result,NULL,ic,TRUE);
3577 /*-----------------------------------------------------------------*/
3578 /* genIfxJump :- will create a jump depending on the ifx */
3579 /*-----------------------------------------------------------------*/
3581 note: May need to add parameter to indicate when a variable is in bit space.
3583 static void genIfxJump (iCode *ic, char *jval)
3587 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 /* if true label then we jump if condition
3590 if ( IC_TRUE(ic) ) {
3592 if(strcmp(jval,"a") == 0)
3594 else if (strcmp(jval,"c") == 0)
3597 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3598 emitpcode(POC_BTFSC, newpCodeOpBit(jval,-1,1));
3601 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3602 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3606 /* false label is present */
3607 if(strcmp(jval,"a") == 0)
3609 else if (strcmp(jval,"c") == 0)
3612 DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
3613 emitpcode(POC_BTFSS, newpCodeOpBit(jval,-1,1));
3616 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3617 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3622 /* mark the icode as generated */
3627 /*-----------------------------------------------------------------*/
3629 /*-----------------------------------------------------------------*/
3630 static void genSkip(iCode *ifx,int status_bit)
3636 if ( IC_TRUE(ifx) ) {
3637 switch(status_bit) {
3652 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3653 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3657 switch(status_bit) {
3671 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3672 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3679 /*-----------------------------------------------------------------*/
3681 /*-----------------------------------------------------------------*/
3682 static void genSkipc(resolvedIfx *rifx)
3693 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3694 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3695 rifx->generated = 1;
3699 /*-----------------------------------------------------------------*/
3701 /*-----------------------------------------------------------------*/
3702 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3708 if( (rifx->condition ^ invert_condition) & 1)
3713 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3714 rifx->generated = 1;
3719 /*-----------------------------------------------------------------*/
3721 /*-----------------------------------------------------------------*/
3722 static void genSkipz(iCode *ifx, int condition)
3725 assert (ifx != NULL);
3733 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3735 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3738 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3740 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3746 /*-----------------------------------------------------------------*/
3748 /*-----------------------------------------------------------------*/
3749 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3756 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3758 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3761 emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3762 rifx->generated = 1;
3767 /*-----------------------------------------------------------------*/
3768 /* genChkZeroes :- greater or less than comparison */
3769 /* For each byte in a literal that is zero, inclusive or the */
3770 /* the corresponding byte in the operand with W */
3771 /* returns true if any of the bytes are zero */
3772 /*-----------------------------------------------------------------*/
3773 static int genChkZeroes(operand *op, int lit, int size)
3780 i = (lit >> (size*8)) & 0xff;
3784 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3786 emitpcode(POC_IORFW, popGet(AOP(op),size));
3796 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3797 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3798 #define DEBUGpc emitpComment
3800 /*-----------------------------------------------------------------*/
3801 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3802 /* aop (if it's NOT a literal) or from lit (if */
3803 /* aop is a literal) */
3804 /*-----------------------------------------------------------------*/
3805 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3806 if (aop->type == AOP_LIT) {
3807 emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3809 emitpcode (POC_MOVFW, popGet (aop, offset));
3813 /* genCmp performs a left < right comparison, stores
3814 * the outcome in result (if != NULL) and generates
3815 * control flow code for the ifx (if != NULL).
3817 * This version leaves in sequences like
3818 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3819 * which should be optmized by the peephole
3820 * optimizer - RN 2005-01-01 */
3821 static void genCmp (operand *left,operand *right,
3822 operand *result, iCode *ifx, int sign)
3832 int invert_result = 0;
3836 assert (AOP_SIZE(left) == AOP_SIZE(right));
3837 assert (left && right);
3839 size = AOP_SIZE(right) - 1;
3840 mask = (0x100UL << (size*8)) - 1;
3841 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3846 resolveIfx (&rIfx, ifx);
3848 /**********************************************************************
3849 * handle bits - bit compares are promoted to int compares seemingly! *
3850 **********************************************************************/
3852 // THIS IS COMPLETELY UNTESTED!
3853 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3854 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3855 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3856 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3859 // 1 < {0,1} is false --> clear C by skipping the next instruction
3860 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3861 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3862 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3863 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3864 emitCLRC; // only skipped for left=0 && right=1
3866 goto correct_result_in_carry;
3870 /*************************************************
3871 * make sure that left is register (or the like) *
3872 *************************************************/
3873 if (!isAOP_REGlike(left)) {
3874 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3875 assert (isAOP_LIT(left));
3876 assert (isAOP_REGlike(right));
3877 // swap left and right
3878 // left < right <==> right > left <==> (right >= left + 1)
3879 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3881 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3882 // MAXVALUE < right? always false
3883 if (performedLt) emitCLRC; else emitSETC;
3884 goto correct_result_in_carry;
3887 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3888 // that's why we handled it above.
3895 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3896 } else if (isAOP_LIT(right)) {
3897 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3900 assert (isAOP_REGlike(left)); // left must be register or the like
3901 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3903 /*************************************************
3904 * special cases go here *
3905 *************************************************/
3907 if (isAOP_LIT(right)) {
3909 // unsigned comparison to a literal
3910 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3912 // unsigned left < 0? always false
3913 if (performedLt) emitCLRC; else emitSETC;
3914 goto correct_result_in_carry;
3917 // signed comparison to a literal
3918 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3919 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3920 // signed left < 0x80000000? always false
3921 if (performedLt) emitCLRC; else emitSETC;
3922 goto correct_result_in_carry;
3923 } else if (lit == 0) {
3924 // compare left < 0; set CARRY if SIGNBIT(left) is set
3925 if (performedLt) emitSETC; else emitCLRC;
3926 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3927 if (performedLt) emitCLRC; else emitSETC;
3928 goto correct_result_in_carry;
3931 } // right is literal
3933 /*************************************************
3934 * perform a general case comparison *
3935 * make sure we get CARRY==1 <==> left >= right *
3936 *************************************************/
3937 // compare most significant bytes
3938 //DEBUGpc ("comparing bytes at offset %d", size);
3940 // unsigned comparison
3941 pic14_mov2w_regOrLit (AOP(right), lit, size);
3942 emitpcode (POC_SUBFW, popGet (AOP(left), size));
3944 // signed comparison
3945 // (add 2^n to both operands then perform an unsigned comparison)
3946 if (isAOP_LIT(right)) {
3947 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3948 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3950 if (litbyte == 0x80) {
3951 // left >= 0x80 -- always true, but more bytes to come
3952 mov2w (AOP(left), size);
3953 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3956 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3957 mov2w (AOP(left), size);
3958 emitpcode (POC_ADDLW, popGetLit (0x80));
3959 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3962 pCodeOp *pctemp = popGetTempReg();
3963 mov2w (AOP(left), size);
3964 emitpcode (POC_ADDLW, popGetLit (0x80));
3965 emitpcode (POC_MOVWF, pctemp);
3966 mov2w (AOP(right), size);
3967 emitpcode (POC_ADDLW, popGetLit (0x80));
3968 emitpcode (POC_SUBFW, pctemp);
3969 popReleaseTempReg(pctemp);
3973 // compare remaining bytes (treat as unsigned case from above)
3974 templbl = newiTempLabel ( NULL );
3977 //DEBUGpc ("comparing bytes at offset %d", offs);
3979 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3980 pic14_mov2w_regOrLit (AOP(right), lit, offs);
3981 emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3983 emitpLabel (templbl->key);
3984 goto result_in_carry;
3988 /****************************************************
3989 * now CARRY contains the result of the comparison: *
3990 * SUBWF sets CARRY iff *
3991 * F-W >= 0 <==> F >= W <==> !(F < W) *
3992 * (F=left, W=right) *
3993 ****************************************************/
3997 // value will be used in the following genSkipc()
3998 rIfx.condition ^= 1;
4001 correct_result_in_carry:
4003 // assign result to variable (if neccessary)
4004 if (result && AOP_TYPE(result) != AOP_CRY) {
4005 //DEBUGpc ("assign result");
4006 size = AOP_SIZE(result);
4008 emitpcode (POC_CLRF, popGet (AOP(result), size));
4010 if (invert_result) {
4012 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4014 emitpcode (POC_RLF, popGet (AOP(result), 0));
4018 // perform conditional jump
4020 //DEBUGpc ("generate control flow");
4028 /* OLD VERSION -- BUGGY, DO NOT USE */
4030 /*-----------------------------------------------------------------*/
4031 /* genCmp :- greater or less than comparison */
4032 /*-----------------------------------------------------------------*/
4033 static void genCmp (operand *left,operand *right,
4034 operand *result, iCode *ifx, int sign)
4036 int size; //, offset = 0 ;
4037 unsigned long lit = 0L,i = 0;
4038 resolvedIfx rFalseIfx;
4039 // resolvedIfx rTrueIfx;
4043 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4046 DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4047 DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4051 resolveIfx(&rFalseIfx,ifx);
4052 truelbl = newiTempLabel(NULL);
4053 size = max(AOP_SIZE(left),AOP_SIZE(right));
4055 DEBUGpic14_AopType(__LINE__,left,right,result);
4059 /* if literal is on the right then swap with left */
4060 if ((AOP_TYPE(right) == AOP_LIT)) {
4061 operand *tmp = right ;
4062 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4063 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4066 lit = (lit - 1) & mask;
4069 rFalseIfx.condition ^= 1;
4072 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4073 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4077 //if(IC_TRUE(ifx) == NULL)
4078 /* if left & right are bit variables */
4079 if (AOP_TYPE(left) == AOP_CRY &&
4080 AOP_TYPE(right) == AOP_CRY ) {
4081 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4082 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4084 /* subtract right from left if at the
4085 end the carry flag is set then we know that
4086 left is greater than right */
4088 symbol *lbl = newiTempLabel(NULL);
4091 if(AOP_TYPE(right) == AOP_LIT) {
4093 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4095 DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4102 genSkipCond(&rFalseIfx,left,size-1,7);
4104 /* no need to compare to 0...*/
4105 /* NOTE: this is a de-generate compare that most certainly
4106 * creates some dead code. */
4107 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4109 if(ifx) ifx->generated = 1;
4116 //i = (lit >> (size*8)) & 0xff;
4117 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4119 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4121 i = ((0-lit) & 0xff);
4124 /* lit is 0x7f, all signed chars are less than
4125 * this except for 0x7f itself */
4126 emitpcode(POC_XORLW, popGetLit(0x7f));
4127 genSkipz2(&rFalseIfx,0);
4129 emitpcode(POC_ADDLW, popGetLit(0x80));
4130 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4131 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4136 genSkipz2(&rFalseIfx,1);
4138 emitpcode(POC_ADDLW, popGetLit(i));
4139 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4143 if(ifx) ifx->generated = 1;
4147 /* chars are out of the way. now do ints and longs */
4150 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4157 genSkipCond(&rFalseIfx,left,size,7);
4158 if(ifx) ifx->generated = 1;
4163 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4165 //rFalseIfx.condition ^= 1;
4166 //genSkipCond(&rFalseIfx,left,size,7);
4167 //rFalseIfx.condition ^= 1;
4169 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4170 if(rFalseIfx.condition)
4171 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4173 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4175 emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4176 emitpcode(POC_ADDFW, popGet(AOP(left),0));
4177 emitpcode(POC_MOVFW, popGet(AOP(left),1));
4180 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4182 if(rFalseIfx.condition) {
4184 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4190 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4191 emitpLabel(truelbl->key);
4192 if(ifx) ifx->generated = 1;
4199 if( (lit & 0xff) == 0) {
4200 /* lower byte is zero */
4201 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4202 i = ((lit >> 8) & 0xff) ^0x80;
4203 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4204 emitpcode(POC_ADDLW, popGetLit( 0x80));
4205 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4206 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4209 if(ifx) ifx->generated = 1;
4214 /* Special cases for signed longs */
4215 if( (lit & 0xffffff) == 0) {
4216 /* lower byte is zero */
4217 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4218 i = ((lit >> 8*3) & 0xff) ^0x80;
4219 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4220 emitpcode(POC_ADDLW, popGetLit( 0x80));
4221 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4222 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4225 if(ifx) ifx->generated = 1;
4233 if(lit & (0x80 << (size*8))) {
4234 /* lit is negative */
4235 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4237 //genSkipCond(&rFalseIfx,left,size,7);
4239 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4241 if(rFalseIfx.condition)
4242 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4244 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4248 /* lit is positive */
4249 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4250 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4251 if(rFalseIfx.condition)
4252 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4254 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4258 /* There are no more special cases, so perform a general compare */
4260 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4261 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4265 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4267 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4269 //rFalseIfx.condition ^= 1;
4270 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4272 emitpLabel(truelbl->key);
4274 if(ifx) ifx->generated = 1;
4281 /* sign is out of the way. So now do an unsigned compare */
4282 DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4285 /* General case - compare to an unsigned literal on the right.*/
4287 i = (lit >> (size*8)) & 0xff;
4288 emitpcode(POC_MOVLW, popGetLit(i));
4289 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4291 i = (lit >> (size*8)) & 0xff;
4294 emitpcode(POC_MOVLW, popGetLit(i));
4296 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4298 /* this byte of the lit is zero,
4299 *if it's not the last then OR in the variable */
4301 emitpcode(POC_IORFW, popGet(AOP(left),size));
4306 emitpLabel(lbl->key);
4307 //if(emitFinalCheck)
4308 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4310 emitpLabel(truelbl->key);
4312 if(ifx) ifx->generated = 1;
4319 if(AOP_TYPE(left) == AOP_LIT) {
4320 //symbol *lbl = newiTempLabel(NULL);
4322 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4325 DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4328 if((lit == 0) && (sign == 0)){
4331 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4333 emitpcode(POC_IORFW, popGet(AOP(right),--size));
4335 genSkipz2(&rFalseIfx,0);
4336 if(ifx) ifx->generated = 1;
4343 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4344 /* degenerate compare can never be true */
4345 if(rFalseIfx.condition == 0)
4346 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4348 if(ifx) ifx->generated = 1;
4353 /* signed comparisons to a literal byte */
4355 int lp1 = (lit+1) & 0xff;
4357 DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4360 rFalseIfx.condition ^= 1;
4361 genSkipCond(&rFalseIfx,right,0,7);
4364 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4365 emitpcode(POC_XORLW, popGetLit(0x7f));
4366 genSkipz2(&rFalseIfx,1);
4369 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4370 emitpcode(POC_ADDLW, popGetLit(0x80));
4371 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4372 rFalseIfx.condition ^= 1;
4373 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4376 if(ifx) ifx->generated = 1;
4378 /* unsigned comparisons to a literal byte */
4380 switch(lit & 0xff ) {
4382 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4383 genSkipz2(&rFalseIfx,0);
4384 if(ifx) ifx->generated = 1;
4387 genSkipCond(&rFalseIfx,right,0,7);
4388 if(ifx) ifx->generated = 1;
4392 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4393 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4394 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4395 rFalseIfx.condition ^= 1;
4396 if (AOP_TYPE(result) == AOP_CRY) {
4397 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4398 if(ifx) ifx->generated = 1;
4400 DEBUGpic14_emitcode ("; ***","%s %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4401 emitpcode(POC_CLRF, popGet(AOP(result),0));
4402 emitpcode(POC_RLF, popGet(AOP(result),0));
4403 emitpcode(POC_MOVLW, popGetLit(0x01));
4404 emitpcode(POC_XORWF, popGet(AOP(result),0));
4415 /* Size is greater than 1 */
4423 /* this means lit = 0xffffffff, or -1 */
4426 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4427 rFalseIfx.condition ^= 1;
4428 genSkipCond(&rFalseIfx,right,size,7);
4429 if(ifx) ifx->generated = 1;
4436 if(rFalseIfx.condition) {
4437 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4438 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4441 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4443 emitpcode(POC_IORFW, popGet(AOP(right),size));
4447 if(rFalseIfx.condition) {
4448 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4449 emitpLabel(truelbl->key);
4451 rFalseIfx.condition ^= 1;
4452 genSkipCond(&rFalseIfx,right,s,7);
4455 if(ifx) ifx->generated = 1;
4459 if((size == 1) && (0 == (lp1&0xff))) {
4460 /* lower byte of signed word is zero */
4461 DEBUGpic14_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4462 i = ((lp1 >> 8) & 0xff) ^0x80;
4463 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4464 emitpcode(POC_ADDLW, popGetLit( 0x80));
4465 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4466 rFalseIfx.condition ^= 1;
4467 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4470 if(ifx) ifx->generated = 1;
4474 if(lit & (0x80 << (size*8))) {
4475 /* Lit is less than zero */
4476 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4477 //rFalseIfx.condition ^= 1;
4478 //genSkipCond(&rFalseIfx,left,size,7);
4479 //rFalseIfx.condition ^= 1;
4480 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4481 //emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4483 if(rFalseIfx.condition)
4484 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4486 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4490 /* Lit is greater than or equal to zero */
4491 DEBUGpic14_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4492 //rFalseIfx.condition ^= 1;
4493 //genSkipCond(&rFalseIfx,right,size,7);
4494 //rFalseIfx.condition ^= 1;
4496 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4497 //emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4499 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4500 if(rFalseIfx.condition)
4501 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4503 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4508 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4509 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4513 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4515 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4517 rFalseIfx.condition ^= 1;
4518 //rFalseIfx.condition = 1;
4519 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4521 emitpLabel(truelbl->key);
4523 if(ifx) ifx->generated = 1;
4528 /* compare word or long to an unsigned literal on the right.*/
4533 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4536 break; /* handled above */
4539 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4541 emitpcode(POC_IORFW, popGet(AOP(right),size));
4542 genSkipz2(&rFalseIfx,0);
4546 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4548 emitpcode(POC_IORFW, popGet(AOP(right),size));
4551 if(rFalseIfx.condition)
4552 emitpcode(POC_GOTO, popGetLabel(rFalseIfx.lbl->key));
4554 emitpcode(POC_GOTO, popGetLabel(truelbl->key));
4557 emitpcode(POC_MOVLW, popGetLit(lit+1));
4558 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4560 rFalseIfx.condition ^= 1;
4561 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4564 emitpLabel(truelbl->key);
4566 if(ifx) ifx->generated = 1;
4572 DEBUGpic14_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4573 i = (lit >> (size*8)) & 0xff;
4575 emitpcode(POC_MOVLW, popGetLit(i));
4576 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4579 i = (lit >> (size*8)) & 0xff;
4582 emitpcode(POC_MOVLW, popGetLit(i));
4584 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4586 /* this byte of the lit is zero,
4587 *if it's not the last then OR in the variable */
4589 emitpcode(POC_IORFW, popGet(AOP(right),size));
4594 emitpLabel(lbl->key);
4596 rFalseIfx.condition ^= 1;
4597 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4601 emitpLabel(truelbl->key);
4602 if(ifx) ifx->generated = 1;
4606 /* Compare two variables */
4608 DEBUGpic14_emitcode(";sign","%d",sign);
4612 /* Sigh. thus sucks... */
4614 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4615 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4616 emitpcode(POC_MOVLW, popGetLit(0x80));
4617 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4618 emitpcode(POC_XORFW, popGet(AOP(right),size));
4619 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4621 /* Signed char comparison */
4622 /* Special thanks to Nikolai Golovchenko for this snippet */
4623 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4624 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4625 emitpcode(POC_RRFW, popGet(AOP(left),0)); /* could be any register */
4626 emitpcode(POC_XORFW, popGet(AOP(left),0));
4627 emitpcode(POC_XORFW, popGet(AOP(right),0));
4628 emitpcode(POC_ADDLW, popGetLit(0x80));
4630 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4631 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4633 if(ifx) ifx->generated = 1;
4639 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4640 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4644 /* The rest of the bytes of a multi-byte compare */
4648 emitpcode(POC_GOTO, popGetLabel(lbl->key));
4651 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4652 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4657 emitpLabel(lbl->key);
4659 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4660 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
4661 (AOP_TYPE(result) == AOP_REG)) {
4662 emitpcode(POC_CLRF, popGet(AOP(result),0));
4663 emitpcode(POC_RLF, popGet(AOP(result),0));
4665 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4667 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4668 if(ifx) ifx->generated = 1;
4675 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4676 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4677 pic14_outBitC(result);
4679 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4680 /* if the result is used in the next
4681 ifx conditional branch then generate
4682 code a little differently */
4684 genIfxJump (ifx,"c");
4686 pic14_outBitC(result);
4687 /* leave the result in acc */
4693 /*-----------------------------------------------------------------*/
4694 /* genCmpGt :- greater than comparison */
4695 /*-----------------------------------------------------------------*/
4696 static void genCmpGt (iCode *ic, iCode *ifx)
4698 operand *left, *right, *result;
4699 sym_link *letype , *retype;
4703 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4705 right= IC_RIGHT(ic);
4706 result = IC_RESULT(ic);
4708 letype = getSpec(operandType(left));
4709 retype =getSpec(operandType(right));
4710 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4711 /* assign the amsops */
4712 aopOp (left,ic,FALSE);
4713 aopOp (right,ic,FALSE);
4714 aopOp (result,ic,TRUE);
4716 genCmp(right, left, result, ifx, sign);
4718 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4719 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4720 freeAsmop(result,NULL,ic,TRUE);
4723 /*-----------------------------------------------------------------*/
4724 /* genCmpLt - less than comparisons */
4725 /*-----------------------------------------------------------------*/
4726 static void genCmpLt (iCode *ic, iCode *ifx)
4728 operand *left, *right, *result;
4729 sym_link *letype , *retype;
4733 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4735 right= IC_RIGHT(ic);
4736 result = IC_RESULT(ic);
4738 letype = getSpec(operandType(left));
4739 retype =getSpec(operandType(right));
4740 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4742 /* assign the amsops */
4743 aopOp (left,ic,FALSE);
4744 aopOp (right,ic,FALSE);
4745 aopOp (result,ic,TRUE);
4747 genCmp(left, right, result, ifx, sign);
4749 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4750 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4751 freeAsmop(result,NULL,ic,TRUE);
4755 /*-----------------------------------------------------------------*/
4756 /* genc16bit2lit - compare a 16 bit value to a literal */
4757 /*-----------------------------------------------------------------*/
4758 static void genc16bit2lit(operand *op, int lit, int offset)
4763 DEBUGpic14_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
4764 if( (lit&0xff) == 0)
4769 switch( BYTEofLONG(lit,i)) {
4771 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4774 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4777 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4780 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4781 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4786 switch( BYTEofLONG(lit,i)) {
4788 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4792 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4796 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4799 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4801 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4809 /*-----------------------------------------------------------------*/
4810 /* gencjneshort - compare and jump if not equal */
4811 /*-----------------------------------------------------------------*/
4812 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4814 int size = min(AOP_SIZE(left),AOP_SIZE(right));
4819 //unsigned long lit = 0L;
4821 if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4822 emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4825 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4826 DEBUGpic14_AopType(__LINE__,left,right,result);
4828 assert (!pic14_sameRegs (AOP(left), AOP(result)));
4829 assert (!pic14_sameRegs (AOP(right), AOP(result)));
4830 if (AOP_SIZE(result)) {
4831 for (offset = 0; offset < AOP_SIZE(result); offset++)
4832 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4835 assert (AOP_SIZE(left) == AOP_SIZE(right));
4836 //resolveIfx(&rIfx,ifx);
4837 lbl = newiTempLabel (NULL);
4840 mov2w (AOP(right),size);
4841 emitpcode (POC_XORFW, popGet (AOP(left), size));
4845 emitpcode (POC_GOTO, popGetLabel (lbl->key));
4848 emitpLabel (lbl->key);
4849 if (AOP_SIZE(result)) {
4851 emitpcode (POC_INCF, popGet (AOP(result), 0));
4854 genSkipz (ifx, NULL != IC_TRUE(ifx));
4861 DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
4862 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4863 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4864 for (offset=0; offset < AOP_SIZE(result); offset++)
4866 emitpcode (POC_CLRF, popGet (AOP(result), offset));
4871 /* if the left side is a literal or
4872 if the right is in a pointer register and left
4874 if ((AOP_TYPE(left) == AOP_LIT) ||
4875 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4880 if(AOP_TYPE(right) == AOP_LIT)
4881 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4883 /* if the right side is a literal then anything goes */
4884 if (AOP_TYPE(right) == AOP_LIT &&
4885 AOP_TYPE(left) != AOP_DIR ) {
4888 genc16bit2lit(left, lit, 0);
4890 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4896 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4897 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4899 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4903 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4911 /* if the right side is in a register or in direct space or
4912 if the left is a pointer register & right is not */
4913 else if (AOP_TYPE(right) == AOP_REG ||
4914 AOP_TYPE(right) == AOP_DIR ||
4915 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4916 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4917 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4918 int lbl_key = lbl->key;
4921 DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
4922 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
4923 __FUNCTION__,__LINE__);
4927 /* switch(size) { */
4929 /* genc16bit2lit(left, lit, 0); */
4931 /* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4937 if((AOP_TYPE(left) == AOP_DIR) &&
4938 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4940 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4941 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4943 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4945 switch (lit & 0xff) {
4947 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4950 emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4951 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4952 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4956 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4957 //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4958 //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4959 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4963 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4964 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4969 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4972 if(AOP_TYPE(result) == AOP_CRY) {
4973 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
4978 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4980 /* fix me. probably need to check result size too */
4981 //emitpcode(POC_CLRF,popGet(AOP(result),0));
4986 emitpcode(POC_GOTO,popGetLabel(lbl_key));
4996 } else if(AOP_TYPE(right) == AOP_REG &&
4997 AOP_TYPE(left) != AOP_DIR){
5001 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5002 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5003 pic14_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5008 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5013 /* right is a pointer reg need both a & b */
5016 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5018 pic14_emitcode("mov","b,%s",l);
5019 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5020 pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5025 emitpcode(POC_INCF,popGet(AOP(result),0));
5027 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5029 emitpLabel(lbl->key);
5031 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5040 /*-----------------------------------------------------------------*/
5041 /* gencjne - compare and jump if not equal */
5042 /*-----------------------------------------------------------------*/
5043 static void gencjne(operand *left, operand *right, iCode *ifx)
5045 symbol *tlbl = newiTempLabel(NULL);
5047 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5048 gencjneshort(left, right, lbl);
5050 pic14_emitcode("mov","a,%s",one);
5051 pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5052 pic14_emitcode("","%05d_DS_:",lbl->key+100);
5053 pic14_emitcode("clr","a");
5054 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5056 emitpLabel(lbl->key);
5057 emitpLabel(tlbl->key);
5062 /*-----------------------------------------------------------------*/
5063 /* genCmpEq - generates code for equal to */
5064 /*-----------------------------------------------------------------*/
5065 static void genCmpEq (iCode *ic, iCode *ifx)
5067 operand *left, *right, *result;
5069 symbol *false_label;
5072 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5075 DEBUGpic14_emitcode ("; ifx is non-null","");
5077 DEBUGpic14_emitcode ("; ifx is null","");
5079 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5080 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5081 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5083 DEBUGpic14_AopType(__LINE__,left,right,result);
5085 /* if literal, move literal to right */
5086 if (op_isLitLike (IC_LEFT(ic))) {
5087 operand *tmp = right ;
5093 if (ifx && !IC_TRUE(ifx))
5095 assert (IC_FALSE(ifx));
5096 false_label = IC_FALSE(ifx);
5099 size = min(AOP_SIZE(left),AOP_SIZE(right));
5100 assert(!pic14_sameRegs(AOP(result),AOP(left)));
5101 assert(!pic14_sameRegs(AOP(result),AOP(right)));
5103 /* assume left != right */
5106 for (i=0; i < AOP_SIZE(result); i++)
5108 emitpcode(POC_CLRF, popGet(AOP(result),i));
5112 if (AOP_TYPE(right) == AOP_LIT)
5114 unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5116 size = AOP_SIZE(left);
5117 assert(!op_isLitLike(left));
5122 mov2w(AOP(left), 0);
5123 for (i=1; i < size; i++)
5124 emitpcode(POC_IORFW,popGet(AOP(left),i));
5125 /* now Z is set iff `left == right' */
5127 if (!false_label) false_label = newiTempLabel(NULL);
5128 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5132 for (i=0; i < size; i++)
5135 emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5136 /* now Z is cleared if `left != right' */
5138 if (!false_label) false_label = newiTempLabel(NULL);
5139 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5146 /* right is no literal */
5149 for (i=0; i < size; i++)
5151 mov2w(AOP(right),i);
5152 emitpcode(POC_XORFW,popGet(AOP(left),i));
5153 /* now Z is cleared if `left != right' */
5155 if (!false_label) false_label = newiTempLabel(NULL);
5156 emitpcode(POC_GOTO, popGetLabel(false_label->key));
5160 /* if we reach here, left == right */
5162 if (AOP_SIZE(result) > 0)
5164 emitpcode(POC_INCF, popGet(AOP(result),0));
5167 if (ifx && IC_TRUE(ifx))
5169 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5172 if (false_label && (!ifx || IC_TRUE(ifx)))
5173 emitpLabel(false_label->key);
5175 if (ifx) ifx->generated = 1;
5177 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5178 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5179 freeAsmop(result,NULL,ic,TRUE);
5182 /*-----------------------------------------------------------------*/
5183 /* ifxForOp - returns the icode containing the ifx for operand */
5184 /*-----------------------------------------------------------------*/
5185 static iCode *ifxForOp ( operand *op, iCode *ic )
5188 /* if true symbol then needs to be assigned */
5189 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5190 if (IS_TRUE_SYMOP(op))
5193 /* if this has register type condition and
5194 the next instruction is ifx with the same operand
5195 and live to of the operand is upto the ifx only then */
5197 ic->next->op == IFX &&
5198 IC_COND(ic->next)->key == op->key &&
5199 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5203 ic->next->op == IFX &&
5204 IC_COND(ic->next)->key == op->key) {
5205 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5209 DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5211 ic->next->op == IFX)
5212 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5215 ic->next->op == IFX &&
5216 IC_COND(ic->next)->key == op->key) {
5217 DEBUGpic14_emitcode ("; "," key is okay");
5218 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5219 OP_SYMBOL(op)->liveTo,
5226 /*-----------------------------------------------------------------*/
5227 /* genAndOp - for && operation */
5228 /*-----------------------------------------------------------------*/
5229 static void genAndOp (iCode *ic)
5231 operand *left,*right, *result;
5235 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5236 /* note here that && operations that are in an
5237 if statement are taken away by backPatchLabels
5238 only those used in arthmetic operations remain */
5239 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5240 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5241 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5243 DEBUGpic14_AopType(__LINE__,left,right,result);
5245 emitpcode(POC_MOVFW,popGet(AOP(left),0));
5246 emitpcode(POC_ANDFW,popGet(AOP(right),0));
5247 emitpcode(POC_MOVWF,popGet(AOP(result),0));
5249 /* if both are bit variables */
5250 /* if (AOP_TYPE(left) == AOP_CRY && */
5251 /* AOP_TYPE(right) == AOP_CRY ) { */
5252 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5253 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5254 /* pic14_outBitC(result); */
5256 /* tlbl = newiTempLabel(NULL); */
5257 /* pic14_toBoolean(left); */
5258 /* pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5259 /* pic14_toBoolean(right); */
5260 /* pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5261 /* pic14_outBitAcc(result); */
5264 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5265 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5266 freeAsmop(result,NULL,ic,TRUE);
5270 /*-----------------------------------------------------------------*/
5271 /* genOrOp - for || operation */
5272 /*-----------------------------------------------------------------*/
5275 modified this code, but it doesn't appear to ever get called
5278 static void genOrOp (iCode *ic)
5280 operand *left,*right, *result;
5284 /* note here that || operations that are in an
5285 if statement are taken away by backPatchLabels
5286 only those used in arthmetic operations remain */
5288 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5289 aopOp((left=IC_LEFT(ic)),ic,FALSE);
5290 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5291 aopOp((result=IC_RESULT(ic)),ic,FALSE);
5293 DEBUGpic14_AopType(__LINE__,left,right,result);
5295 for (i=0; i < AOP_SIZE(result); i++)
5297 emitpcode(POC_CLRF, popGet(AOP(result), i));
5300 tlbl = newiTempLabel(NULL);
5301 pic14_toBoolean(left);
5303 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5304 pic14_toBoolean(right);
5305 emitpLabel(tlbl->key);
5306 /* here Z is clear IFF `left || right' */
5308 emitpcode(POC_INCF, popGet(AOP(result), 0));
5310 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5311 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5312 freeAsmop(result,NULL,ic,TRUE);
5315 /*-----------------------------------------------------------------*/
5316 /* isLiteralBit - test if lit == 2^n */
5317 /*-----------------------------------------------------------------*/
5318 static int isLiteralBit(unsigned long lit)
5320 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5321 0x100L,0x200L,0x400L,0x800L,
5322 0x1000L,0x2000L,0x4000L,0x8000L,
5323 0x10000L,0x20000L,0x40000L,0x80000L,
5324 0x100000L,0x200000L,0x400000L,0x800000L,
5325 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5326 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5330 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5331 for(idx = 0; idx < 32; idx++)
5337 /*-----------------------------------------------------------------*/
5338 /* continueIfTrue - */
5339 /*-----------------------------------------------------------------*/
5340 static void continueIfTrue (iCode *ic)
5343 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5347 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5348 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5353 /*-----------------------------------------------------------------*/
5355 /*-----------------------------------------------------------------*/
5356 static void jumpIfTrue (iCode *ic)
5359 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5363 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5364 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5369 /*-----------------------------------------------------------------*/
5370 /* jmpTrueOrFalse - */
5371 /*-----------------------------------------------------------------*/
5372 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5375 // ugly but optimized by peephole
5376 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5378 symbol *nlbl = newiTempLabel(NULL);
5379 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5380 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5381 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5382 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5385 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5386 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5391 /*-----------------------------------------------------------------*/
5392 /* genAnd - code for and */
5393 /*-----------------------------------------------------------------*/
5394 static void genAnd (iCode *ic, iCode *ifx)
5396 operand *left, *right, *result;
5398 unsigned long lit = 0L;
5403 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5404 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5405 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5406 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5408 resolveIfx(&rIfx,ifx);
5410 /* if left is a literal & right is not then exchange them */
5411 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5412 AOP_NEEDSACC(left)) {
5413 operand *tmp = right ;
5418 /* if result = right then exchange them */
5419 if(pic14_sameRegs(AOP(result),AOP(right))){
5420 operand *tmp = right ;
5425 /* if right is bit then exchange them */
5426 if (AOP_TYPE(right) == AOP_CRY &&
5427 AOP_TYPE(left) != AOP_CRY){
5428 operand *tmp = right ;
5432 if(AOP_TYPE(right) == AOP_LIT)
5433 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5435 size = AOP_SIZE(result);
5437 DEBUGpic14_AopType(__LINE__,left,right,result);
5440 // result = bit & yy;
5441 if (AOP_TYPE(left) == AOP_CRY){
5442 // c = bit & literal;
5443 if(AOP_TYPE(right) == AOP_LIT){
5445 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5448 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5451 if(size && (AOP_TYPE(result) == AOP_CRY)){
5452 pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5455 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5459 pic14_emitcode("clr","c");
5462 if (AOP_TYPE(right) == AOP_CRY){
5464 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5465 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5468 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5470 pic14_emitcode("rrc","a");
5471 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5477 pic14_outBitC(result);
5479 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5480 genIfxJump(ifx, "c");
5484 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5485 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5486 if((AOP_TYPE(right) == AOP_LIT) &&
5487 (AOP_TYPE(result) == AOP_CRY) &&
5488 (AOP_TYPE(left) != AOP_CRY)){
5489 int posbit = isLiteralBit(lit);
5493 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5496 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5501 while (posbit > 7) {
5505 emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5506 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5507 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5514 symbol *tlbl = newiTempLabel(NULL);
5515 int sizel = AOP_SIZE(left);
5517 pic14_emitcode("setb","c");
5519 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5520 mov2w( AOP(left), offset);
5522 if((posbit = isLiteralBit(bytelit)) != 0) {
5523 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5524 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5525 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5528 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5529 if (rIfx.condition) emitSKPZ;
5532 if(bytelit != 0x0FFL)
5534 pic14_emitcode("anl","a,%s",
5535 aopGet(AOP(right),offset,FALSE,TRUE));
5537 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5540 emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5546 // bit = left & literal
5548 pic14_emitcode("clr","c");
5549 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5551 // if(left & literal)
5554 jmpTrueOrFalse(ifx, tlbl);
5558 pic14_outBitC(result);
5562 /* if left is same as result */
5563 if(pic14_sameRegs(AOP(result),AOP(left))){
5565 for(;size--; offset++,lit>>=8) {
5566 if(AOP_TYPE(right) == AOP_LIT){
5567 switch(lit & 0xff) {
5569 /* and'ing with 0 has clears the result */
5570 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5573 /* and'ing with 0xff is a nop when the result and left are the same */
5578 int p = my_powof2( (~lit) & 0xff );
5580 /* only one bit is set in the literal, so use a bcf instruction */
5581 emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5584 if(know_W != (int)(lit&0xff))
5585 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5587 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5592 if (AOP_TYPE(left) == AOP_ACC) {
5593 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5595 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5596 emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5603 // left & result in different registers
5604 if(AOP_TYPE(result) == AOP_CRY){
5606 // if(size), result in bit
5607 // if(!size && ifx), conditional oper: if(left & right)
5608 symbol *tlbl = newiTempLabel(NULL);
5609 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5611 pic14_emitcode("setb","c");
5613 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5614 pic14_emitcode("anl","a,%s",
5615 aopGet(AOP(left),offset,FALSE,FALSE));
5616 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5621 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5622 pic14_outBitC(result);
5624 jmpTrueOrFalse(ifx, tlbl);
5626 for(;(size--);offset++) {
5628 // result = left & right
5629 if(AOP_TYPE(right) == AOP_LIT){
5630 int t = (lit >> (offset*8)) & 0x0FFL;
5633 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5636 if(AOP_TYPE(left) != AOP_ACC) {
5637 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5639 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5642 if(AOP_TYPE(left) == AOP_ACC) {
5643 emitpcode(POC_ANDLW, popGetLit(t));
5645 emitpcode(POC_MOVLW, popGetLit(t));
5646 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5648 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5653 if (AOP_TYPE(left) == AOP_ACC) {
5654 emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5656 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5657 emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5659 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5665 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5666 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5667 freeAsmop(result,NULL,ic,TRUE);
5670 /*-----------------------------------------------------------------*/
5671 /* genOr - code for or */
5672 /*-----------------------------------------------------------------*/
5673 static void genOr (iCode *ic, iCode *ifx)
5675 operand *left, *right, *result;
5677 unsigned long lit = 0L;
5680 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5682 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5683 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5684 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5686 DEBUGpic14_AopType(__LINE__,left,right,result);
5688 /* if left is a literal & right is not then exchange them */
5689 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5690 AOP_NEEDSACC(left)) {
5691 operand *tmp = right ;
5696 /* if result = right then exchange them */
5697 if(pic14_sameRegs(AOP(result),AOP(right))){
5698 operand *tmp = right ;
5703 /* if right is bit then exchange them */
5704 if (AOP_TYPE(right) == AOP_CRY &&
5705 AOP_TYPE(left) != AOP_CRY){
5706 operand *tmp = right ;
5711 DEBUGpic14_AopType(__LINE__,left,right,result);
5713 if(AOP_TYPE(right) == AOP_LIT)
5714 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5716 size = AOP_SIZE(result);
5720 if (AOP_TYPE(left) == AOP_CRY){
5721 if(AOP_TYPE(right) == AOP_LIT){
5722 // c = bit & literal;
5724 // lit != 0 => result = 1
5725 if(AOP_TYPE(result) == AOP_CRY){
5727 emitpcode(POC_BSF, popGet(AOP(result),0));
5728 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5729 // AOP(result)->aopu.aop_dir,
5730 // AOP(result)->aopu.aop_dir);
5732 continueIfTrue(ifx);
5736 // lit == 0 => result = left
5737 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5739 pic14_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5742 if (AOP_TYPE(right) == AOP_CRY){
5743 if(pic14_sameRegs(AOP(result),AOP(left))){
5745 emitpcode(POC_BCF, popGet(AOP(result),0));
5746 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5747 emitpcode(POC_BSF, popGet(AOP(result),0));
5749 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5750 AOP(result)->aopu.aop_dir,
5751 AOP(result)->aopu.aop_dir);
5752 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5753 AOP(right)->aopu.aop_dir,
5754 AOP(right)->aopu.aop_dir);
5755 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5756 AOP(result)->aopu.aop_dir,
5757 AOP(result)->aopu.aop_dir);
5759 if( AOP_TYPE(result) == AOP_ACC) {
5760 emitpcode(POC_MOVLW, popGetLit(0));
5761 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5762 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5763 emitpcode(POC_MOVLW, popGetLit(1));
5767 emitpcode(POC_BCF, popGet(AOP(result),0));
5768 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5769 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5770 emitpcode(POC_BSF, popGet(AOP(result),0));
5772 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5773 AOP(result)->aopu.aop_dir,
5774 AOP(result)->aopu.aop_dir);
5775 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5776 AOP(right)->aopu.aop_dir,
5777 AOP(right)->aopu.aop_dir);
5778 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5779 AOP(left)->aopu.aop_dir,
5780 AOP(left)->aopu.aop_dir);
5781 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5782 AOP(result)->aopu.aop_dir,
5783 AOP(result)->aopu.aop_dir);
5788 symbol *tlbl = newiTempLabel(NULL);
5789 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5792 emitpcode(POC_BCF, popGet(AOP(result),0));
5793 if( AOP_TYPE(right) == AOP_ACC) {
5794 emitpcode(POC_IORLW, popGetLit(0));
5796 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5797 emitpcode(POC_BSF, popGet(AOP(result),0));
5802 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5803 pic14_emitcode(";XXX setb","c");
5804 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5805 AOP(left)->aopu.aop_dir,tlbl->key+100);
5806 pic14_toBoolean(right);
5807 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5808 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5809 jmpTrueOrFalse(ifx, tlbl);
5813 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5820 pic14_outBitC(result);
5822 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5823 genIfxJump(ifx, "c");
5827 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5828 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5829 if((AOP_TYPE(right) == AOP_LIT) &&
5830 (AOP_TYPE(result) == AOP_CRY) &&
5831 (AOP_TYPE(left) != AOP_CRY)){
5833 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5836 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5838 continueIfTrue(ifx);
5841 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5842 // lit = 0, result = boolean(left)
5844 pic14_emitcode(";XXX setb","c");
5845 pic14_toBoolean(right);
5847 symbol *tlbl = newiTempLabel(NULL);
5848 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5850 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5852 genIfxJump (ifx,"a");
5856 pic14_outBitC(result);
5860 /* if left is same as result */
5861 if(pic14_sameRegs(AOP(result),AOP(left))){
5863 for(;size--; offset++,lit>>=8) {
5864 if(AOP_TYPE(right) == AOP_LIT){
5865 if((lit & 0xff) == 0)
5866 /* or'ing with 0 has no effect */
5869 int p = my_powof2(lit & 0xff);
5871 /* only one bit is set in the literal, so use a bsf instruction */
5873 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5875 if(know_W != (int)(lit & 0xff))
5876 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5877 know_W = lit & 0xff;
5878 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5883 if (AOP_TYPE(left) == AOP_ACC) {
5884 emitpcode(POC_IORFW, popGet(AOP(right),offset));
5885 pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5887 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
5888 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5890 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5891 pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5897 // left & result in different registers
5898 if(AOP_TYPE(result) == AOP_CRY){
5900 // if(size), result in bit
5901 // if(!size && ifx), conditional oper: if(left | right)
5902 symbol *tlbl = newiTempLabel(NULL);
5903 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5904 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5908 pic14_emitcode(";XXX setb","c");
5910 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5911 pic14_emitcode(";XXX orl","a,%s",
5912 aopGet(AOP(left),offset,FALSE,FALSE));
5913 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5918 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5919 pic14_outBitC(result);
5921 jmpTrueOrFalse(ifx, tlbl);
5922 } else for(;(size--);offset++){
5924 // result = left | right
5925 if(AOP_TYPE(right) == AOP_LIT){
5926 int t = (lit >> (offset*8)) & 0x0FFL;
5929 if (AOP_TYPE(left) != AOP_ACC) {
5930 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
5932 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5936 if (AOP_TYPE(left) == AOP_ACC) {
5937 emitpcode(POC_IORLW, popGetLit(t));
5939 emitpcode(POC_MOVLW, popGetLit(t));
5940 emitpcode(POC_IORFW, popGet(AOP(left),offset));
5942 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5947 // faster than result <- left, anl result,right
5948 // and better if result is SFR
5949 if (AOP_TYPE(left) == AOP_ACC) {
5950 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5952 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5953 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5955 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5960 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5961 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5962 freeAsmop(result,NULL,ic,TRUE);
5965 /*-----------------------------------------------------------------*/
5966 /* genXor - code for xclusive or */
5967 /*-----------------------------------------------------------------*/
5968 static void genXor (iCode *ic, iCode *ifx)
5970 operand *left, *right, *result;
5972 unsigned long lit = 0L;
5975 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5977 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5978 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5979 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5981 /* if left is a literal & right is not ||
5982 if left needs acc & right does not */
5983 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5984 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5985 operand *tmp = right ;
5990 /* if result = right then exchange them */
5991 if(pic14_sameRegs(AOP(result),AOP(right))){
5992 operand *tmp = right ;
5997 /* if right is bit then exchange them */
5998 if (AOP_TYPE(right) == AOP_CRY &&
5999 AOP_TYPE(left) != AOP_CRY){
6000 operand *tmp = right ;
6004 if(AOP_TYPE(right) == AOP_LIT)
6005 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6007 size = AOP_SIZE(result);
6011 if (AOP_TYPE(left) == AOP_CRY){
6012 if(AOP_TYPE(right) == AOP_LIT){
6013 // c = bit & literal;
6015 // lit>>1 != 0 => result = 1
6016 if(AOP_TYPE(result) == AOP_CRY){
6018 {emitpcode(POC_BSF, popGet(AOP(result),offset));
6019 pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6021 continueIfTrue(ifx);
6024 pic14_emitcode("setb","c");
6028 // lit == 0, result = left
6029 if(size && pic14_sameRegs(AOP(result),AOP(left)))
6031 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6033 // lit == 1, result = not(left)
6034 if(size && pic14_sameRegs(AOP(result),AOP(left))){
6035 emitpcode(POC_MOVLW, popGet(AOP(result),offset));
6036 emitpcode(POC_XORWF, popGet(AOP(result),offset));
6037 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6040 assert ( !"incomplete genXor" );
6041 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6042 pic14_emitcode("cpl","c");
6049 symbol *tlbl = newiTempLabel(NULL);
6050 if (AOP_TYPE(right) == AOP_CRY){
6052 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6055 int sizer = AOP_SIZE(right);
6057 // if val>>1 != 0, result = 1
6058 pic14_emitcode("setb","c");
6060 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6062 // test the msb of the lsb
6063 pic14_emitcode("anl","a,#0xfe");
6064 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6068 pic14_emitcode("rrc","a");
6070 pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6071 pic14_emitcode("cpl","c");
6072 pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6077 pic14_outBitC(result);
6079 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6080 genIfxJump(ifx, "c");
6084 if(pic14_sameRegs(AOP(result),AOP(left))){
6085 /* if left is same as result */
6086 for(;size--; offset++) {
6087 if(AOP_TYPE(right) == AOP_LIT){
6088 int t = (lit >> (offset*8)) & 0x0FFL;
6092 if (IS_AOP_PREG(left)) {
6093 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6094 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6095 aopPut(AOP(result),"a",offset);
6097 emitpcode(POC_MOVLW, popGetLit(t));
6098 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6099 pic14_emitcode("xrl","%s,%s",
6100 aopGet(AOP(left),offset,FALSE,TRUE),
6101 aopGet(AOP(right),offset,FALSE,FALSE));
6104 if (AOP_TYPE(left) == AOP_ACC)
6105 pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6107 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6108 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6110 if (IS_AOP_PREG(left)) {
6111 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6112 aopPut(AOP(result),"a",offset);
6114 pic14_emitcode("xrl","%s,a",
6115 aopGet(AOP(left),offset,FALSE,TRUE));
6121 // left & result in different registers
6122 if(AOP_TYPE(result) == AOP_CRY){
6124 // if(size), result in bit
6125 // if(!size && ifx), conditional oper: if(left ^ right)
6126 symbol *tlbl = newiTempLabel(NULL);
6127 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6129 pic14_emitcode("setb","c");
6131 if((AOP_TYPE(right) == AOP_LIT) &&
6132 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6133 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6135 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6136 pic14_emitcode("xrl","a,%s",
6137 aopGet(AOP(left),offset,FALSE,FALSE));
6139 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6144 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6145 pic14_outBitC(result);
6147 jmpTrueOrFalse(ifx, tlbl);
6148 } else for(;(size--);offset++){
6150 // result = left & right
6151 if(AOP_TYPE(right) == AOP_LIT){
6152 int t = (lit >> (offset*8)) & 0x0FFL;
6155 if (AOP_TYPE(left) != AOP_ACC) {
6156 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6158 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6159 pic14_emitcode("movf","%s,w",
6160 aopGet(AOP(left),offset,FALSE,FALSE));
6161 pic14_emitcode("movwf","%s",
6162 aopGet(AOP(result),offset,FALSE,FALSE));
6165 if (AOP_TYPE(left) == AOP_ACC) {
6166 emitpcode(POC_XORLW, popGetLit(t));
6168 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6170 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6173 if (AOP_TYPE(left) == AOP_ACC) {
6174 emitpcode(POC_XORLW, popGetLit(t));
6176 emitpcode(POC_MOVLW, popGetLit(t));
6177 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6179 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6180 pic14_emitcode("movlw","0x%x",t);
6181 pic14_emitcode("xorwf","%s,w",
6182 aopGet(AOP(left),offset,FALSE,FALSE));
6183 pic14_emitcode("movwf","%s",
6184 aopGet(AOP(result),offset,FALSE,FALSE));
6190 // faster than result <- left, anl result,right
6191 // and better if result is SFR
6192 if (AOP_TYPE(left) == AOP_ACC) {
6193 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6195 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6196 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6198 if ( AOP_TYPE(result) != AOP_ACC){
6199 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6205 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6206 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6207 freeAsmop(result,NULL,ic,TRUE);
6210 /*-----------------------------------------------------------------*/
6211 /* genInline - write the inline code out */
6212 /*-----------------------------------------------------------------*/
6213 static void genInline (iCode *ic)
6215 char *buffer, *bp, *bp1;
6216 bool inComment = FALSE;
6219 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6221 _G.inLine += (!options.asmpeep);
6223 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6238 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6243 /* Add \n for labels, not dirs such as c:\mydir */
6244 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6249 /* print label, use this special format with NULL directive
6250 * to denote that the argument should not be indented with tab */
6251 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6259 if ((bp1 != bp) && *bp1)
6260 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6264 _G.inLine -= (!options.asmpeep);
6267 /*-----------------------------------------------------------------*/
6268 /* genRRC - rotate right with carry */
6269 /*-----------------------------------------------------------------*/
6270 static void genRRC (iCode *ic)
6272 operand *left , *result ;
6273 int size, offset = 0, same;
6276 /* rotate right with carry */
6278 result=IC_RESULT(ic);
6279 aopOp (left,ic,FALSE);
6280 aopOp (result,ic,FALSE);
6282 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6284 same = pic14_sameRegs(AOP(result),AOP(left));
6286 size = AOP_SIZE(result);
6288 /* get the lsb and put it into the carry */
6289 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6296 emitpcode(POC_RRF, popGet(AOP(left),offset));
6298 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6299 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6305 freeAsmop(left,NULL,ic,TRUE);
6306 freeAsmop(result,NULL,ic,TRUE);
6309 /*-----------------------------------------------------------------*/
6310 /* genRLC - generate code for rotate left with carry */
6311 /*-----------------------------------------------------------------*/
6312 static void genRLC (iCode *ic)
6314 operand *left , *result ;
6315 int size, offset = 0;
6319 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6320 /* rotate right with carry */
6322 result=IC_RESULT(ic);
6323 aopOp (left,ic,FALSE);
6324 aopOp (result,ic,FALSE);
6326 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6328 same = pic14_sameRegs(AOP(result),AOP(left));
6330 /* move it to the result */
6331 size = AOP_SIZE(result);
6333 /* get the msb and put it into the carry */
6334 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6341 emitpcode(POC_RLF, popGet(AOP(left),offset));
6343 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6344 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6351 freeAsmop(left,NULL,ic,TRUE);
6352 freeAsmop(result,NULL,ic,TRUE);
6355 /*-----------------------------------------------------------------*/
6356 /* genGetHbit - generates code get highest order bit */
6357 /*-----------------------------------------------------------------*/
6358 static void genGetHbit (iCode *ic)
6360 operand *left, *result;
6362 result=IC_RESULT(ic);
6363 aopOp (left,ic,FALSE);
6364 aopOp (result,ic,FALSE);
6367 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6368 /* get the highest order byte into a */
6369 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6370 if(AOP_TYPE(result) == AOP_CRY){
6371 pic14_emitcode("rlc","a");
6372 pic14_outBitC(result);
6375 pic14_emitcode("rl","a");
6376 pic14_emitcode("anl","a,#0x01");
6377 pic14_outAcc(result);
6381 freeAsmop(left,NULL,ic,TRUE);
6382 freeAsmop(result,NULL,ic,TRUE);
6385 /*-----------------------------------------------------------------*/
6386 /* AccLsh - shift left accumulator by known count */
6387 /* MARK: pic14 always rotates through CARRY! */
6388 /*-----------------------------------------------------------------*/
6389 static void AccLsh (pCodeOp *pcop,int shCount)
6392 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6393 shCount &= 0x0007; // shCount : 0..7
6400 emitpcode(POC_RLF,pcop);
6404 emitpcode(POC_RLF,pcop);
6405 emitpcode(POC_RLF,pcop);
6408 emitpcode(POC_RLF,pcop);
6409 emitpcode(POC_RLF,pcop);
6410 emitpcode(POC_RLF,pcop);
6413 emitpcode(POC_SWAPF,pcop);
6416 emitpcode(POC_SWAPF,pcop);
6417 emitpcode(POC_RLF,pcop);
6420 emitpcode(POC_SWAPF,pcop);
6421 emitpcode(POC_RLF,pcop);
6422 emitpcode(POC_RLF,pcop);
6425 emitpcode(POC_RRFW,pcop);
6426 emitpcode(POC_RRF,pcop);
6429 /* clear invalid bits */
6430 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6431 emitpcode(POC_ANDWF, pcop);
6434 /*-----------------------------------------------------------------*/
6435 /* AccRsh - shift right accumulator by known count */
6436 /* MARK: pic14 always rotates through CARRY! */
6437 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6438 /* 1: mask out invalid bits (zero-extend) */
6439 /* 2: sign-extend result (pretty slow) */
6440 /*-----------------------------------------------------------------*/
6441 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6444 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6445 shCount &= 0x0007; // shCount : 0..7
6451 /* load sign if needed */
6452 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6453 else if (mask_mode == 1) emitCLRC;
6454 emitpcode(POC_RRF,pcop);
6458 /* load sign if needed */
6459 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6460 emitpcode(POC_RRF,pcop);
6461 /* load sign if needed */
6462 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6463 emitpcode(POC_RRF,pcop);
6464 if (mask_mode == 2) return;
6467 /* load sign if needed */
6468 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6469 emitpcode(POC_RRF,pcop);
6470 /* load sign if needed */
6471 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6472 emitpcode(POC_RRF,pcop);
6473 /* load sign if needed */
6474 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6475 emitpcode(POC_RRF,pcop);
6476 if (mask_mode == 2) return;
6479 emitpcode(POC_SWAPF,pcop);
6482 emitpcode(POC_SWAPF,pcop);
6483 emitpcode(POC_RRF,pcop);
6486 emitpcode(POC_SWAPF,pcop);
6487 emitpcode(POC_RRF,pcop);
6488 emitpcode(POC_RRF,pcop);
6494 emitpcode(POC_RLFW,pcop);
6495 emitpcode(POC_CLRF,pcop);
6497 emitpcode(POC_COMF,pcop);
6500 emitpcode(POC_RLFW,pcop);
6501 emitpcode(POC_RLF,pcop);
6508 /* leave invalid bits undefined */
6512 /* clear invalid bits -- zero-extend */
6513 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6514 emitpcode(POC_ANDWF, pcop);
6516 if (mask_mode == 2) {
6518 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6519 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6520 emitpcode(POC_IORWF, pcop);
6525 /*-----------------------------------------------------------------*/
6526 /* AccSRsh - signed right shift accumulator by known count */
6527 /*-----------------------------------------------------------------*/
6528 static void AccSRsh (int shCount)
6531 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6534 pic14_emitcode("mov","c,acc.7");
6535 pic14_emitcode("rrc","a");
6536 } else if(shCount == 2){
6537 pic14_emitcode("mov","c,acc.7");
6538 pic14_emitcode("rrc","a");
6539 pic14_emitcode("mov","c,acc.7");
6540 pic14_emitcode("rrc","a");
6542 tlbl = newiTempLabel(NULL);
6543 /* rotate right accumulator */
6544 AccRol(8 - shCount);
6545 /* and kill the higher order bits */
6546 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6547 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6548 pic14_emitcode("orl","a,#0x%02x",
6549 (unsigned char)~SRMask[shCount]);
6550 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6555 /*-----------------------------------------------------------------*/
6556 /* shiftR1Left2Result - shift right one byte from left to result */
6557 /*-----------------------------------------------------------------*/
6558 static void shiftR1Left2ResultSigned (operand *left, int offl,
6559 operand *result, int offr,
6565 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6567 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6571 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6573 emitpcode(POC_RRF, popGet(AOP(result),offr));
6575 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6576 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6582 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6584 emitpcode(POC_RRF, popGet(AOP(result),offr));
6586 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6587 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6589 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6590 emitpcode(POC_RRF, popGet(AOP(result),offr));
6596 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6598 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6599 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6602 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6603 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6604 emitpcode(POC_ANDLW, popGetLit(0x1f));
6606 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6607 emitpcode(POC_IORLW, popGetLit(0xe0));
6609 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6613 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6614 emitpcode(POC_ANDLW, popGetLit(0x0f));
6615 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6616 emitpcode(POC_IORLW, popGetLit(0xf0));
6617 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6621 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6623 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6624 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6626 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6627 emitpcode(POC_ANDLW, popGetLit(0x07));
6628 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6629 emitpcode(POC_IORLW, popGetLit(0xf8));
6630 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6635 emitpcode(POC_MOVLW, popGetLit(0x00));
6636 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6637 emitpcode(POC_MOVLW, popGetLit(0xfe));
6638 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6639 emitpcode(POC_IORLW, popGetLit(0x01));
6640 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6642 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6643 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6644 emitpcode(POC_DECF, popGet(AOP(result),offr));
6645 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6646 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6652 emitpcode(POC_MOVLW, popGetLit(0x00));
6653 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6654 emitpcode(POC_MOVLW, popGetLit(0xff));
6655 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6657 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6658 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6659 emitpcode(POC_DECF, popGet(AOP(result),offr));
6667 /*-----------------------------------------------------------------*/
6668 /* shiftR1Left2Result - shift right one byte from left to result */
6669 /*-----------------------------------------------------------------*/
6670 static void shiftR1Left2Result (operand *left, int offl,
6671 operand *result, int offr,
6672 int shCount, int sign)
6677 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6679 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6681 /* Copy the msb into the carry if signed. */
6683 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6693 emitpcode(POC_RRF, popGet(AOP(result),offr));
6695 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6696 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6702 emitpcode(POC_RRF, popGet(AOP(result),offr));
6704 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6705 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6708 emitpcode(POC_RRF, popGet(AOP(result),offr));
6713 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6715 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6716 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6719 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6720 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6721 emitpcode(POC_ANDLW, popGetLit(0x1f));
6722 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6727 emitpcode(POC_ANDLW, popGetLit(0x0f));
6728 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6732 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6733 emitpcode(POC_ANDLW, popGetLit(0x0f));
6734 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6736 emitpcode(POC_RRF, popGet(AOP(result),offr));
6741 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6742 emitpcode(POC_ANDLW, popGetLit(0x80));
6743 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744 emitpcode(POC_RLF, popGet(AOP(result),offr));
6745 emitpcode(POC_RLF, popGet(AOP(result),offr));
6750 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6751 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6752 emitpcode(POC_RLF, popGet(AOP(result),offr));
6761 /*-----------------------------------------------------------------*/
6762 /* shiftL1Left2Result - shift left one byte from left to result */
6763 /*-----------------------------------------------------------------*/
6764 static void shiftL1Left2Result (operand *left, int offl,
6765 operand *result, int offr, int shCount)
6771 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6773 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6774 DEBUGpic14_emitcode ("; ***","same = %d",same);
6775 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6777 /* shift left accumulator */
6778 //AccLsh(shCount); // don't comment out just yet...
6779 // aopPut(AOP(result),"a",offr);
6783 /* Shift left 1 bit position */
6784 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6786 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6788 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6789 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6793 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6794 emitpcode(POC_ANDLW,popGetLit(0x7e));
6795 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6796 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6799 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6800 emitpcode(POC_ANDLW,popGetLit(0x3e));
6801 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6802 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6803 emitpcode(POC_RLF, popGet(AOP(result),offr));
6806 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6807 emitpcode(POC_ANDLW, popGetLit(0xf0));
6808 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6811 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6812 emitpcode(POC_ANDLW, popGetLit(0xf0));
6813 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6814 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6817 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6818 emitpcode(POC_ANDLW, popGetLit(0x30));
6819 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6820 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6821 emitpcode(POC_RLF, popGet(AOP(result),offr));
6824 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6825 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6826 emitpcode(POC_RRF, popGet(AOP(result),offr));
6830 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6836 /*-----------------------------------------------------------------*/
6837 /* movLeft2Result - move byte from left to result */
6838 /*-----------------------------------------------------------------*/
6839 static void movLeft2Result (operand *left, int offl,
6840 operand *result, int offr)
6844 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6845 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6846 l = aopGet(AOP(left),offl,FALSE,FALSE);
6848 if (*l == '@' && (IS_AOP_PREG(result))) {
6849 pic14_emitcode("mov","a,%s",l);
6850 aopPut(AOP(result),"a",offr);
6852 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6853 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6858 /*-----------------------------------------------------------------*/
6859 /* shiftLeft_Left2ResultLit - shift left by known count */
6860 /*-----------------------------------------------------------------*/
6862 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6864 int size, same, offr, i;
6866 size = AOP_SIZE(left);
6867 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6869 same = pic14_sameRegs (AOP(left), AOP(result));
6872 shCount = shCount & 0x07;
6878 case 0: /* takes 0 or 2N cycles (for offr==0) */
6879 if (!same || offr) {
6880 for (i=size-1; i >= 0; i--)
6881 movLeft2Result (left, i, result, offr + i);
6885 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6887 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6888 shiftLeft_Left2ResultLit (result, result, shCount);
6889 return; /* prevent clearing result again */
6892 for (i=0; i < size; i++) {
6893 if (same && !offr) {
6894 emitpcode (POC_RLF, popGet (AOP(left), i));
6896 emitpcode (POC_RLFW, popGet (AOP(left), i));
6897 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6903 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6904 /* works in-place/with offr as well */
6905 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6906 emitpcode (POC_ANDLW, popGetLit (0xF0));
6907 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6909 for (i = size - 2; i >= 0; i--)
6911 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6912 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6913 emitpcode (POC_ANDLW, popGetLit (0x0F));
6914 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6915 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6919 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6920 /* works in-place/with offr as well */
6921 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6922 for (i = size-2; i >= 0; i--) {
6923 emitpcode (POC_RRFW, popGet (AOP(left), i));
6924 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6926 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6927 emitpcode (POC_RRF, popGet (AOP(result), offr));
6931 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6932 shiftLeft_Left2ResultLit (result, result, 1);
6933 return; /* prevent clearing result again */
6939 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6943 /*-----------------------------------------------------------------*/
6944 /* shiftRight_Left2ResultLit - shift right by known count */
6945 /*-----------------------------------------------------------------*/
6947 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6949 int size, same, offr, i;
6951 size = AOP_SIZE(left);
6952 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6954 same = pic14_sameRegs (AOP(left), AOP(result));
6957 shCount = shCount & 0x07;
6965 case 0: /* takes 0 or 2N cycles (for offr==0) */
6966 if (!same || offr) {
6967 for (i=0; i < size; i++)
6968 movLeft2Result (left, i + offr, result, i);
6972 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6973 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6975 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6976 shiftRight_Left2ResultLit (result, result, shCount, sign);
6977 return; /* prevent sign-extending result again */
6981 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6984 for (i = size-1; i >= 0; i--) {
6985 if (same && !offr) {
6986 emitpcode (POC_RRF, popGet (AOP(left), i));
6988 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6989 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6995 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6996 /* works in-place/with offr as well */
6997 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6998 emitpcode (POC_ANDLW, popGetLit (0x0F));
6999 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7001 for (i = 1; i < size; i++)
7003 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7004 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7005 emitpcode (POC_ANDLW, popGetLit (0xF0));
7006 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7007 emitpcode (POC_XORWF, popGet (AOP(result), i));
7012 emitpcode (POC_MOVLW, popGetLit (0xF0));
7013 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7014 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7018 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7019 /* works in-place/with offr as well */
7020 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7021 for (i = 0; i < size-1; i++) {
7022 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7023 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7025 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7027 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7030 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7035 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7036 shiftRight_Left2ResultLit (result, result, 1, sign);
7037 return; /* prevent sign extending result again */
7042 addSign (result, size, sign);
7046 /*-----------------------------------------------------------------*/
7047 /* shiftL2Left2Result - shift left two bytes from left to result */
7048 /*-----------------------------------------------------------------*/
7049 static void shiftL2Left2Result (operand *left, int offl,
7050 operand *result, int offr, int shCount)
7054 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7056 if(pic14_sameRegs(AOP(result), AOP(left))) {
7064 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7065 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7066 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7070 emitpcode(POC_RLF, popGet(AOP(result),offr));
7071 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7077 emitpcode(POC_MOVLW, popGetLit(0x0f));
7078 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7079 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7080 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7081 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7082 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7083 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7085 emitpcode(POC_RLF, popGet(AOP(result),offr));
7086 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7090 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7091 emitpcode(POC_RRF, popGet(AOP(result),offr));
7092 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7093 emitpcode(POC_RRF, popGet(AOP(result),offr));
7094 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7095 emitpcode(POC_ANDLW,popGetLit(0xc0));
7096 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7097 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7098 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7099 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7102 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7103 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7104 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7105 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7106 emitpcode(POC_RRF, popGet(AOP(result),offr));
7116 /* note, use a mov/add for the shift since the mov has a
7117 chance of getting optimized out */
7118 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7119 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7120 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7121 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7122 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7126 emitpcode(POC_RLF, popGet(AOP(result),offr));
7127 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7133 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7134 emitpcode(POC_ANDLW, popGetLit(0xF0));
7135 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7136 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7137 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7138 emitpcode(POC_ANDLW, popGetLit(0xF0));
7139 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7140 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7144 emitpcode(POC_RLF, popGet(AOP(result),offr));
7145 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7149 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7150 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7151 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7152 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7154 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7155 emitpcode(POC_RRF, popGet(AOP(result),offr));
7156 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7157 emitpcode(POC_ANDLW,popGetLit(0xc0));
7158 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7159 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7160 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7161 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7164 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7165 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7166 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7167 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7168 emitpcode(POC_RRF, popGet(AOP(result),offr));
7174 /*-----------------------------------------------------------------*/
7175 /* shiftR2Left2Result - shift right two bytes from left to result */
7176 /*-----------------------------------------------------------------*/
7177 static void shiftR2Left2Result (operand *left, int offl,
7178 operand *result, int offr,
7179 int shCount, int sign)
7184 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7185 same = pic14_sameRegs(AOP(result), AOP(left));
7187 if(same && ((offl + MSB16) == offr)){
7189 /* don't crash result[offr] */
7190 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7191 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7194 movLeft2Result(left,offl, result, offr);
7195 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7198 /* a:x >> shCount (x = lsb(result))*/
7201 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7203 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7212 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7217 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7218 emitpcode(POC_RRF,popGet(AOP(result),offr));
7220 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7221 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7222 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7223 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7228 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7231 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7232 emitpcode(POC_RRF,popGet(AOP(result),offr));
7239 emitpcode(POC_MOVLW, popGetLit(0xf0));
7240 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7241 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7243 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7244 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7245 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7246 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7248 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7249 emitpcode(POC_ANDLW, popGetLit(0x0f));
7250 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7252 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7253 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7254 emitpcode(POC_ANDLW, popGetLit(0xf0));
7255 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7256 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7260 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7261 emitpcode(POC_RRF, popGet(AOP(result),offr));
7265 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7266 emitpcode(POC_BTFSC,
7267 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7268 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7276 emitpcode(POC_RLF, popGet(AOP(result),offr));
7277 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7279 emitpcode(POC_RLF, popGet(AOP(result),offr));
7280 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7281 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7282 emitpcode(POC_ANDLW,popGetLit(0x03));
7284 emitpcode(POC_BTFSC,
7285 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7286 emitpcode(POC_IORLW,popGetLit(0xfc));
7288 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7289 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7290 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7291 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7293 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7294 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7295 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7296 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7297 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7298 emitpcode(POC_RLF, popGet(AOP(result),offr));
7299 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7300 emitpcode(POC_ANDLW,popGetLit(0x03));
7302 emitpcode(POC_BTFSC,
7303 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7304 emitpcode(POC_IORLW,popGetLit(0xfc));
7306 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7307 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7314 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7315 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7316 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7317 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7320 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7322 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7326 /*-----------------------------------------------------------------*/
7327 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7328 /*-----------------------------------------------------------------*/
7329 static void shiftLLeftOrResult (operand *left, int offl,
7330 operand *result, int offr, int shCount)
7333 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7335 /* shift left accumulator */
7336 AccLsh(left,offl,shCount);
7337 /* or with result */
7338 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7339 assert ( !"broken (modifies left, fails for left==result))" );
7342 /*-----------------------------------------------------------------*/
7343 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7344 /*-----------------------------------------------------------------*/
7345 static void shiftRLeftOrResult (operand *left, int offl,
7346 operand *result, int offr, int shCount)
7349 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7351 /* shift right accumulator */
7352 AccRsh(left,offl,shCount);
7353 /* or with result */
7354 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7355 assert ( !"broken (modifies left, fails for left==result))" );
7358 /*-----------------------------------------------------------------*/
7359 /* genlshOne - left shift a one byte quantity by known count */
7360 /*-----------------------------------------------------------------*/
7361 static void genlshOne (operand *result, operand *left, int shCount)
7364 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7365 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7368 /*-----------------------------------------------------------------*/
7369 /* genlshTwo - left shift two bytes by known amount != 0 */
7370 /*-----------------------------------------------------------------*/
7371 static void genlshTwo (operand *result,operand *left, int shCount)
7376 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7377 size = pic14_getDataSize(result);
7379 /* if shCount >= 8 */
7385 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7387 movLeft2Result(left, LSB, result, MSB16);
7389 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7392 /* 1 <= shCount <= 7 */
7395 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7397 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7401 /*-----------------------------------------------------------------*/
7402 /* shiftLLong - shift left one long from left to result */
7403 /* offl = LSB or MSB16 */
7404 /*-----------------------------------------------------------------*/
7405 static void shiftLLong (operand *left, operand *result, int offr )
7408 int size = AOP_SIZE(result);
7411 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7412 if(size >= LSB+offr){
7413 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7415 pic14_emitcode("add","a,acc");
7416 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7417 size >= MSB16+offr && offr != LSB )
7418 pic14_emitcode("xch","a,%s",
7419 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7421 aopPut(AOP(result),"a",LSB+offr);
7424 if(size >= MSB16+offr){
7425 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7426 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7429 pic14_emitcode("rlc","a");
7430 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7431 size >= MSB24+offr && offr != LSB)
7432 pic14_emitcode("xch","a,%s",
7433 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7435 aopPut(AOP(result),"a",MSB16+offr);
7438 if(size >= MSB24+offr){
7439 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7440 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7443 pic14_emitcode("rlc","a");
7444 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7445 size >= MSB32+offr && offr != LSB )
7446 pic14_emitcode("xch","a,%s",
7447 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7449 aopPut(AOP(result),"a",MSB24+offr);
7452 if(size > MSB32+offr){
7453 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7454 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7457 pic14_emitcode("rlc","a");
7458 aopPut(AOP(result),"a",MSB32+offr);
7461 aopPut(AOP(result),zero,LSB);
7464 /*-----------------------------------------------------------------*/
7465 /* genlshFour - shift four byte by a known amount != 0 */
7466 /*-----------------------------------------------------------------*/
7467 static void genlshFour (operand *result, operand *left, int shCount)
7472 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7473 size = AOP_SIZE(result);
7475 /* if shifting more that 3 bytes */
7476 if (shCount >= 24 ) {
7479 /* lowest order of left goes to the highest
7480 order of the destination */
7481 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7483 movLeft2Result(left, LSB, result, MSB32);
7484 aopPut(AOP(result),zero,LSB);
7485 aopPut(AOP(result),zero,MSB16);
7486 aopPut(AOP(result),zero,MSB32);
7490 /* more than two bytes */
7491 else if ( shCount >= 16 ) {
7492 /* lower order two bytes goes to higher order two bytes */
7494 /* if some more remaining */
7496 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7498 movLeft2Result(left, MSB16, result, MSB32);
7499 movLeft2Result(left, LSB, result, MSB24);
7501 aopPut(AOP(result),zero,MSB16);
7502 aopPut(AOP(result),zero,LSB);
7506 /* if more than 1 byte */
7507 else if ( shCount >= 8 ) {
7508 /* lower order three bytes goes to higher order three bytes */
7512 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7514 movLeft2Result(left, LSB, result, MSB16);
7516 else{ /* size = 4 */
7518 movLeft2Result(left, MSB24, result, MSB32);
7519 movLeft2Result(left, MSB16, result, MSB24);
7520 movLeft2Result(left, LSB, result, MSB16);
7521 aopPut(AOP(result),zero,LSB);
7523 else if(shCount == 1)
7524 shiftLLong(left, result, MSB16);
7526 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7527 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7528 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7529 aopPut(AOP(result),zero,LSB);
7534 /* 1 <= shCount <= 7 */
7535 else if(shCount <= 2){
7536 shiftLLong(left, result, LSB);
7538 shiftLLong(result, result, LSB);
7540 /* 3 <= shCount <= 7, optimize */
7542 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7543 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7544 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7550 /*-----------------------------------------------------------------*/
7551 /* genLeftShiftLiteral - left shifting by known count */
7552 /*-----------------------------------------------------------------*/
7553 static void genLeftShiftLiteral (operand *left,
7558 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7562 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7563 freeAsmop(right,NULL,ic,TRUE);
7565 aopOp(left,ic,FALSE);
7566 aopOp(result,ic,FALSE);
7568 size = getSize(operandType(result));
7571 pic14_emitcode("; shift left ","result %d, left %d",size,
7575 /* I suppose that the left size >= result size */
7578 movLeft2Result(left, size, result, size);
7582 else if(shCount >= (size * 8))
7584 aopPut(AOP(result),zero,size);
7588 genlshOne (result,left,shCount);
7593 genlshTwo (result,left,shCount);
7597 genlshFour (result,left,shCount);
7601 freeAsmop(left,NULL,ic,TRUE);
7602 freeAsmop(result,NULL,ic,TRUE);
7606 /*-----------------------------------------------------------------*
7607 * genMultiAsm - repeat assembly instruction for size of register.
7608 * if endian == 1, then the high byte (i.e base address + size of
7609 * register) is used first else the low byte is used first;
7610 *-----------------------------------------------------------------*/
7611 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7617 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7630 emitpcode(poc, popGet(AOP(reg),offset));
7637 /*-----------------------------------------------------------------*/
7638 /* genLeftShift - generates code for left shifting */
7639 /*-----------------------------------------------------------------*/
7640 static void genLeftShift (iCode *ic)
7642 operand *left,*right, *result;
7644 unsigned long lit = 0L;
7646 symbol *tlbl , *tlbl1;
7650 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7652 right = IC_RIGHT(ic);
7654 result = IC_RESULT(ic);
7656 aopOp(right,ic,FALSE);
7657 aopOp(left,ic,FALSE);
7658 aopOp(result,ic,FALSE);
7661 /* if the shift count is known then do it
7662 as efficiently as possible */
7663 if (AOP_TYPE(right) == AOP_LIT) {
7664 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7668 /* shift count is unknown then we have to form
7669 a loop get the loop count in B : Note: we take
7670 only the lower order byte since shifting
7671 more that 32 bits make no sense anyway, ( the
7672 largest size of an object can be only 32 bits ) */
7674 /* this code fails for RIGHT == RESULT */
7675 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7677 /* now move the left to the result if they are not the
7679 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7680 AOP_SIZE(result) > 1) {
7682 size = AOP_SIZE(result);
7685 l = aopGet(AOP(left),offset,FALSE,TRUE);
7686 if (*l == '@' && (IS_AOP_PREG(result))) {
7688 pic14_emitcode("mov","a,%s",l);
7689 aopPut(AOP(result),"a",offset);
7691 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7692 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7693 //aopPut(AOP(result),l,offset);
7699 if(AOP_TYPE(left) == AOP_LIT)
7700 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7702 size = AOP_SIZE(result);
7704 /* if it is only one byte then */
7706 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7707 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7708 emitpcode(POC_ANDLW, popGetLit(0xf0));
7709 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7710 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7711 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7712 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7713 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7714 emitpcode(POC_RLFW, popGet(AOP(result),0));
7715 emitpcode(POC_ANDLW, popGetLit(0xfe));
7716 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7717 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7718 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7721 tlbl = newiTempLabel(NULL);
7722 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7723 mov2w (AOP(left), 0);
7724 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7727 emitpcode(POC_COMFW, popGet(AOP(right),0));
7728 emitpcode(POC_RRF, popGet(AOP(result),0));
7729 emitpLabel(tlbl->key);
7730 emitpcode(POC_RLF, popGet(AOP(result),0));
7731 emitpcode(POC_ADDLW, popGetLit(1));
7733 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7738 if (pic14_sameRegs(AOP(left),AOP(result))) {
7740 tlbl = newiTempLabel(NULL);
7741 emitpcode(POC_COMFW, popGet(AOP(right),0));
7742 genMultiAsm(POC_RRF, result, size,1);
7743 emitpLabel(tlbl->key);
7744 genMultiAsm(POC_RLF, result, size,0);
7745 emitpcode(POC_ADDLW, popGetLit(1));
7747 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7751 //tlbl = newiTempLabel(NULL);
7753 //tlbl1 = newiTempLabel(NULL);
7755 //reAdjustPreg(AOP(result));
7757 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7758 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7759 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7761 //pic14_emitcode("add","a,acc");
7762 //aopPut(AOP(result),"a",offset++);
7764 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7766 // pic14_emitcode("rlc","a");
7767 // aopPut(AOP(result),"a",offset++);
7769 //reAdjustPreg(AOP(result));
7771 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7772 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7775 tlbl = newiTempLabel(NULL);
7776 tlbl1= newiTempLabel(NULL);
7778 size = AOP_SIZE(result);
7781 pctemp = popGetTempReg(); /* grab a temporary working register. */
7783 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7785 /* offset should be 0, 1 or 3 */
7786 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7788 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7790 emitpcode(POC_MOVWF, pctemp);
7793 emitpLabel(tlbl->key);
7796 emitpcode(POC_RLF, popGet(AOP(result),0));
7798 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7800 emitpcode(POC_DECFSZ, pctemp);
7801 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7802 emitpLabel(tlbl1->key);
7804 popReleaseTempReg(pctemp);
7808 freeAsmop (right,NULL,ic,TRUE);
7809 freeAsmop(left,NULL,ic,TRUE);
7810 freeAsmop(result,NULL,ic,TRUE);
7815 /*-----------------------------------------------------------------*/
7816 /* genrshOne - right shift a one byte quantity by known count */
7817 /*-----------------------------------------------------------------*/
7818 static void genrshOne (operand *result, operand *left,
7819 int shCount, int sign)
7822 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7823 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7826 /*-----------------------------------------------------------------*/
7827 /* genrshTwo - right shift two bytes by known amount != 0 */
7828 /*-----------------------------------------------------------------*/
7829 static void genrshTwo (operand *result,operand *left,
7830 int shCount, int sign)
7833 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7834 /* if shCount >= 8 */
7838 shiftR1Left2Result(left, MSB16, result, LSB,
7841 movLeft2Result(left, MSB16, result, LSB);
7843 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7846 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7847 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7851 /* 1 <= shCount <= 7 */
7853 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7856 /*-----------------------------------------------------------------*/
7857 /* shiftRLong - shift right one long from left to result */
7858 /* offl = LSB or MSB16 */
7859 /*-----------------------------------------------------------------*/
7860 static void shiftRLong (operand *left, int offl,
7861 operand *result, int sign)
7866 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7868 size = AOP_SIZE(left);
7869 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7872 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7876 assert (offl >= 0 && offl < size);
7878 same = pic14_sameRegs (AOP(left), AOP(result));
7880 /* perform the shift */
7883 if (same && !offl) {
7884 emitpcode (POC_RRF, popGet (AOP(result), size));
7886 emitpcode (POC_RRFW, popGet (AOP(left), size));
7887 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7891 addSign (result, AOP_SIZE(left) - offl, sign);
7894 /*-----------------------------------------------------------------*/
7895 /* genrshFour - shift four byte by a known amount != 0 */
7896 /*-----------------------------------------------------------------*/
7897 static void genrshFour (operand *result, operand *left,
7898 int shCount, int sign)
7901 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7902 /* if shifting more that 3 bytes */
7903 if(shCount >= 24 ) {
7906 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7908 movLeft2Result(left, MSB32, result, LSB);
7910 addSign(result, MSB16, sign);
7912 else if(shCount >= 16){
7915 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7917 movLeft2Result(left, MSB24, result, LSB);
7918 movLeft2Result(left, MSB32, result, MSB16);
7920 addSign(result, MSB24, sign);
7922 else if(shCount >= 8){
7925 shiftRLong(left, MSB16, result, sign);
7926 else if(shCount == 0){
7927 movLeft2Result(left, MSB16, result, LSB);
7928 movLeft2Result(left, MSB24, result, MSB16);
7929 movLeft2Result(left, MSB32, result, MSB24);
7930 addSign(result, MSB32, sign);
7933 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7934 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7935 /* the last shift is signed */
7936 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7937 addSign(result, MSB32, sign);
7940 else{ /* 1 <= shCount <= 7 */
7942 shiftRLong(left, LSB, result, sign);
7944 shiftRLong(result, LSB, result, sign);
7947 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7948 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7949 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7954 /*-----------------------------------------------------------------*/
7955 /* genRightShiftLiteral - right shifting by known count */
7956 /*-----------------------------------------------------------------*/
7957 static void genRightShiftLiteral (operand *left,
7963 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7967 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7968 freeAsmop(right,NULL,ic,TRUE);
7970 aopOp(left,ic,FALSE);
7971 aopOp(result,ic,FALSE);
7974 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7978 lsize = pic14_getDataSize(left);
7979 res_size = pic14_getDataSize(result);
7980 /* test the LEFT size !!! */
7982 /* I suppose that the left size >= result size */
7985 movLeft2Result(left, res_size, result, res_size);
7988 else if(shCount >= (lsize * 8)){
7991 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7993 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7994 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7999 emitpcode(POC_MOVLW, popGetLit(0));
8000 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8001 emitpcode(POC_MOVLW, popGetLit(0xff));
8003 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8008 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8015 genrshOne (result,left,shCount,sign);
8019 genrshTwo (result,left,shCount,sign);
8023 genrshFour (result,left,shCount,sign);
8031 freeAsmop(left,NULL,ic,TRUE);
8032 freeAsmop(result,NULL,ic,TRUE);
8037 /*-----------------------------------------------------------------*/
8038 /* genSignedRightShift - right shift of signed number */
8039 /*-----------------------------------------------------------------*/
8040 static void genSignedRightShift (iCode *ic)
8042 operand *right, *left, *result;
8045 symbol *tlbl, *tlbl1 ;
8048 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8050 /* we do it the hard way put the shift count in b
8051 and loop thru preserving the sign */
8053 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8055 right = IC_RIGHT(ic);
8057 result = IC_RESULT(ic);
8059 aopOp(right,ic,FALSE);
8060 aopOp(left,ic,FALSE);
8061 aopOp(result,ic,FALSE);
8064 if ( AOP_TYPE(right) == AOP_LIT) {
8065 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8066 //genRightShiftLiteral (left,right,result,ic,1);
8069 /* shift count is unknown then we have to form
8070 a loop get the loop count in B : Note: we take
8071 only the lower order byte since shifting
8072 more that 32 bits make no sense anyway, ( the
8073 largest size of an object can be only 32 bits ) */
8075 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8076 //pic14_emitcode("inc","b");
8077 //freeAsmop (right,NULL,ic,TRUE);
8078 //aopOp(left,ic,FALSE);
8079 //aopOp(result,ic,FALSE);
8081 /* now move the left to the result if they are not the
8083 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8084 AOP_SIZE(result) > 1) {
8086 size = AOP_SIZE(result);
8090 l = aopGet(AOP(left),offset,FALSE,TRUE);
8091 if (*l == '@' && IS_AOP_PREG(result)) {
8092 pic14_emitcode("mov","a,%s",l);
8093 aopPut(AOP(result),"a",offset);
8095 aopPut(AOP(result),l,offset);
8097 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8098 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8104 /* mov the highest order bit to OVR */
8105 tlbl = newiTempLabel(NULL);
8106 tlbl1= newiTempLabel(NULL);
8108 size = AOP_SIZE(result);
8111 pctemp = popGetTempReg(); /* grab a temporary working register. */
8113 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8115 /* offset should be 0, 1 or 3 */
8116 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8118 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8120 emitpcode(POC_MOVWF, pctemp);
8123 emitpLabel(tlbl->key);
8125 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8126 emitpcode(POC_RRF, popGet(AOP(result),offset));
8129 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8132 emitpcode(POC_DECFSZ, pctemp);
8133 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8134 emitpLabel(tlbl1->key);
8136 popReleaseTempReg(pctemp);
8138 size = AOP_SIZE(result);
8140 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8141 pic14_emitcode("rlc","a");
8142 pic14_emitcode("mov","ov,c");
8143 /* if it is only one byte then */
8145 l = aopGet(AOP(left),0,FALSE,FALSE);
8147 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8148 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8149 pic14_emitcode("mov","c,ov");
8150 pic14_emitcode("rrc","a");
8151 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8152 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8153 aopPut(AOP(result),"a",0);
8157 reAdjustPreg(AOP(result));
8158 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8159 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8160 pic14_emitcode("mov","c,ov");
8162 l = aopGet(AOP(result),offset,FALSE,FALSE);
8164 pic14_emitcode("rrc","a");
8165 aopPut(AOP(result),"a",offset--);
8167 reAdjustPreg(AOP(result));
8168 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8169 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8174 freeAsmop(left,NULL,ic,TRUE);
8175 freeAsmop(result,NULL,ic,TRUE);
8176 freeAsmop(right,NULL,ic,TRUE);
8180 /*-----------------------------------------------------------------*/
8181 /* loadSignToC - load the operand's sign bit into CARRY */
8182 /*-----------------------------------------------------------------*/
8184 static void loadSignToC (operand *op)
8187 assert (op && AOP(op) && AOP_SIZE(op));
8190 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8194 /*-----------------------------------------------------------------*/
8195 /* genRightShift - generate code for right shifting */
8196 /*-----------------------------------------------------------------*/
8197 static void genGenericShift (iCode *ic, int shiftRight)
8199 operand *right, *left, *result;
8202 symbol *tlbl, *tlbl1, *inverselbl;
8205 /* if signed then we do it the hard way preserve the
8206 sign bit moving it inwards */
8207 retype = getSpec(operandType(IC_RESULT(ic)));
8208 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8210 /* signed & unsigned types are treated the same : i.e. the
8211 signed is NOT propagated inwards : quoting from the
8212 ANSI - standard : "for E1 >> E2, is equivalent to division
8213 by 2**E2 if unsigned or if it has a non-negative value,
8214 otherwise the result is implementation defined ", MY definition
8215 is that the sign does not get propagated */
8217 right = IC_RIGHT(ic);
8219 result = IC_RESULT(ic);
8221 aopOp(right,ic,FALSE);
8222 aopOp(left,ic,FALSE);
8223 aopOp(result,ic,FALSE);
8225 /* if the shift count is known then do it
8226 as efficiently as possible */
8227 if (AOP_TYPE(right) == AOP_LIT) {
8228 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8232 shiftRight = !shiftRight;
8236 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8238 shiftLeft_Left2ResultLit (left, result, lit);
8239 //genRightShiftLiteral (left,right,result,ic, 0);
8243 /* shift count is unknown then we have to form
8244 a loop get the loop count in B : Note: we take
8245 only the lower order byte since shifting
8246 more that 32 bits make no sense anyway, ( the
8247 largest size of an object can be only 32 bits ) */
8249 /* we must not overwrite the shift counter */
8250 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8252 /* now move the left to the result if they are not the
8254 if (!pic14_sameRegs(AOP(left),AOP(result)))
8256 size = min(AOP_SIZE(result), AOP_SIZE(left));
8258 mov2w(AOP(left), size);
8259 movwf(AOP(result), size);
8261 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8264 tlbl = newiTempLabel(NULL);
8265 tlbl1= newiTempLabel(NULL);
8267 size = AOP_SIZE(result);
8269 mov2w(AOP(right),0);
8270 if (!SPEC_USIGN(operandType(right)))
8272 inverselbl = newiTempLabel(NULL);
8273 /* signed shift count -- invert shift direction for c<0 */
8274 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8275 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8277 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8278 /* check for `a = b >> c' with `-c == 0' */
8280 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8281 emitpLabel(tlbl->key);
8282 /* propagate the sign bit inwards for SIGNED result */
8283 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8284 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8285 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8287 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8289 if (!SPEC_USIGN(operandType(right)))
8291 symbol *inv_loop = newiTempLabel(NULL);
8293 shiftRight = !shiftRight; /* invert shift direction */
8295 /* we came here from the code above -- we are done */
8296 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8298 /* emit code for shifting N<0 steps, count is already in W */
8299 emitpLabel(inverselbl->key);
8300 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8301 emitpLabel(inv_loop->key);
8302 /* propagate the sign bit inwards for SIGNED result */
8303 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8304 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8305 emitpcode(POC_ADDLW, popGetLit(1));
8307 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8310 emitpLabel(tlbl1->key);
8312 freeAsmop(left,NULL,ic,TRUE);
8313 freeAsmop (right,NULL,ic,TRUE);
8314 freeAsmop(result,NULL,ic,TRUE);
8317 static void genRightShift (iCode *ic)
8319 genGenericShift(ic, 1);
8322 static void genLeftShift (iCode *ic)
8324 genGenericShift(ic, 0);
8327 /*-----------------------------------------------------------------*/
8328 /* SetIrp - Set IRP bit */
8329 /*-----------------------------------------------------------------*/
8330 void SetIrp(operand *result) {
8332 if (AOP_TYPE(result) == AOP_LIT) {
8333 unsigned lit = (unsigned)operandLitValue(result);
8339 if (PCOP(AOP(result))->type == PO_LITERAL) {
8340 int addrs = PCOL(AOP(result))->lit;
8346 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8347 if(AOP_SIZE(result) > 1) {
8348 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8356 setup_fsr (operand *ptr)
8359 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8361 /* also setup-up IRP */
8365 /*-----------------------------------------------------------------*/
8366 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8367 /* arbitrary pointer (__code, __data, generic) */
8368 /*-----------------------------------------------------------------*/
8370 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8377 if (!alreadyAddressed) setup_fsr (src);
8378 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8382 assert( AOP_SIZE(src) == 2 );
8384 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8386 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8387 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8388 call_libraryfunc ("__gptrget1");
8392 assert( AOP_SIZE(src) == 3 );
8394 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8396 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8398 call_libraryfunc ("__gptrget1");
8402 assert( !"unhandled pointer type" );
8407 /*-----------------------------------------------------------------*/
8408 /* emitPtrByteSet - emits code to set a byte from src through a */
8409 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8410 /*-----------------------------------------------------------------*/
8412 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8419 if (!alreadyAddressed) setup_fsr (dst);
8420 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8424 assert( !"trying to assign to __code pointer" );
8428 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8430 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8432 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8434 call_libraryfunc ("__gptrput1");
8438 assert( !"unhandled pointer type" );
8443 /*-----------------------------------------------------------------*/
8444 /* genUnpackBits - generates code for unpacking bits */
8445 /*-----------------------------------------------------------------*/
8446 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8448 int rsize; /* result size */
8449 sym_link *etype; /* bitfield type information */
8450 int blen; /* bitfield length */
8451 int bstr; /* bitfield starting bit within byte */
8454 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8455 etype = getSpec(operandType(result));
8456 rsize = getSize (operandType (result));
8457 blen = SPEC_BLEN (etype);
8458 bstr = SPEC_BSTR (etype);
8460 /* single bit field case */
8462 if (ifx) { /* that is for an if statement */
8465 resolveIfx(&rIfx,ifx);
8466 if (ptype == -1) /* direct */
8467 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8469 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8470 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8471 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8475 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8476 for (i=0; i < AOP_SIZE(result); i++)
8477 emitpcode (POC_CLRF, popGet (AOP(result), i));
8482 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8483 /* adjust result below */
8490 emitPtrByteGet (left, ptype, FALSE);
8491 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8493 /* adjust result below */
8497 assert( !"unhandled pointer type" );
8500 /* move sign-/zero extended bit to result */
8501 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8502 emitpcode (POC_INCF, popGet (AOP(result), 0));
8504 emitpcode (POC_DECF, popGet (AOP(result), 0));
8506 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8510 else if (blen <= 8 && ((blen + bstr) <= 8))
8515 for (i=0; i < AOP_SIZE(result); i++)
8516 emitpcode (POC_CLRF, popGet (AOP(result), i));
8521 mov2w(AOP(left), 0);
8528 emitPtrByteGet (left, ptype, FALSE);
8532 assert( !"unhandled pointer type" );
8536 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8537 movwf(AOP(result), 0);
8538 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8540 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8542 /* signed bitfield */
8543 assert (bstr + blen > 0);
8544 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8545 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8546 emitpcode(POC_IORWF, popGet(AOP(result),0));
8548 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8552 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8556 /*-----------------------------------------------------------------*/
8557 /* genDataPointerGet - generates code when ptr offset is known */
8558 /*-----------------------------------------------------------------*/
8559 static void genDataPointerGet (operand *left,
8563 int size , offset = 0;
8566 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8569 /* optimization - most of the time, left and result are the same
8570 * address, but different types. for the pic code, we could omit
8573 aopOp(result,ic,TRUE);
8575 if (pic14_sameRegs (AOP(left), AOP(result)))
8578 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8580 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8582 size = AOP_SIZE(result);
8583 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8587 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8588 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8592 freeAsmop(left,NULL,ic,TRUE);
8593 freeAsmop(result,NULL,ic,TRUE);
8597 /*-----------------------------------------------------------------*/
8598 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8599 /*-----------------------------------------------------------------*/
8600 static void genNearPointerGet (operand *left,
8605 sym_link *ltype = operandType(left);
8606 sym_link *rtype = operandType(result);
8607 sym_link *retype= getSpec(rtype); /* bitfield type information */
8611 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8614 aopOp(left,ic,FALSE);
8616 /* if left is rematerialisable and
8617 result is not bit variable type and
8618 the left is pointer to data space i.e
8619 lower 128 bytes of space */
8620 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8621 !IS_BITVAR(retype) &&
8622 PIC_IS_DATA_PTR(ltype)) {
8623 genDataPointerGet (left,result,ic);
8627 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8628 aopOp (result,ic,FALSE);
8630 /* Check if can access directly instead of via a pointer */
8631 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8632 && AOP_SIZE(result) == 1)
8637 if (IS_BITFIELD(getSpec(operandType(result))))
8639 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8643 /* If the pointer value is not in a the FSR then need to put it in */
8644 /* Must set/reset IRP bit for use with FSR. */
8649 /* if bitfield then unpack the bits */
8651 /* we have can just get the values */
8652 int size = AOP_SIZE(result);
8655 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8659 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8661 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8662 if (AOP_TYPE(result) == AOP_LIT) {
8663 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8665 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8667 if (size && !direct)
8668 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8673 /* now some housekeeping stuff */
8675 /* we had to allocate for this iCode */
8676 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8677 freeAsmop(NULL,aop,ic,TRUE);
8679 /* we did not allocate which means left
8680 already in a pointer register, then
8681 if size > 0 && this could be used again
8682 we have to point it back to where it
8684 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8685 if (AOP_SIZE(result) > 1 &&
8686 !OP_SYMBOL(left)->remat &&
8687 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8689 int size = AOP_SIZE(result) - 1;
8691 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8697 freeAsmop(left,NULL,ic,TRUE);
8698 freeAsmop(result,NULL,ic,TRUE);
8703 /*-----------------------------------------------------------------*/
8704 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8705 /*-----------------------------------------------------------------*/
8706 static void genPagedPointerGet (operand *left,
8713 sym_link *rtype, *retype;
8716 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8718 rtype = operandType(result);
8719 retype= getSpec(rtype);
8721 aopOp(left,ic,FALSE);
8723 /* if the value is already in a pointer register
8724 then don't need anything more */
8725 if (!AOP_INPREG(AOP(left))) {
8726 /* otherwise get a free pointer register */
8728 preg = getFreePtr(ic,&aop,FALSE);
8729 pic14_emitcode("mov","%s,%s",
8731 aopGet(AOP(left),0,FALSE,TRUE));
8732 rname = preg->name ;
8734 rname = aopGet(AOP(left),0,FALSE,FALSE);
8736 freeAsmop(left,NULL,ic,TRUE);
8737 aopOp (result,ic,FALSE);
8739 /* if bitfield then unpack the bits */
8740 if (IS_BITFIELD(retype))
8741 genUnpackBits (result,left,rname,PPOINTER,0);
8743 /* we have can just get the values */
8744 int size = AOP_SIZE(result);
8749 pic14_emitcode("movx","a,@%s",rname);
8750 aopPut(AOP(result),"a",offset);
8755 pic14_emitcode("inc","%s",rname);
8759 /* now some housekeeping stuff */
8761 /* we had to allocate for this iCode */
8762 freeAsmop(NULL,aop,ic,TRUE);
8764 /* we did not allocate which means left
8765 already in a pointer register, then
8766 if size > 0 && this could be used again
8767 we have to point it back to where it
8769 if (AOP_SIZE(result) > 1 &&
8770 !OP_SYMBOL(left)->remat &&
8771 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8773 int size = AOP_SIZE(result) - 1;
8775 pic14_emitcode("dec","%s",rname);
8780 freeAsmop(result,NULL,ic,TRUE);
8785 /*-----------------------------------------------------------------*/
8786 /* genFarPointerGet - gget value from far space */
8787 /*-----------------------------------------------------------------*/
8788 static void genFarPointerGet (operand *left,
8789 operand *result, iCode *ic)
8792 sym_link *retype = getSpec(operandType(result));
8795 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8797 aopOp(left,ic,FALSE);
8799 /* if the operand is already in dptr
8800 then we do nothing else we move the value to dptr */
8801 if (AOP_TYPE(left) != AOP_STR) {
8802 /* if this is remateriazable */
8803 if (AOP_TYPE(left) == AOP_IMMD)
8804 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8805 else { /* we need to get it byte by byte */
8806 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8807 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8808 if (options.model == MODEL_FLAT24)
8810 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8814 /* so dptr know contains the address */
8815 freeAsmop(left,NULL,ic,TRUE);
8816 aopOp(result,ic,FALSE);
8818 /* if bit then unpack */
8819 if (IS_BITFIELD(retype))
8820 genUnpackBits(result,left,"dptr",FPOINTER,0);
8822 size = AOP_SIZE(result);
8826 pic14_emitcode("movx","a,@dptr");
8827 aopPut(AOP(result),"a",offset++);
8829 pic14_emitcode("inc","dptr");
8833 freeAsmop(result,NULL,ic,TRUE);
8838 /*-----------------------------------------------------------------*/
8839 /* genCodePointerGet - get value from code space */
8840 /*-----------------------------------------------------------------*/
8841 static void genCodePointerGet (operand *left,
8842 operand *result, iCode *ic)
8845 sym_link *retype = getSpec(operandType(result));
8847 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8849 aopOp(left,ic,FALSE);
8851 /* if the operand is already in dptr
8852 then we do nothing else we move the value to dptr */
8853 if (AOP_TYPE(left) != AOP_STR) {
8854 /* if this is remateriazable */
8855 if (AOP_TYPE(left) == AOP_IMMD)
8856 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8857 else { /* we need to get it byte by byte */
8858 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8859 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8860 if (options.model == MODEL_FLAT24)
8862 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8866 /* so dptr know contains the address */
8867 freeAsmop(left,NULL,ic,TRUE);
8868 aopOp(result,ic,FALSE);
8870 /* if bit then unpack */
8871 if (IS_BITFIELD(retype))
8872 genUnpackBits(result,left,"dptr",CPOINTER,0);
8874 size = AOP_SIZE(result);
8878 pic14_emitcode("clr","a");
8879 pic14_emitcode("movc","a,@a+dptr");
8880 aopPut(AOP(result),"a",offset++);
8882 pic14_emitcode("inc","dptr");
8886 freeAsmop(result,NULL,ic,TRUE);
8889 /*-----------------------------------------------------------------*/
8890 /* genGenPointerGet - gget value from generic pointer space */
8891 /*-----------------------------------------------------------------*/
8892 static void genGenPointerGet (operand *left,
8893 operand *result, iCode *ic)
8896 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8897 aopOp(left,ic,FALSE);
8898 aopOp(result,ic,FALSE);
8901 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8903 if (IS_BITFIELD(getSpec(operandType(result))))
8905 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8910 /* emit call to __gptrget */
8911 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8912 int size = AOP_SIZE(result);
8915 assert (size > 0 && size <= 4);
8917 /* pass arguments */
8918 assert (AOP_SIZE(left) == 3);
8919 mov2w(AOP(left), 0);
8920 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8921 mov2w(AOP(left), 1);
8922 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8923 mov2w(AOP(left), 2);
8924 call_libraryfunc (func[size]);
8927 movwf (AOP(result), --size);
8929 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8930 movwf (AOP(result), size);
8934 freeAsmop(left,NULL,ic,TRUE);
8935 freeAsmop(result,NULL,ic,TRUE);
8939 /*-----------------------------------------------------------------*/
8940 /* genConstPointerGet - get value from const generic pointer space */
8941 /*-----------------------------------------------------------------*/
8942 static void genConstPointerGet (operand *left,
8943 operand *result, iCode *ic)
8945 //sym_link *retype = getSpec(operandType(result));
8947 symbol *albl, *blbl;//, *clbl;
8954 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8955 aopOp(left,ic,FALSE);
8956 aopOp(result,ic,FALSE);
8958 size = AOP_SIZE(result);
8960 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8962 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8964 lit = op_isLitLike (left);
8965 poc = lit ? POC_MOVLW : POC_MOVFW;
8967 if (IS_BITFIELD(getSpec(operandType(result))))
8969 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
8974 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
8975 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
8976 assert (size > 0 && size <= 4);
8979 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8981 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8982 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8983 call_libraryfunc (func[size]);
8985 movwf(AOP(result),size-1);
8986 for (i = 1; i < size; i++)
8988 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
8989 movwf(AOP(result),size - 1 - i);
8994 freeAsmop(left,NULL,ic,TRUE);
8995 freeAsmop(result,NULL,ic,TRUE);
8998 /*-----------------------------------------------------------------*/
8999 /* genPointerGet - generate code for pointer get */
9000 /*-----------------------------------------------------------------*/
9001 static void genPointerGet (iCode *ic)
9003 operand *left, *result ;
9004 sym_link *type, *etype;
9008 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9011 result = IC_RESULT(ic) ;
9013 /* depending on the type of pointer we need to
9014 move it to the correct pointer register */
9015 type = operandType(left);
9016 etype = getSpec(type);
9018 if (IS_PTR_CONST(type))
9019 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9021 /* if left is of type of pointer then it is simple */
9022 if (IS_PTR(type) && !IS_FUNC(type->next))
9023 p_type = DCL_TYPE(type);
9025 /* we have to go by the storage class */
9026 p_type = PTR_TYPE(SPEC_OCLS(etype));
9028 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9030 if (SPEC_OCLS(etype)->codesp ) {
9031 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9032 //p_type = CPOINTER ;
9035 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9036 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9037 /*p_type = FPOINTER ;*/
9039 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9040 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9041 /* p_type = PPOINTER; */
9043 if (SPEC_OCLS(etype) == idata )
9044 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9045 /* p_type = IPOINTER; */
9047 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9048 /* p_type = POINTER ; */
9051 /* now that we have the pointer type we assign
9052 the pointer values */
9058 genNearPointerGet (left,result,ic);
9062 genPagedPointerGet(left,result,ic);
9066 genFarPointerGet (left,result,ic);
9070 genConstPointerGet (left,result,ic);
9074 genGenPointerGet (left,result,ic);
9077 assert ( !"unhandled pointer type" );
9083 /*-----------------------------------------------------------------*/
9084 /* genPackBits - generates code for packed bit storage */
9085 /*-----------------------------------------------------------------*/
9086 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9088 int blen; /* bitfield length */
9089 int bstr; /* bitfield starting bit within byte */
9090 int litval; /* source literal value (if AOP_LIT) */
9091 unsigned char mask; /* bitmask within current byte */
9094 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9096 blen = SPEC_BLEN (etype);
9097 bstr = SPEC_BSTR (etype);
9099 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9100 if ((blen <= 8) && ((bstr + blen) <= 8))
9102 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9103 (unsigned char) (0xFF >> (8 - bstr)));
9105 if (AOP_TYPE (right) == AOP_LIT)
9107 /* Case with a bitfield length <8 and literal source */
9108 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9115 if (AOP(result)->type == AOP_PCODE)
9116 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9118 pcop = popGet(AOP(result),0);
9119 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9125 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9129 assert( !"trying to assign to bitfield via pointer to __code space" );
9133 emitPtrByteGet(result, p_type, FALSE);
9135 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9137 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9139 emitPtrByteSet(result, p_type, TRUE);
9143 assert( !"unhandled pointer type" );
9145 } // switch (p_type)
9148 litval = lit << bstr;
9149 litval &= (~mask) & 0x00ff;
9154 mov2w (AOP(result), 0);
9155 if ((litval|mask) != 0x00ff)
9156 emitpcode(POC_ANDLW, popGetLit (mask));
9158 emitpcode(POC_IORLW, popGetLit (litval));
9159 movwf (AOP(result), 0);
9165 emitPtrByteGet(result, p_type, FALSE);
9166 if ((litval|mask) != 0x00ff)
9167 emitpcode(POC_ANDLW, popGetLit (mask));
9169 emitpcode(POC_IORLW, popGetLit (litval));
9170 emitPtrByteSet(result, p_type, TRUE);
9174 assert( !"trying to assign to bitfield via pointer to __code space" );
9178 assert( !"unhandled pointer type" );
9185 /* right is no literal */
9190 /* Note more efficient code, of pre clearing bit then only setting it if required,
9191 * can only be done if it is known that the result is not a SFR */
9192 emitpcode(POC_RRFW,popGet(AOP(right),0));
9194 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9196 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9202 emitPtrByteGet (result, p_type, FALSE);
9203 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9204 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9205 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9206 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9207 emitPtrByteSet (result, p_type, TRUE);
9211 assert( !"trying to assign to bitfield via pointer to __code space" );
9215 assert( !"unhandled pointer type" );
9220 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9221 pCodeOp *temp = popGetTempReg ();
9223 mov2w (AOP(right), 0);
9225 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9227 emitpcode(POC_MOVWF, temp);
9229 AccLsh (temp, bstr);
9235 mov2w (AOP(result), 0);
9236 emitpcode(POC_ANDLW, popGetLit (mask));
9237 emitpcode(POC_IORFW, temp);
9238 movwf (AOP(result), 0);
9244 emitPtrByteGet (result, p_type, FALSE);
9245 emitpcode(POC_ANDLW, popGetLit (mask));
9246 emitpcode(POC_IORFW, temp);
9247 emitPtrByteSet (result, p_type, TRUE);
9251 assert( !"trying to assign to bitfield via pointer to __code space" );
9255 assert( !"unhandled pointer type" );
9259 popReleaseTempReg (temp);
9261 } // if (AOP(right)->type != AOP_LIT)
9263 } // if (blen <= 8 && ((blen + bstr) <= 8))
9265 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9268 /*-----------------------------------------------------------------*/
9269 /* genDataPointerSet - remat pointer to data space */
9270 /*-----------------------------------------------------------------*/
9271 static void genDataPointerSet(operand *right,
9275 int size, offset = 0 ;
9279 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9280 aopOp(right,ic,FALSE);
9281 aopOp(result,ic,FALSE);
9283 assert (IS_SYMOP(result));
9284 assert (IS_PTR(OP_SYM_TYPE(result)));
9286 if (AOP_TYPE(right) == AOP_LIT)
9289 size = AOP_SIZE(right);
9290 ressize = getSize(OP_SYM_ETYPE(result));
9291 if (size > ressize) size = ressize;
9292 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9294 //assert( !"what's going on here?" );
9297 if ( AOP_TYPE(result) == AOP_PCODE) {
9298 fprintf(stderr,"genDataPointerSet %s, %d\n",
9299 AOP(result)->aopu.pcop->name,
9300 PCOI(AOP(result)->aopu.pcop)->offset);
9304 // tsd, was l+1 - the underline `_' prefix was being stripped
9306 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9308 if (AOP_TYPE(right) == AOP_LIT) {
9309 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9310 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9312 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9313 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9315 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9318 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9319 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9320 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9326 freeAsmop(right,NULL,ic,TRUE);
9327 freeAsmop(result,NULL,ic,TRUE);
9330 /*-----------------------------------------------------------------*/
9331 /* genNearPointerSet - pic14_emitcode for near pointer put */
9332 /*-----------------------------------------------------------------*/
9333 static void genNearPointerSet (operand *right,
9338 sym_link *ptype = operandType(result);
9339 sym_link *retype = getSpec(operandType(right));
9340 sym_link *letype = getSpec(ptype);
9345 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9346 aopOp(result,ic,FALSE);
9349 /* if the result is rematerializable &
9350 in data space & not a bit variable */
9351 //if (AOP_TYPE(result) == AOP_IMMD &&
9352 if (AOP_TYPE(result) == AOP_PCODE &&
9353 PIC_IS_DATA_PTR(ptype) &&
9354 !IS_BITVAR (retype) &&
9355 !IS_BITVAR (letype)) {
9356 genDataPointerSet (right,result,ic);
9357 freeAsmop(result,NULL,ic,TRUE);
9362 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9363 aopOp(right,ic,FALSE);
9364 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9366 /* Check if can access directly instead of via a pointer */
9367 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9371 if (IS_BITFIELD (letype))
9373 genPackBits (letype, result, right, direct?-1:POINTER);
9377 /* If the pointer value is not in a the FSR then need to put it in */
9378 /* Must set/reset IRP bit for use with FSR. */
9379 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9384 /* we have can just get the values */
9385 int size = AOP_SIZE(right);
9388 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9390 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9392 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9394 if (AOP_TYPE(right) == AOP_LIT) {
9395 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9397 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9400 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9402 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9404 if (size && !direct)
9405 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9411 /* now some housekeeping stuff */
9413 /* we had to allocate for this iCode */
9414 freeAsmop(NULL,aop,ic,TRUE);
9416 /* we did not allocate which means left
9417 already in a pointer register, then
9418 if size > 0 && this could be used again
9419 we have to point it back to where it
9421 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9422 if (AOP_SIZE(right) > 1 &&
9423 !OP_SYMBOL(result)->remat &&
9424 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9426 int size = AOP_SIZE(right) - 1;
9428 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9432 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9435 freeAsmop(right,NULL,ic,TRUE);
9436 freeAsmop(result,NULL,ic,TRUE);
9440 /*-----------------------------------------------------------------*/
9441 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9442 /*-----------------------------------------------------------------*/
9443 static void genPagedPointerSet (operand *right,
9453 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9455 retype= getSpec(operandType(right));
9457 aopOp(result,ic,FALSE);
9459 /* if the value is already in a pointer register
9460 then don't need anything more */
9461 if (!AOP_INPREG(AOP(result))) {
9462 /* otherwise get a free pointer register */
9464 preg = getFreePtr(ic,&aop,FALSE);
9465 pic14_emitcode("mov","%s,%s",
9467 aopGet(AOP(result),0,FALSE,TRUE));
9468 rname = preg->name ;
9470 rname = aopGet(AOP(result),0,FALSE,FALSE);
9472 freeAsmop(result,NULL,ic,TRUE);
9473 aopOp (right,ic,FALSE);
9475 /* if bitfield then unpack the bits */
9476 if (IS_BITFIELD(retype))
9477 genPackBits (retype,result,right,rname,PPOINTER);
9479 /* we have can just get the values */
9480 int size = AOP_SIZE(right);
9484 l = aopGet(AOP(right),offset,FALSE,TRUE);
9487 pic14_emitcode("movx","@%s,a",rname);
9490 pic14_emitcode("inc","%s",rname);
9496 /* now some housekeeping stuff */
9498 /* we had to allocate for this iCode */
9499 freeAsmop(NULL,aop,ic,TRUE);
9501 /* we did not allocate which means left
9502 already in a pointer register, then
9503 if size > 0 && this could be used again
9504 we have to point it back to where it
9506 if (AOP_SIZE(right) > 1 &&
9507 !OP_SYMBOL(result)->remat &&
9508 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9510 int size = AOP_SIZE(right) - 1;
9512 pic14_emitcode("dec","%s",rname);
9517 freeAsmop(right,NULL,ic,TRUE);
9522 /*-----------------------------------------------------------------*/
9523 /* genFarPointerSet - set value from far space */
9524 /*-----------------------------------------------------------------*/
9525 static void genFarPointerSet (operand *right,
9526 operand *result, iCode *ic)
9529 sym_link *retype = getSpec(operandType(right));
9532 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 aopOp(result,ic,FALSE);
9535 /* if the operand is already in dptr
9536 then we do nothing else we move the value to dptr */
9537 if (AOP_TYPE(result) != AOP_STR) {
9538 /* if this is remateriazable */
9539 if (AOP_TYPE(result) == AOP_IMMD)
9540 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9541 else { /* we need to get it byte by byte */
9542 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9543 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9544 if (options.model == MODEL_FLAT24)
9546 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9550 /* so dptr know contains the address */
9551 freeAsmop(result,NULL,ic,TRUE);
9552 aopOp(right,ic,FALSE);
9554 /* if bit then unpack */
9555 if (IS_BITFIELD(retype))
9556 genPackBits(retype,result,right,"dptr",FPOINTER);
9558 size = AOP_SIZE(right);
9562 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9564 pic14_emitcode("movx","@dptr,a");
9566 pic14_emitcode("inc","dptr");
9570 freeAsmop(right,NULL,ic,TRUE);
9574 /*-----------------------------------------------------------------*/
9575 /* genGenPointerSet - set value from generic pointer space */
9576 /*-----------------------------------------------------------------*/
9577 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9579 sym_link *retype = getSpec(operandType(result));
9582 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9583 aopOp(right,ic,FALSE);
9584 aopOp(result,ic,FALSE);
9587 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9589 if (IS_BITFIELD(retype))
9591 genPackBits (retype, result, right, GPOINTER);
9596 /* emit call to __gptrput */
9597 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9598 int size = AOP_SIZE(right);
9601 /* The following assertion fails for
9602 * struct foo { char a; char b; } bar;
9603 * void demo(struct foo *dst, char c) { dst->b = c; }
9604 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9605 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9607 * The frontend seems to guarantee that IC_LEFT has the correct size,
9608 * it works fine both for larger and smaller types of `char c'.
9610 //assert (size == getSize(OP_SYM_ETYPE(result)));
9611 assert (size > 0 && size <= 4);
9613 /* pass arguments */
9614 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9620 mov2w_op (right, off);
9621 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9626 assert (AOP_SIZE(result) == 3);
9627 mov2w(AOP(result), 0);
9628 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9629 mov2w(AOP(result), 1);
9630 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9631 mov2w(AOP(result), 2);
9632 call_libraryfunc (func[size]);
9635 freeAsmop(right,NULL,ic,TRUE);
9636 freeAsmop(result,NULL,ic,TRUE);
9639 /*-----------------------------------------------------------------*/
9640 /* genPointerSet - stores the value into a pointer location */
9641 /*-----------------------------------------------------------------*/
9642 static void genPointerSet (iCode *ic)
9644 operand *right, *result ;
9645 sym_link *type, *etype;
9649 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9651 right = IC_RIGHT(ic);
9652 result = IC_RESULT(ic) ;
9654 /* depending on the type of pointer we need to
9655 move it to the correct pointer register */
9656 type = operandType(result);
9657 etype = getSpec(type);
9658 /* if left is of type of pointer then it is simple */
9659 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9660 p_type = DCL_TYPE(type);
9663 /* we have to go by the storage class */
9664 p_type = PTR_TYPE(SPEC_OCLS(etype));
9666 /* if (SPEC_OCLS(etype)->codesp ) { */
9667 /* p_type = CPOINTER ; */
9670 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9671 /* p_type = FPOINTER ; */
9673 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9674 /* p_type = PPOINTER ; */
9676 /* if (SPEC_OCLS(etype) == idata ) */
9677 /* p_type = IPOINTER ; */
9679 /* p_type = POINTER ; */
9682 /* now that we have the pointer type we assign
9683 the pointer values */
9689 genNearPointerSet (right,result,ic);
9693 genPagedPointerSet (right,result,ic);
9697 genFarPointerSet (right,result,ic);
9701 genGenPointerSet (right,result,ic);
9705 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9706 "genPointerSet: illegal pointer type");
9710 /*-----------------------------------------------------------------*/
9711 /* genIfx - generate code for Ifx statement */
9712 /*-----------------------------------------------------------------*/
9713 static void genIfx (iCode *ic, iCode *popIc)
9715 operand *cond = IC_COND(ic);
9719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9721 aopOp(cond,ic,FALSE);
9723 /* get the value into acc */
9724 if (AOP_TYPE(cond) != AOP_CRY)
9725 pic14_toBoolean(cond);
9729 /* if there was something to be popped then do it */
9735 /* This assumes that CARRY is set iff cond is true */
9738 assert (!IC_FALSE(ic));
9739 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9741 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9743 assert (IC_FALSE(ic));
9744 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9746 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9750 static int hasWarned = 0;
9753 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9760 /* now Z is set iff !cond */
9763 assert (!IC_FALSE(ic));
9765 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9768 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9774 /* the result is now in the accumulator */
9775 freeAsmop(cond,NULL,ic,TRUE);
9778 /*-----------------------------------------------------------------*/
9779 /* genAddrOf - generates code for address of */
9780 /*-----------------------------------------------------------------*/
9781 static void genAddrOf (iCode *ic)
9783 operand *right, *result, *left;
9787 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9790 //aopOp(IC_RESULT(ic),ic,FALSE);
9792 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9793 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9794 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9796 DEBUGpic14_AopType(__LINE__,left,right,result);
9797 assert (IS_SYMOP (left));
9799 /* sanity check: generic pointers to code space are not yet supported,
9800 * pionters to codespace must not be assigned addresses of __data values. */
9802 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9803 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)));
9804 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)));
9805 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)));
9806 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)));
9809 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9810 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9811 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9812 OP_SYMBOL(left)->name);
9813 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9814 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9815 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9816 OP_SYMBOL(left)->name);
9819 size = AOP_SIZE(IC_RESULT(ic));
9820 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9822 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9827 /* fixing bug #863624, reported from (errolv) */
9828 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9829 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9832 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9833 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9838 if (IS_GENPTR(OP_SYM_TYPE(result)))
9840 /* provide correct tag */
9841 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9842 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9843 movwf (AOP(result), 2);
9846 freeAsmop(left,NULL,ic,FALSE);
9847 freeAsmop(result,NULL,ic,TRUE);
9852 /*-----------------------------------------------------------------*/
9853 /* genFarFarAssign - assignment when both are in far space */
9854 /*-----------------------------------------------------------------*/
9855 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9857 int size = AOP_SIZE(right);
9860 /* first push the right side on to the stack */
9862 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9864 pic14_emitcode ("push","acc");
9867 freeAsmop(right,NULL,ic,FALSE);
9868 /* now assign DPTR to result */
9869 aopOp(result,ic,FALSE);
9870 size = AOP_SIZE(result);
9872 pic14_emitcode ("pop","acc");
9873 aopPut(AOP(result),"a",--offset);
9875 freeAsmop(result,NULL,ic,FALSE);
9880 /*-----------------------------------------------------------------*/
9881 /* genAssign - generate code for assignment */
9882 /*-----------------------------------------------------------------*/
9883 static void genAssign (iCode *ic)
9885 operand *result, *right;
9886 int size, offset,know_W;
9887 unsigned long lit = 0L;
9889 result = IC_RESULT(ic);
9890 right = IC_RIGHT(ic) ;
9893 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9895 /* if they are the same */
9896 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9899 aopOp(right,ic,FALSE);
9900 aopOp(result,ic,TRUE);
9902 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9904 /* if they are the same registers */
9905 if (pic14_sameRegs(AOP(right),AOP(result)))
9908 /* special case: assign from __code */
9909 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9910 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9911 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9912 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9913 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9915 emitpComment ("genAssign from CODESPACE");
9916 genConstPointerGet (right, result, ic);
9920 /* just for symmetry reasons... */
9921 if (!IS_ITEMP(result)
9922 && IS_SYMOP (result)
9923 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9925 assert ( !"cannot write to CODESPACE" );
9928 /* if the result is a bit */
9929 if (AOP_TYPE(result) == AOP_CRY) {
9931 /* if the right size is a literal then
9932 we know what the value is */
9933 if (AOP_TYPE(right) == AOP_LIT) {
9935 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9936 popGet(AOP(result),0));
9938 if (((int) operandLitValue(right)))
9939 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9940 AOP(result)->aopu.aop_dir,
9941 AOP(result)->aopu.aop_dir);
9943 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9944 AOP(result)->aopu.aop_dir,
9945 AOP(result)->aopu.aop_dir);
9949 /* the right is also a bit variable */
9950 if (AOP_TYPE(right) == AOP_CRY) {
9951 emitpcode(POC_BCF, popGet(AOP(result),0));
9952 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9953 emitpcode(POC_BSF, popGet(AOP(result),0));
9955 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9956 AOP(result)->aopu.aop_dir,
9957 AOP(result)->aopu.aop_dir);
9958 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9959 AOP(right)->aopu.aop_dir,
9960 AOP(right)->aopu.aop_dir);
9961 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9962 AOP(result)->aopu.aop_dir,
9963 AOP(result)->aopu.aop_dir);
9968 emitpcode(POC_BCF, popGet(AOP(result),0));
9969 pic14_toBoolean(right);
9971 emitpcode(POC_BSF, popGet(AOP(result),0));
9972 //aopPut(AOP(result),"a",0);
9976 /* bit variables done */
9978 size = AOP_SIZE(result);
9980 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9981 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9982 if(aopIdx(AOP(result),0) == 4) {
9983 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9984 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9985 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9988 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9994 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9995 if(AOP_TYPE(right) == AOP_LIT) {
9996 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
9998 if(know_W != (int)(lit&0xff))
9999 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10001 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10003 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10005 } else if (AOP_TYPE(right) == AOP_CRY) {
10006 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10008 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10009 emitpcode(POC_INCF, popGet(AOP(result),0));
10012 mov2w_op (right, offset);
10013 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10021 freeAsmop (right,NULL,ic,FALSE);
10022 freeAsmop (result,NULL,ic,TRUE);
10025 /*-----------------------------------------------------------------*/
10026 /* genJumpTab - genrates code for jump table */
10027 /*-----------------------------------------------------------------*/
10028 static void genJumpTab (iCode *ic)
10034 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10036 aopOp(IC_JTCOND(ic),ic,FALSE);
10037 /* get the condition into accumulator */
10038 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10040 /* multiply by three */
10041 pic14_emitcode("add","a,acc");
10042 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10044 jtab = newiTempLabel(NULL);
10045 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10046 pic14_emitcode("jmp","@a+dptr");
10047 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10049 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10050 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10051 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10052 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10054 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10055 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10056 emitpLabel(jtab->key);
10058 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10060 /* now generate the jump labels */
10061 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10062 jtab = setNextItem(IC_JTLABELS(ic))) {
10063 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10064 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10070 /*-----------------------------------------------------------------*/
10071 /* genMixedOperation - gen code for operators between mixed types */
10072 /*-----------------------------------------------------------------*/
10074 TSD - Written for the PIC port - but this unfortunately is buggy.
10075 This routine is good in that it is able to efficiently promote
10076 types to different (larger) sizes. Unfortunately, the temporary
10077 variables that are optimized out by this routine are sometimes
10078 used in other places. So until I know how to really parse the
10079 iCode tree, I'm going to not be using this routine :(.
10081 static int genMixedOperation (iCode *ic)
10085 operand *result = IC_RESULT(ic);
10086 sym_link *ctype = operandType(IC_LEFT(ic));
10087 operand *right = IC_RIGHT(ic);
10093 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10095 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10101 nextright = IC_RIGHT(nextic);
10102 nextleft = IC_LEFT(nextic);
10103 nextresult = IC_RESULT(nextic);
10105 aopOp(right,ic,FALSE);
10106 aopOp(result,ic,FALSE);
10107 aopOp(nextright, nextic, FALSE);
10108 aopOp(nextleft, nextic, FALSE);
10109 aopOp(nextresult, nextic, FALSE);
10111 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10113 operand *t = right;
10117 pic14_emitcode(";remove right +","");
10119 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10121 operand *t = right;
10125 pic14_emitcode(";remove left +","");
10129 big = AOP_SIZE(nextleft);
10130 small = AOP_SIZE(nextright);
10132 switch(nextic->op) {
10135 pic14_emitcode(";optimize a +","");
10136 /* if unsigned or not an integral type */
10137 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10138 pic14_emitcode(";add a bit to something","");
10141 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10143 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10144 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10145 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10147 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10155 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10156 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10157 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10160 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10162 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10163 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10164 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10165 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10166 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10169 pic14_emitcode("rlf","known_zero,w");
10176 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10177 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10178 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10180 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10190 freeAsmop(right,NULL,ic,TRUE);
10191 freeAsmop(result,NULL,ic,TRUE);
10192 freeAsmop(nextright,NULL,ic,TRUE);
10193 freeAsmop(nextleft,NULL,ic,TRUE);
10195 nextic->generated = 1;
10202 /*-----------------------------------------------------------------*/
10203 /* genCast - gen code for casting */
10204 /*-----------------------------------------------------------------*/
10205 static void genCast (iCode *ic)
10207 operand *result = IC_RESULT(ic);
10208 sym_link *restype = operandType(result);
10209 sym_link *rtype = operandType(IC_RIGHT(ic));
10210 operand *right = IC_RIGHT(ic);
10214 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10215 /* if they are equivalent then do nothing */
10216 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10219 aopOp(right,ic,FALSE) ;
10220 aopOp(result,ic,FALSE);
10222 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10224 /* if the result is a bit */
10225 if (AOP_TYPE(result) == AOP_CRY) {
10226 assert(!"assigning to bit variables is not supported");
10229 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10231 size = AOP_SIZE(result);
10233 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10235 emitpcode(POC_CLRF, popGet(AOP(result),0));
10236 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10237 emitpcode(POC_INCF, popGet(AOP(result),0));
10240 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10245 if (IS_PTR(restype))
10247 operand *result = IC_RESULT(ic);
10248 //operand *left = IC_LEFT(ic);
10249 operand *right = IC_RIGHT(ic);
10252 /* copy common part */
10253 int max, size = AOP_SIZE(result);
10254 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10255 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10257 /* warn if we discard generic opinter tag */
10258 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10260 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10266 mov2w_op (right, size);
10267 movwf (AOP(result), size);
10270 /* upcast into generic pointer type? */
10271 if (IS_GENPTR(restype)
10272 && (size < AOP_SIZE(result))
10273 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10275 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10278 switch (DCL_TYPE(rtype))
10280 case POINTER: /* __data */
10281 case FPOINTER: /* __data */
10282 assert (AOP_SIZE(right) == 2);
10283 tag = GPTRTAG_DATA;
10286 case CPOINTER: /* __code */
10287 assert (AOP_SIZE(right) == 2);
10288 tag = GPTRTAG_CODE;
10291 case GPOINTER: /* unknown destination, __data or __code */
10292 /* assume __data space (address of immediate) */
10293 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10294 if (AOP(right)->code)
10295 tag = GPTRTAG_CODE;
10297 tag = GPTRTAG_DATA;
10301 assert (!"unhandled pointer type");
10304 /* convert other values into pointers to __data space */
10305 tag = GPTRTAG_DATA;
10308 assert (AOP_SIZE(result) == 3);
10310 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10312 emitpcode(POC_MOVLW, popGetLit(tag));
10313 movwf(AOP(result), 2);
10316 addSign(result, max, 0);
10321 /* if they are the same size : or less */
10322 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10324 /* if they are in the same place */
10325 if (pic14_sameRegs(AOP(right),AOP(result)))
10328 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10329 if (IS_PTR_CONST(rtype))
10330 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10331 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10332 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10334 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10335 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10336 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10337 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10338 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10339 if(AOP_SIZE(result) <2)
10340 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10344 /* if they in different places then copy */
10345 size = AOP_SIZE(result);
10348 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10349 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10351 //aopPut(AOP(result),
10352 // aopGet(AOP(right),offset,FALSE,FALSE),
10361 /* so we now know that the size of destination is greater
10362 than the size of the source.
10363 Now, if the next iCode is an operator then we might be
10364 able to optimize the operation without performing a cast.
10366 if(0 && genMixedOperation(ic)) {
10367 /* XXX: cannot optimize: must copy regs! */
10371 /* we move to result for the size of source */
10372 size = AOP_SIZE(right);
10375 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10376 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10380 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10383 freeAsmop(right,NULL,ic,TRUE);
10384 freeAsmop(result,NULL,ic,TRUE);
10388 /*-----------------------------------------------------------------*/
10389 /* genDjnz - generate decrement & jump if not zero instrucion */
10390 /*-----------------------------------------------------------------*/
10391 static int genDjnz (iCode *ic, iCode *ifx)
10393 symbol *lbl, *lbl1;
10395 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10400 /* if the if condition has a false label
10401 then we cannot save */
10405 /* if the minus is not of the form
10407 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10408 !IS_OP_LITERAL(IC_RIGHT(ic)))
10411 if (operandLitValue(IC_RIGHT(ic)) != 1)
10414 /* if the size of this greater than one then no
10416 if (getSize(operandType(IC_RESULT(ic))) > 1)
10419 /* otherwise we can save BIG */
10420 lbl = newiTempLabel(NULL);
10421 lbl1= newiTempLabel(NULL);
10423 aopOp(IC_RESULT(ic),ic,FALSE);
10425 if (IS_AOP_PREG(IC_RESULT(ic))) {
10426 pic14_emitcode("dec","%s",
10427 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10428 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10429 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10433 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10434 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10436 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10437 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10440 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10441 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10442 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10443 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10446 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10447 ifx->generated = 1;
10451 /*-----------------------------------------------------------------*/
10452 /* genReceive - generate code for a receive iCode */
10453 /*-----------------------------------------------------------------*/
10454 static void genReceive (iCode *ic)
10457 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10459 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10460 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10461 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10463 int size = getSize(operandType(IC_RESULT(ic)));
10464 int offset = fReturnSizePic - size;
10466 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10467 fReturn[fReturnSizePic - offset - 1] : "acc"));
10470 aopOp(IC_RESULT(ic),ic,FALSE);
10471 size = AOP_SIZE(IC_RESULT(ic));
10474 pic14_emitcode ("pop","acc");
10475 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10480 aopOp(IC_RESULT(ic),ic,FALSE);
10482 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10483 assignResultValue(IC_RESULT(ic));
10486 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10489 /*-----------------------------------------------------------------*/
10490 /* genDummyRead - generate code for dummy read of volatiles */
10491 /*-----------------------------------------------------------------*/
10493 genDummyRead (iCode * ic)
10496 pic14_emitcode ("; genDummyRead","");
10497 pic14_emitcode ("; not implemented","");
10502 /*-----------------------------------------------------------------*/
10503 /* genpic14Code - generate code for pic14 based controllers */
10504 /*-----------------------------------------------------------------*/
10506 * At this point, ralloc.c has gone through the iCode and attempted
10507 * to optimize in a way suitable for a PIC. Now we've got to generate
10508 * PIC instructions that correspond to the iCode.
10510 * Once the instructions are generated, we'll pass through both the
10511 * peep hole optimizer and the pCode optimizer.
10512 *-----------------------------------------------------------------*/
10514 void genpic14Code (iCode *lic)
10521 lineHead = lineCurr = NULL;
10523 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10526 /* if debug information required */
10527 if (options.debug && debugFile && currFunc) {
10528 debugFile->writeFunction (currFunc, lic);
10532 for (ic = lic ; ic ; ic = ic->next ) {
10534 //DEBUGpic14_emitcode(";ic","");
10535 //fprintf (stderr, "in ic loop\n");
10536 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10537 //ic->lineno, printCLine(ic->filename, ic->lineno));
10539 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10541 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10542 cline = printCLine (ic->filename, ic->lineno);
10543 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10544 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10545 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10548 if (options.iCodeInAsm) {
10549 char *iLine = printILine(ic);
10550 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10553 /* if the result is marked as
10554 spilt and rematerializable or code for
10555 this has already been generated then
10557 if (resultRemat(ic) || ic->generated )
10560 /* depending on the operation */
10579 /* IPOP happens only when trying to restore a
10580 spilt live range, if there is an ifx statement
10581 following this pop then the if statement might
10582 be using some of the registers being popped which
10583 would destory the contents of the register so
10584 we need to check for this condition and handle it */
10586 ic->next->op == IFX &&
10587 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10588 genIfx (ic->next,ic);
10606 genEndFunction (ic);
10626 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10643 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10647 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10654 /* note these two are xlated by algebraic equivalence
10655 during parsing SDCC.y */
10656 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10657 "got '>=' or '<=' shouldn't have come here");
10661 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10673 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10677 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10681 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10705 genRightShift (ic);
10708 case GET_VALUE_AT_ADDRESS:
10713 if (POINTER_SET(ic))
10740 addSet(&_G.sendSet,ic);
10743 case DUMMY_READ_VOLATILE:
10748 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10755 /* now we are ready to call the
10756 peep hole optimizer */
10757 if (!options.nopeep) {
10758 peepHole (&lineHead);
10760 /* now do the actual printing */
10761 printLine (lineHead,codeOutBuf);
10764 DFPRINTF((stderr,"printing pBlock\n\n"));
10765 printpBlock(stdout,pb);
10771 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10772 * (meaning: representing its own address) or not (referencing its contents).
10773 * This can only be decided based on the operand's type. */
10775 aop_isLitLike (asmop *aop)
10778 if (aop->type == AOP_LIT) return 1;
10779 if (aop->type == AOP_IMMD) return 1;
10780 if ((aop->type == AOP_PCODE) &&
10781 ((aop->aopu.pcop->type == PO_LITERAL)))
10783 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10784 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10791 op_isLitLike (operand *op)
10794 if (aop_isLitLike (AOP(op))) return 1;
10795 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10796 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;