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;
6218 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6220 _G.inLine += (!options.asmpeep);
6222 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6223 strcpy(buffer,IC_INLINE(ic));
6225 /* emit each line as a code */
6231 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6239 /* print label, use this special format with NULL directive
6240 * to denote that the argument should not be indented with tab */
6241 addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6248 if ((bp1 != bp) && *bp1)
6249 addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6253 _G.inLine -= (!options.asmpeep);
6256 /*-----------------------------------------------------------------*/
6257 /* genRRC - rotate right with carry */
6258 /*-----------------------------------------------------------------*/
6259 static void genRRC (iCode *ic)
6261 operand *left , *result ;
6262 int size, offset = 0, same;
6265 /* rotate right with carry */
6267 result=IC_RESULT(ic);
6268 aopOp (left,ic,FALSE);
6269 aopOp (result,ic,FALSE);
6271 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6273 same = pic14_sameRegs(AOP(result),AOP(left));
6275 size = AOP_SIZE(result);
6277 /* get the lsb and put it into the carry */
6278 emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6285 emitpcode(POC_RRF, popGet(AOP(left),offset));
6287 emitpcode(POC_RRFW, popGet(AOP(left),offset));
6288 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6294 freeAsmop(left,NULL,ic,TRUE);
6295 freeAsmop(result,NULL,ic,TRUE);
6298 /*-----------------------------------------------------------------*/
6299 /* genRLC - generate code for rotate left with carry */
6300 /*-----------------------------------------------------------------*/
6301 static void genRLC (iCode *ic)
6303 operand *left , *result ;
6304 int size, offset = 0;
6308 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6309 /* rotate right with carry */
6311 result=IC_RESULT(ic);
6312 aopOp (left,ic,FALSE);
6313 aopOp (result,ic,FALSE);
6315 DEBUGpic14_AopType(__LINE__,left,NULL,result);
6317 same = pic14_sameRegs(AOP(result),AOP(left));
6319 /* move it to the result */
6320 size = AOP_SIZE(result);
6322 /* get the msb and put it into the carry */
6323 emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6330 emitpcode(POC_RLF, popGet(AOP(left),offset));
6332 emitpcode(POC_RLFW, popGet(AOP(left),offset));
6333 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6340 freeAsmop(left,NULL,ic,TRUE);
6341 freeAsmop(result,NULL,ic,TRUE);
6344 /*-----------------------------------------------------------------*/
6345 /* genGetHbit - generates code get highest order bit */
6346 /*-----------------------------------------------------------------*/
6347 static void genGetHbit (iCode *ic)
6349 operand *left, *result;
6351 result=IC_RESULT(ic);
6352 aopOp (left,ic,FALSE);
6353 aopOp (result,ic,FALSE);
6356 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6357 /* get the highest order byte into a */
6358 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6359 if(AOP_TYPE(result) == AOP_CRY){
6360 pic14_emitcode("rlc","a");
6361 pic14_outBitC(result);
6364 pic14_emitcode("rl","a");
6365 pic14_emitcode("anl","a,#0x01");
6366 pic14_outAcc(result);
6370 freeAsmop(left,NULL,ic,TRUE);
6371 freeAsmop(result,NULL,ic,TRUE);
6374 /*-----------------------------------------------------------------*/
6375 /* AccLsh - shift left accumulator by known count */
6376 /* MARK: pic14 always rotates through CARRY! */
6377 /*-----------------------------------------------------------------*/
6378 static void AccLsh (pCodeOp *pcop,int shCount)
6381 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6382 shCount &= 0x0007; // shCount : 0..7
6389 emitpcode(POC_RLF,pcop);
6393 emitpcode(POC_RLF,pcop);
6394 emitpcode(POC_RLF,pcop);
6397 emitpcode(POC_RLF,pcop);
6398 emitpcode(POC_RLF,pcop);
6399 emitpcode(POC_RLF,pcop);
6402 emitpcode(POC_SWAPF,pcop);
6405 emitpcode(POC_SWAPF,pcop);
6406 emitpcode(POC_RLF,pcop);
6409 emitpcode(POC_SWAPF,pcop);
6410 emitpcode(POC_RLF,pcop);
6411 emitpcode(POC_RLF,pcop);
6414 emitpcode(POC_RRFW,pcop);
6415 emitpcode(POC_RRF,pcop);
6418 /* clear invalid bits */
6419 emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6420 emitpcode(POC_ANDWF, pcop);
6423 /*-----------------------------------------------------------------*/
6424 /* AccRsh - shift right accumulator by known count */
6425 /* MARK: pic14 always rotates through CARRY! */
6426 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6427 /* 1: mask out invalid bits (zero-extend) */
6428 /* 2: sign-extend result (pretty slow) */
6429 /*-----------------------------------------------------------------*/
6430 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6433 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6434 shCount &= 0x0007; // shCount : 0..7
6440 /* load sign if needed */
6441 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6442 else if (mask_mode == 1) emitCLRC;
6443 emitpcode(POC_RRF,pcop);
6447 /* load sign if needed */
6448 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6449 emitpcode(POC_RRF,pcop);
6450 /* load sign if needed */
6451 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6452 emitpcode(POC_RRF,pcop);
6453 if (mask_mode == 2) return;
6456 /* load sign if needed */
6457 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6458 emitpcode(POC_RRF,pcop);
6459 /* load sign if needed */
6460 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6461 emitpcode(POC_RRF,pcop);
6462 /* load sign if needed */
6463 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6464 emitpcode(POC_RRF,pcop);
6465 if (mask_mode == 2) return;
6468 emitpcode(POC_SWAPF,pcop);
6471 emitpcode(POC_SWAPF,pcop);
6472 emitpcode(POC_RRF,pcop);
6475 emitpcode(POC_SWAPF,pcop);
6476 emitpcode(POC_RRF,pcop);
6477 emitpcode(POC_RRF,pcop);
6483 emitpcode(POC_RLFW,pcop);
6484 emitpcode(POC_CLRF,pcop);
6486 emitpcode(POC_COMF,pcop);
6489 emitpcode(POC_RLFW,pcop);
6490 emitpcode(POC_RLF,pcop);
6497 /* leave invalid bits undefined */
6501 /* clear invalid bits -- zero-extend */
6502 emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6503 emitpcode(POC_ANDWF, pcop);
6505 if (mask_mode == 2) {
6507 emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6508 emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6509 emitpcode(POC_IORWF, pcop);
6514 /*-----------------------------------------------------------------*/
6515 /* AccSRsh - signed right shift accumulator by known count */
6516 /*-----------------------------------------------------------------*/
6517 static void AccSRsh (int shCount)
6520 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6523 pic14_emitcode("mov","c,acc.7");
6524 pic14_emitcode("rrc","a");
6525 } else if(shCount == 2){
6526 pic14_emitcode("mov","c,acc.7");
6527 pic14_emitcode("rrc","a");
6528 pic14_emitcode("mov","c,acc.7");
6529 pic14_emitcode("rrc","a");
6531 tlbl = newiTempLabel(NULL);
6532 /* rotate right accumulator */
6533 AccRol(8 - shCount);
6534 /* and kill the higher order bits */
6535 pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6536 pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6537 pic14_emitcode("orl","a,#0x%02x",
6538 (unsigned char)~SRMask[shCount]);
6539 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6544 /*-----------------------------------------------------------------*/
6545 /* shiftR1Left2Result - shift right one byte from left to result */
6546 /*-----------------------------------------------------------------*/
6547 static void shiftR1Left2ResultSigned (operand *left, int offl,
6548 operand *result, int offr,
6554 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6556 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6560 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6562 emitpcode(POC_RRF, popGet(AOP(result),offr));
6564 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6565 emitpcode(POC_MOVWF, popGet(AOP(result),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));
6578 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6579 emitpcode(POC_RRF, popGet(AOP(result),offr));
6585 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6587 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6588 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6591 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6592 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6593 emitpcode(POC_ANDLW, popGetLit(0x1f));
6595 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6596 emitpcode(POC_IORLW, popGetLit(0xe0));
6598 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6602 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6603 emitpcode(POC_ANDLW, popGetLit(0x0f));
6604 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6605 emitpcode(POC_IORLW, popGetLit(0xf0));
6606 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6610 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6612 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6613 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6615 emitpcode(POC_RRFW, popGet(AOP(result),offr));
6616 emitpcode(POC_ANDLW, popGetLit(0x07));
6617 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6618 emitpcode(POC_IORLW, popGetLit(0xf8));
6619 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6624 emitpcode(POC_MOVLW, popGetLit(0x00));
6625 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6626 emitpcode(POC_MOVLW, popGetLit(0xfe));
6627 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6628 emitpcode(POC_IORLW, popGetLit(0x01));
6629 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6631 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6632 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6633 emitpcode(POC_DECF, popGet(AOP(result),offr));
6634 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6635 emitpcode(POC_BCF, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6641 emitpcode(POC_MOVLW, popGetLit(0x00));
6642 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6643 emitpcode(POC_MOVLW, popGetLit(0xff));
6644 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6646 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6647 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6648 emitpcode(POC_DECF, popGet(AOP(result),offr));
6656 /*-----------------------------------------------------------------*/
6657 /* shiftR1Left2Result - shift right one byte from left to result */
6658 /*-----------------------------------------------------------------*/
6659 static void shiftR1Left2Result (operand *left, int offl,
6660 operand *result, int offr,
6661 int shCount, int sign)
6666 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6668 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6670 /* Copy the msb into the carry if signed. */
6672 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6682 emitpcode(POC_RRF, popGet(AOP(result),offr));
6684 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6685 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6691 emitpcode(POC_RRF, popGet(AOP(result),offr));
6693 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6694 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6697 emitpcode(POC_RRF, popGet(AOP(result),offr));
6702 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6704 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6705 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6708 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6709 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6710 emitpcode(POC_ANDLW, popGetLit(0x1f));
6711 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6715 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6716 emitpcode(POC_ANDLW, popGetLit(0x0f));
6717 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6721 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6722 emitpcode(POC_ANDLW, popGetLit(0x0f));
6723 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6725 emitpcode(POC_RRF, popGet(AOP(result),offr));
6730 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6731 emitpcode(POC_ANDLW, popGetLit(0x80));
6732 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6733 emitpcode(POC_RLF, popGet(AOP(result),offr));
6734 emitpcode(POC_RLF, popGet(AOP(result),offr));
6739 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6740 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6741 emitpcode(POC_RLF, popGet(AOP(result),offr));
6750 /*-----------------------------------------------------------------*/
6751 /* shiftL1Left2Result - shift left one byte from left to result */
6752 /*-----------------------------------------------------------------*/
6753 static void shiftL1Left2Result (operand *left, int offl,
6754 operand *result, int offr, int shCount)
6760 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6762 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6763 DEBUGpic14_emitcode ("; ***","same = %d",same);
6764 // l = aopGet(AOP(left),offl,FALSE,FALSE);
6766 /* shift left accumulator */
6767 //AccLsh(shCount); // don't comment out just yet...
6768 // aopPut(AOP(result),"a",offr);
6772 /* Shift left 1 bit position */
6773 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6775 emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6777 emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6778 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6782 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6783 emitpcode(POC_ANDLW,popGetLit(0x7e));
6784 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6785 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6788 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6789 emitpcode(POC_ANDLW,popGetLit(0x3e));
6790 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6791 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6792 emitpcode(POC_RLF, popGet(AOP(result),offr));
6795 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6796 emitpcode(POC_ANDLW, popGetLit(0xf0));
6797 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6800 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6801 emitpcode(POC_ANDLW, popGetLit(0xf0));
6802 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6803 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6806 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6807 emitpcode(POC_ANDLW, popGetLit(0x30));
6808 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6809 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6810 emitpcode(POC_RLF, popGet(AOP(result),offr));
6813 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6814 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6815 emitpcode(POC_RRF, popGet(AOP(result),offr));
6819 DEBUGpic14_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6825 /*-----------------------------------------------------------------*/
6826 /* movLeft2Result - move byte from left to result */
6827 /*-----------------------------------------------------------------*/
6828 static void movLeft2Result (operand *left, int offl,
6829 operand *result, int offr)
6833 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6834 if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6835 l = aopGet(AOP(left),offl,FALSE,FALSE);
6837 if (*l == '@' && (IS_AOP_PREG(result))) {
6838 pic14_emitcode("mov","a,%s",l);
6839 aopPut(AOP(result),"a",offr);
6841 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6842 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6847 /*-----------------------------------------------------------------*/
6848 /* shiftLeft_Left2ResultLit - shift left by known count */
6849 /*-----------------------------------------------------------------*/
6851 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6853 int size, same, offr, i;
6855 size = AOP_SIZE(left);
6856 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6858 same = pic14_sameRegs (AOP(left), AOP(result));
6861 shCount = shCount & 0x07;
6867 case 0: /* takes 0 or 2N cycles (for offr==0) */
6868 if (!same || offr) {
6869 for (i=size-1; i >= 0; i--)
6870 movLeft2Result (left, i, result, offr + i);
6874 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6876 shiftLeft_Left2ResultLit (left, result, 8 * offr);
6877 shiftLeft_Left2ResultLit (result, result, shCount);
6878 return; /* prevent clearing result again */
6881 for (i=0; i < size; i++) {
6882 if (same && !offr) {
6883 emitpcode (POC_RLF, popGet (AOP(left), i));
6885 emitpcode (POC_RLFW, popGet (AOP(left), i));
6886 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6892 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6893 /* works in-place/with offr as well */
6894 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6895 emitpcode (POC_ANDLW, popGetLit (0xF0));
6896 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6898 for (i = size - 2; i >= 0; i--)
6900 emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6901 emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6902 emitpcode (POC_ANDLW, popGetLit (0x0F));
6903 emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6904 emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6908 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6909 /* works in-place/with offr as well */
6910 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6911 for (i = size-2; i >= 0; i--) {
6912 emitpcode (POC_RRFW, popGet (AOP(left), i));
6913 emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6915 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6916 emitpcode (POC_RRF, popGet (AOP(result), offr));
6920 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6921 shiftLeft_Left2ResultLit (result, result, 1);
6922 return; /* prevent clearing result again */
6928 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6932 /*-----------------------------------------------------------------*/
6933 /* shiftRight_Left2ResultLit - shift right by known count */
6934 /*-----------------------------------------------------------------*/
6936 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6938 int size, same, offr, i;
6940 size = AOP_SIZE(left);
6941 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6943 same = pic14_sameRegs (AOP(left), AOP(result));
6946 shCount = shCount & 0x07;
6954 case 0: /* takes 0 or 2N cycles (for offr==0) */
6955 if (!same || offr) {
6956 for (i=0; i < size; i++)
6957 movLeft2Result (left, i + offr, result, i);
6961 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6962 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6964 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6965 shiftRight_Left2ResultLit (result, result, shCount, sign);
6966 return; /* prevent sign-extending result again */
6970 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6973 for (i = size-1; i >= 0; i--) {
6974 if (same && !offr) {
6975 emitpcode (POC_RRF, popGet (AOP(left), i));
6977 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6978 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6984 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6985 /* works in-place/with offr as well */
6986 emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6987 emitpcode (POC_ANDLW, popGetLit (0x0F));
6988 emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6990 for (i = 1; i < size; i++)
6992 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6993 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6994 emitpcode (POC_ANDLW, popGetLit (0xF0));
6995 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6996 emitpcode (POC_XORWF, popGet (AOP(result), i));
7001 emitpcode (POC_MOVLW, popGetLit (0xF0));
7002 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7003 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7007 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7008 /* works in-place/with offr as well */
7009 emitpcode (POC_RLFW, popGet (AOP(left), offr));
7010 for (i = 0; i < size-1; i++) {
7011 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7012 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7014 emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7016 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7019 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7024 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7025 shiftRight_Left2ResultLit (result, result, 1, sign);
7026 return; /* prevent sign extending result again */
7031 addSign (result, size, sign);
7035 /*-----------------------------------------------------------------*/
7036 /* shiftL2Left2Result - shift left two bytes from left to result */
7037 /*-----------------------------------------------------------------*/
7038 static void shiftL2Left2Result (operand *left, int offl,
7039 operand *result, int offr, int shCount)
7043 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7045 if(pic14_sameRegs(AOP(result), AOP(left))) {
7053 emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7054 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7055 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7059 emitpcode(POC_RLF, popGet(AOP(result),offr));
7060 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7066 emitpcode(POC_MOVLW, popGetLit(0x0f));
7067 emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7068 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7069 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7070 emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7071 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7072 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7074 emitpcode(POC_RLF, popGet(AOP(result),offr));
7075 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7079 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7080 emitpcode(POC_RRF, popGet(AOP(result),offr));
7081 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7082 emitpcode(POC_RRF, popGet(AOP(result),offr));
7083 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7084 emitpcode(POC_ANDLW,popGetLit(0xc0));
7085 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7086 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7087 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7088 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7091 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7092 emitpcode(POC_RRFW, popGet(AOP(result),offr));
7093 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7094 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7095 emitpcode(POC_RRF, popGet(AOP(result),offr));
7105 /* note, use a mov/add for the shift since the mov has a
7106 chance of getting optimized out */
7107 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7108 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7109 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7110 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7111 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7115 emitpcode(POC_RLF, popGet(AOP(result),offr));
7116 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7122 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7123 emitpcode(POC_ANDLW, popGetLit(0xF0));
7124 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7125 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7126 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7127 emitpcode(POC_ANDLW, popGetLit(0xF0));
7128 emitpcode(POC_XORWF, popGet(AOP(result),offr));
7129 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7133 emitpcode(POC_RLF, popGet(AOP(result),offr));
7134 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7138 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7139 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7140 emitpcode(POC_RRFW, popGet(AOP(result),offl));
7141 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7143 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7144 emitpcode(POC_RRF, popGet(AOP(result),offr));
7145 emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7146 emitpcode(POC_ANDLW,popGetLit(0xc0));
7147 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7148 emitpcode(POC_XORWF,popGet(AOP(result),offr));
7149 emitpcode(POC_XORFW,popGet(AOP(result),offr));
7150 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7153 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7154 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7155 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7156 emitpcode(POC_CLRF, popGet(AOP(result),offr));
7157 emitpcode(POC_RRF, popGet(AOP(result),offr));
7163 /*-----------------------------------------------------------------*/
7164 /* shiftR2Left2Result - shift right two bytes from left to result */
7165 /*-----------------------------------------------------------------*/
7166 static void shiftR2Left2Result (operand *left, int offl,
7167 operand *result, int offr,
7168 int shCount, int sign)
7173 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7174 same = pic14_sameRegs(AOP(result), AOP(left));
7176 if(same && ((offl + MSB16) == offr)){
7178 /* don't crash result[offr] */
7179 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7180 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7183 movLeft2Result(left,offl, result, offr);
7184 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7187 /* a:x >> shCount (x = lsb(result))*/
7190 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7192 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7201 emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7206 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7207 emitpcode(POC_RRF,popGet(AOP(result),offr));
7209 emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7210 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7211 emitpcode(POC_RRFW, popGet(AOP(left),offl));
7212 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7217 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7220 emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7221 emitpcode(POC_RRF,popGet(AOP(result),offr));
7228 emitpcode(POC_MOVLW, popGetLit(0xf0));
7229 emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7230 emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7232 emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7233 emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7234 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7235 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7237 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7238 emitpcode(POC_ANDLW, popGetLit(0x0f));
7239 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7241 emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7242 emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7243 emitpcode(POC_ANDLW, popGetLit(0xf0));
7244 emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7245 emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7249 emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7250 emitpcode(POC_RRF, popGet(AOP(result),offr));
7254 emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7255 emitpcode(POC_BTFSC,
7256 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7257 emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7265 emitpcode(POC_RLF, popGet(AOP(result),offr));
7266 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7268 emitpcode(POC_RLF, popGet(AOP(result),offr));
7269 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7270 emitpcode(POC_RLFW, popGet(AOP(result),offr));
7271 emitpcode(POC_ANDLW,popGetLit(0x03));
7273 emitpcode(POC_BTFSC,
7274 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7275 emitpcode(POC_IORLW,popGetLit(0xfc));
7277 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7278 emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7279 emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7280 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7282 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7283 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7284 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7285 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7286 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7287 emitpcode(POC_RLF, popGet(AOP(result),offr));
7288 emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7289 emitpcode(POC_ANDLW,popGetLit(0x03));
7291 emitpcode(POC_BTFSC,
7292 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7293 emitpcode(POC_IORLW,popGetLit(0xfc));
7295 emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7296 //emitpcode(POC_RLF, popGet(AOP(result),offr));
7303 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7304 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7305 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7306 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7309 emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7311 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7315 /*-----------------------------------------------------------------*/
7316 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7317 /*-----------------------------------------------------------------*/
7318 static void shiftLLeftOrResult (operand *left, int offl,
7319 operand *result, int offr, int shCount)
7322 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7324 /* shift left accumulator */
7325 AccLsh(left,offl,shCount);
7326 /* or with result */
7327 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7328 assert ( !"broken (modifies left, fails for left==result))" );
7331 /*-----------------------------------------------------------------*/
7332 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7333 /*-----------------------------------------------------------------*/
7334 static void shiftRLeftOrResult (operand *left, int offl,
7335 operand *result, int offr, int shCount)
7338 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7340 /* shift right accumulator */
7341 AccRsh(left,offl,shCount);
7342 /* or with result */
7343 emitpcode (POC_IORWF, popGet (AOP(result), offr));
7344 assert ( !"broken (modifies left, fails for left==result))" );
7347 /*-----------------------------------------------------------------*/
7348 /* genlshOne - left shift a one byte quantity by known count */
7349 /*-----------------------------------------------------------------*/
7350 static void genlshOne (operand *result, operand *left, int shCount)
7353 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7354 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7357 /*-----------------------------------------------------------------*/
7358 /* genlshTwo - left shift two bytes by known amount != 0 */
7359 /*-----------------------------------------------------------------*/
7360 static void genlshTwo (operand *result,operand *left, int shCount)
7365 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7366 size = pic14_getDataSize(result);
7368 /* if shCount >= 8 */
7374 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7376 movLeft2Result(left, LSB, result, MSB16);
7378 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7381 /* 1 <= shCount <= 7 */
7384 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7386 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7390 /*-----------------------------------------------------------------*/
7391 /* shiftLLong - shift left one long from left to result */
7392 /* offl = LSB or MSB16 */
7393 /*-----------------------------------------------------------------*/
7394 static void shiftLLong (operand *left, operand *result, int offr )
7397 int size = AOP_SIZE(result);
7400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7401 if(size >= LSB+offr){
7402 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7404 pic14_emitcode("add","a,acc");
7405 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7406 size >= MSB16+offr && offr != LSB )
7407 pic14_emitcode("xch","a,%s",
7408 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7410 aopPut(AOP(result),"a",LSB+offr);
7413 if(size >= MSB16+offr){
7414 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7415 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7418 pic14_emitcode("rlc","a");
7419 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7420 size >= MSB24+offr && offr != LSB)
7421 pic14_emitcode("xch","a,%s",
7422 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7424 aopPut(AOP(result),"a",MSB16+offr);
7427 if(size >= MSB24+offr){
7428 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7429 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7432 pic14_emitcode("rlc","a");
7433 if (pic14_sameRegs(AOP(left),AOP(result)) &&
7434 size >= MSB32+offr && offr != LSB )
7435 pic14_emitcode("xch","a,%s",
7436 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7438 aopPut(AOP(result),"a",MSB24+offr);
7441 if(size > MSB32+offr){
7442 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7443 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7446 pic14_emitcode("rlc","a");
7447 aopPut(AOP(result),"a",MSB32+offr);
7450 aopPut(AOP(result),zero,LSB);
7453 /*-----------------------------------------------------------------*/
7454 /* genlshFour - shift four byte by a known amount != 0 */
7455 /*-----------------------------------------------------------------*/
7456 static void genlshFour (operand *result, operand *left, int shCount)
7461 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7462 size = AOP_SIZE(result);
7464 /* if shifting more that 3 bytes */
7465 if (shCount >= 24 ) {
7468 /* lowest order of left goes to the highest
7469 order of the destination */
7470 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7472 movLeft2Result(left, LSB, result, MSB32);
7473 aopPut(AOP(result),zero,LSB);
7474 aopPut(AOP(result),zero,MSB16);
7475 aopPut(AOP(result),zero,MSB32);
7479 /* more than two bytes */
7480 else if ( shCount >= 16 ) {
7481 /* lower order two bytes goes to higher order two bytes */
7483 /* if some more remaining */
7485 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7487 movLeft2Result(left, MSB16, result, MSB32);
7488 movLeft2Result(left, LSB, result, MSB24);
7490 aopPut(AOP(result),zero,MSB16);
7491 aopPut(AOP(result),zero,LSB);
7495 /* if more than 1 byte */
7496 else if ( shCount >= 8 ) {
7497 /* lower order three bytes goes to higher order three bytes */
7501 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7503 movLeft2Result(left, LSB, result, MSB16);
7505 else{ /* size = 4 */
7507 movLeft2Result(left, MSB24, result, MSB32);
7508 movLeft2Result(left, MSB16, result, MSB24);
7509 movLeft2Result(left, LSB, result, MSB16);
7510 aopPut(AOP(result),zero,LSB);
7512 else if(shCount == 1)
7513 shiftLLong(left, result, MSB16);
7515 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7516 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7517 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7518 aopPut(AOP(result),zero,LSB);
7523 /* 1 <= shCount <= 7 */
7524 else if(shCount <= 2){
7525 shiftLLong(left, result, LSB);
7527 shiftLLong(result, result, LSB);
7529 /* 3 <= shCount <= 7, optimize */
7531 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7532 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7533 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7539 /*-----------------------------------------------------------------*/
7540 /* genLeftShiftLiteral - left shifting by known count */
7541 /*-----------------------------------------------------------------*/
7542 static void genLeftShiftLiteral (operand *left,
7547 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7551 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7552 freeAsmop(right,NULL,ic,TRUE);
7554 aopOp(left,ic,FALSE);
7555 aopOp(result,ic,FALSE);
7557 size = getSize(operandType(result));
7560 pic14_emitcode("; shift left ","result %d, left %d",size,
7564 /* I suppose that the left size >= result size */
7567 movLeft2Result(left, size, result, size);
7571 else if(shCount >= (size * 8))
7573 aopPut(AOP(result),zero,size);
7577 genlshOne (result,left,shCount);
7582 genlshTwo (result,left,shCount);
7586 genlshFour (result,left,shCount);
7590 freeAsmop(left,NULL,ic,TRUE);
7591 freeAsmop(result,NULL,ic,TRUE);
7595 /*-----------------------------------------------------------------*
7596 * genMultiAsm - repeat assembly instruction for size of register.
7597 * if endian == 1, then the high byte (i.e base address + size of
7598 * register) is used first else the low byte is used first;
7599 *-----------------------------------------------------------------*/
7600 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7606 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7619 emitpcode(poc, popGet(AOP(reg),offset));
7626 /*-----------------------------------------------------------------*/
7627 /* genLeftShift - generates code for left shifting */
7628 /*-----------------------------------------------------------------*/
7629 static void genLeftShift (iCode *ic)
7631 operand *left,*right, *result;
7633 unsigned long lit = 0L;
7635 symbol *tlbl , *tlbl1;
7639 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7641 right = IC_RIGHT(ic);
7643 result = IC_RESULT(ic);
7645 aopOp(right,ic,FALSE);
7646 aopOp(left,ic,FALSE);
7647 aopOp(result,ic,FALSE);
7650 /* if the shift count is known then do it
7651 as efficiently as possible */
7652 if (AOP_TYPE(right) == AOP_LIT) {
7653 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7657 /* shift count is unknown then we have to form
7658 a loop get the loop count in B : Note: we take
7659 only the lower order byte since shifting
7660 more that 32 bits make no sense anyway, ( the
7661 largest size of an object can be only 32 bits ) */
7663 /* this code fails for RIGHT == RESULT */
7664 assert (!pic14_sameRegs (AOP(right), AOP(result)));
7666 /* now move the left to the result if they are not the
7668 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
7669 AOP_SIZE(result) > 1) {
7671 size = AOP_SIZE(result);
7674 l = aopGet(AOP(left),offset,FALSE,TRUE);
7675 if (*l == '@' && (IS_AOP_PREG(result))) {
7677 pic14_emitcode("mov","a,%s",l);
7678 aopPut(AOP(result),"a",offset);
7680 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
7681 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7682 //aopPut(AOP(result),l,offset);
7688 if(AOP_TYPE(left) == AOP_LIT)
7689 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7691 size = AOP_SIZE(result);
7693 /* if it is only one byte then */
7695 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7696 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7697 emitpcode(POC_ANDLW, popGetLit(0xf0));
7698 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7699 emitpcode(POC_MOVFW, popGet(AOP(left),0));
7700 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7701 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7702 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7703 emitpcode(POC_RLFW, popGet(AOP(result),0));
7704 emitpcode(POC_ANDLW, popGetLit(0xfe));
7705 emitpcode(POC_ADDFW, popGet(AOP(result),0));
7706 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7707 emitpcode(POC_ADDWF, popGet(AOP(result),0));
7710 tlbl = newiTempLabel(NULL);
7711 if (!pic14_sameRegs(AOP(left),AOP(result))) {
7712 mov2w (AOP(left), 0);
7713 emitpcode(POC_MOVWF, popGet(AOP(result),0));
7716 emitpcode(POC_COMFW, popGet(AOP(right),0));
7717 emitpcode(POC_RRF, popGet(AOP(result),0));
7718 emitpLabel(tlbl->key);
7719 emitpcode(POC_RLF, popGet(AOP(result),0));
7720 emitpcode(POC_ADDLW, popGetLit(1));
7722 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7727 if (pic14_sameRegs(AOP(left),AOP(result))) {
7729 tlbl = newiTempLabel(NULL);
7730 emitpcode(POC_COMFW, popGet(AOP(right),0));
7731 genMultiAsm(POC_RRF, result, size,1);
7732 emitpLabel(tlbl->key);
7733 genMultiAsm(POC_RLF, result, size,0);
7734 emitpcode(POC_ADDLW, popGetLit(1));
7736 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7740 //tlbl = newiTempLabel(NULL);
7742 //tlbl1 = newiTempLabel(NULL);
7744 //reAdjustPreg(AOP(result));
7746 //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7747 //pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7748 //l = aopGet(AOP(result),offset,FALSE,FALSE);
7750 //pic14_emitcode("add","a,acc");
7751 //aopPut(AOP(result),"a",offset++);
7753 // l = aopGet(AOP(result),offset,FALSE,FALSE);
7755 // pic14_emitcode("rlc","a");
7756 // aopPut(AOP(result),"a",offset++);
7758 //reAdjustPreg(AOP(result));
7760 //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7761 //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7764 tlbl = newiTempLabel(NULL);
7765 tlbl1= newiTempLabel(NULL);
7767 size = AOP_SIZE(result);
7770 pctemp = popGetTempReg(); /* grab a temporary working register. */
7772 emitpcode(POC_MOVFW, popGet(AOP(right),0));
7774 /* offset should be 0, 1 or 3 */
7775 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7777 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
7779 emitpcode(POC_MOVWF, pctemp);
7782 emitpLabel(tlbl->key);
7785 emitpcode(POC_RLF, popGet(AOP(result),0));
7787 emitpcode(POC_RLF, popGet(AOP(result),offset++));
7789 emitpcode(POC_DECFSZ, pctemp);
7790 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7791 emitpLabel(tlbl1->key);
7793 popReleaseTempReg(pctemp);
7797 freeAsmop (right,NULL,ic,TRUE);
7798 freeAsmop(left,NULL,ic,TRUE);
7799 freeAsmop(result,NULL,ic,TRUE);
7804 /*-----------------------------------------------------------------*/
7805 /* genrshOne - right shift a one byte quantity by known count */
7806 /*-----------------------------------------------------------------*/
7807 static void genrshOne (operand *result, operand *left,
7808 int shCount, int sign)
7811 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7812 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7815 /*-----------------------------------------------------------------*/
7816 /* genrshTwo - right shift two bytes by known amount != 0 */
7817 /*-----------------------------------------------------------------*/
7818 static void genrshTwo (operand *result,operand *left,
7819 int shCount, int sign)
7822 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7823 /* if shCount >= 8 */
7827 shiftR1Left2Result(left, MSB16, result, LSB,
7830 movLeft2Result(left, MSB16, result, LSB);
7832 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7835 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7836 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7840 /* 1 <= shCount <= 7 */
7842 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7845 /*-----------------------------------------------------------------*/
7846 /* shiftRLong - shift right one long from left to result */
7847 /* offl = LSB or MSB16 */
7848 /*-----------------------------------------------------------------*/
7849 static void shiftRLong (operand *left, int offl,
7850 operand *result, int sign)
7855 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7857 size = AOP_SIZE(left);
7858 if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7861 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7865 assert (offl >= 0 && offl < size);
7867 same = pic14_sameRegs (AOP(left), AOP(result));
7869 /* perform the shift */
7872 if (same && !offl) {
7873 emitpcode (POC_RRF, popGet (AOP(result), size));
7875 emitpcode (POC_RRFW, popGet (AOP(left), size));
7876 emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7880 addSign (result, AOP_SIZE(left) - offl, sign);
7883 /*-----------------------------------------------------------------*/
7884 /* genrshFour - shift four byte by a known amount != 0 */
7885 /*-----------------------------------------------------------------*/
7886 static void genrshFour (operand *result, operand *left,
7887 int shCount, int sign)
7890 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7891 /* if shifting more that 3 bytes */
7892 if(shCount >= 24 ) {
7895 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7897 movLeft2Result(left, MSB32, result, LSB);
7899 addSign(result, MSB16, sign);
7901 else if(shCount >= 16){
7904 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7906 movLeft2Result(left, MSB24, result, LSB);
7907 movLeft2Result(left, MSB32, result, MSB16);
7909 addSign(result, MSB24, sign);
7911 else if(shCount >= 8){
7914 shiftRLong(left, MSB16, result, sign);
7915 else if(shCount == 0){
7916 movLeft2Result(left, MSB16, result, LSB);
7917 movLeft2Result(left, MSB24, result, MSB16);
7918 movLeft2Result(left, MSB32, result, MSB24);
7919 addSign(result, MSB32, sign);
7922 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7923 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7924 /* the last shift is signed */
7925 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7926 addSign(result, MSB32, sign);
7929 else{ /* 1 <= shCount <= 7 */
7931 shiftRLong(left, LSB, result, sign);
7933 shiftRLong(result, LSB, result, sign);
7936 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7937 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7938 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7943 /*-----------------------------------------------------------------*/
7944 /* genRightShiftLiteral - right shifting by known count */
7945 /*-----------------------------------------------------------------*/
7946 static void genRightShiftLiteral (operand *left,
7952 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7956 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7957 freeAsmop(right,NULL,ic,TRUE);
7959 aopOp(left,ic,FALSE);
7960 aopOp(result,ic,FALSE);
7963 pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7967 lsize = pic14_getDataSize(left);
7968 res_size = pic14_getDataSize(result);
7969 /* test the LEFT size !!! */
7971 /* I suppose that the left size >= result size */
7974 movLeft2Result(left, res_size, result, res_size);
7977 else if(shCount >= (lsize * 8)){
7980 emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7982 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7983 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7988 emitpcode(POC_MOVLW, popGetLit(0));
7989 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7990 emitpcode(POC_MOVLW, popGetLit(0xff));
7992 emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7997 emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8004 genrshOne (result,left,shCount,sign);
8008 genrshTwo (result,left,shCount,sign);
8012 genrshFour (result,left,shCount,sign);
8020 freeAsmop(left,NULL,ic,TRUE);
8021 freeAsmop(result,NULL,ic,TRUE);
8026 /*-----------------------------------------------------------------*/
8027 /* genSignedRightShift - right shift of signed number */
8028 /*-----------------------------------------------------------------*/
8029 static void genSignedRightShift (iCode *ic)
8031 operand *right, *left, *result;
8034 symbol *tlbl, *tlbl1 ;
8037 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8039 /* we do it the hard way put the shift count in b
8040 and loop thru preserving the sign */
8042 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8044 right = IC_RIGHT(ic);
8046 result = IC_RESULT(ic);
8048 aopOp(right,ic,FALSE);
8049 aopOp(left,ic,FALSE);
8050 aopOp(result,ic,FALSE);
8053 if ( AOP_TYPE(right) == AOP_LIT) {
8054 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8055 //genRightShiftLiteral (left,right,result,ic,1);
8058 /* shift count is unknown then we have to form
8059 a loop get the loop count in B : Note: we take
8060 only the lower order byte since shifting
8061 more that 32 bits make no sense anyway, ( the
8062 largest size of an object can be only 32 bits ) */
8064 //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8065 //pic14_emitcode("inc","b");
8066 //freeAsmop (right,NULL,ic,TRUE);
8067 //aopOp(left,ic,FALSE);
8068 //aopOp(result,ic,FALSE);
8070 /* now move the left to the result if they are not the
8072 if (!pic14_sameRegs(AOP(left),AOP(result)) &&
8073 AOP_SIZE(result) > 1) {
8075 size = AOP_SIZE(result);
8079 l = aopGet(AOP(left),offset,FALSE,TRUE);
8080 if (*l == '@' && IS_AOP_PREG(result)) {
8081 pic14_emitcode("mov","a,%s",l);
8082 aopPut(AOP(result),"a",offset);
8084 aopPut(AOP(result),l,offset);
8086 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8087 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8093 /* mov the highest order bit to OVR */
8094 tlbl = newiTempLabel(NULL);
8095 tlbl1= newiTempLabel(NULL);
8097 size = AOP_SIZE(result);
8100 pctemp = popGetTempReg(); /* grab a temporary working register. */
8102 emitpcode(POC_MOVFW, popGet(AOP(right),0));
8104 /* offset should be 0, 1 or 3 */
8105 emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8107 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8109 emitpcode(POC_MOVWF, pctemp);
8112 emitpLabel(tlbl->key);
8114 emitpcode(POC_RLFW, popGet(AOP(result),offset));
8115 emitpcode(POC_RRF, popGet(AOP(result),offset));
8118 emitpcode(POC_RRF, popGet(AOP(result),--offset));
8121 emitpcode(POC_DECFSZ, pctemp);
8122 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8123 emitpLabel(tlbl1->key);
8125 popReleaseTempReg(pctemp);
8127 size = AOP_SIZE(result);
8129 pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8130 pic14_emitcode("rlc","a");
8131 pic14_emitcode("mov","ov,c");
8132 /* if it is only one byte then */
8134 l = aopGet(AOP(left),0,FALSE,FALSE);
8136 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8137 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8138 pic14_emitcode("mov","c,ov");
8139 pic14_emitcode("rrc","a");
8140 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8141 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8142 aopPut(AOP(result),"a",0);
8146 reAdjustPreg(AOP(result));
8147 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8148 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8149 pic14_emitcode("mov","c,ov");
8151 l = aopGet(AOP(result),offset,FALSE,FALSE);
8153 pic14_emitcode("rrc","a");
8154 aopPut(AOP(result),"a",offset--);
8156 reAdjustPreg(AOP(result));
8157 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8158 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8163 freeAsmop(left,NULL,ic,TRUE);
8164 freeAsmop(result,NULL,ic,TRUE);
8165 freeAsmop(right,NULL,ic,TRUE);
8169 /*-----------------------------------------------------------------*/
8170 /* loadSignToC - load the operand's sign bit into CARRY */
8171 /*-----------------------------------------------------------------*/
8173 static void loadSignToC (operand *op)
8176 assert (op && AOP(op) && AOP_SIZE(op));
8179 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8183 /*-----------------------------------------------------------------*/
8184 /* genRightShift - generate code for right shifting */
8185 /*-----------------------------------------------------------------*/
8186 static void genGenericShift (iCode *ic, int shiftRight)
8188 operand *right, *left, *result;
8191 symbol *tlbl, *tlbl1, *inverselbl;
8194 /* if signed then we do it the hard way preserve the
8195 sign bit moving it inwards */
8196 retype = getSpec(operandType(IC_RESULT(ic)));
8197 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8199 /* signed & unsigned types are treated the same : i.e. the
8200 signed is NOT propagated inwards : quoting from the
8201 ANSI - standard : "for E1 >> E2, is equivalent to division
8202 by 2**E2 if unsigned or if it has a non-negative value,
8203 otherwise the result is implementation defined ", MY definition
8204 is that the sign does not get propagated */
8206 right = IC_RIGHT(ic);
8208 result = IC_RESULT(ic);
8210 aopOp(right,ic,FALSE);
8211 aopOp(left,ic,FALSE);
8212 aopOp(result,ic,FALSE);
8214 /* if the shift count is known then do it
8215 as efficiently as possible */
8216 if (AOP_TYPE(right) == AOP_LIT) {
8217 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8221 shiftRight = !shiftRight;
8225 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8227 shiftLeft_Left2ResultLit (left, result, lit);
8228 //genRightShiftLiteral (left,right,result,ic, 0);
8232 /* shift count is unknown then we have to form
8233 a loop get the loop count in B : Note: we take
8234 only the lower order byte since shifting
8235 more that 32 bits make no sense anyway, ( the
8236 largest size of an object can be only 32 bits ) */
8238 /* we must not overwrite the shift counter */
8239 assert (!pic14_sameRegs(AOP(right),AOP(result)));
8241 /* now move the left to the result if they are not the
8243 if (!pic14_sameRegs(AOP(left),AOP(result)))
8245 size = min(AOP_SIZE(result), AOP_SIZE(left));
8247 mov2w(AOP(left), size);
8248 movwf(AOP(result), size);
8250 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8253 tlbl = newiTempLabel(NULL);
8254 tlbl1= newiTempLabel(NULL);
8256 size = AOP_SIZE(result);
8258 mov2w(AOP(right),0);
8259 if (!SPEC_USIGN(operandType(right)))
8261 inverselbl = newiTempLabel(NULL);
8262 /* signed shift count -- invert shift direction for c<0 */
8263 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8264 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8266 emitpcode(POC_SUBLW, popGetLit(0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8267 /* check for `a = b >> c' with `-c == 0' */
8269 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8270 emitpLabel(tlbl->key);
8271 /* propagate the sign bit inwards for SIGNED result */
8272 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8273 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8274 emitpcode(POC_ADDLW, popGetLit(1)); /* clears CARRY (unless W==0 afterwards) */
8276 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8278 if (!SPEC_USIGN(operandType(right)))
8280 symbol *inv_loop = newiTempLabel(NULL);
8282 shiftRight = !shiftRight; /* invert shift direction */
8284 /* we came here from the code above -- we are done */
8285 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8287 /* emit code for shifting N<0 steps, count is already in W */
8288 emitpLabel(inverselbl->key);
8289 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8290 emitpLabel(inv_loop->key);
8291 /* propagate the sign bit inwards for SIGNED result */
8292 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8293 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8294 emitpcode(POC_ADDLW, popGetLit(1));
8296 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8299 emitpLabel(tlbl1->key);
8301 freeAsmop(left,NULL,ic,TRUE);
8302 freeAsmop (right,NULL,ic,TRUE);
8303 freeAsmop(result,NULL,ic,TRUE);
8306 static void genRightShift (iCode *ic)
8308 genGenericShift(ic, 1);
8311 static void genLeftShift (iCode *ic)
8313 genGenericShift(ic, 0);
8316 /*-----------------------------------------------------------------*/
8317 /* SetIrp - Set IRP bit */
8318 /*-----------------------------------------------------------------*/
8319 void SetIrp(operand *result) {
8321 if (AOP_TYPE(result) == AOP_LIT) {
8322 unsigned lit = (unsigned)operandLitValue(result);
8328 if (PCOP(AOP(result))->type == PO_LITERAL) {
8329 int addrs = PCOL(AOP(result))->lit;
8335 emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8336 if(AOP_SIZE(result) > 1) {
8337 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8345 setup_fsr (operand *ptr)
8348 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8350 /* also setup-up IRP */
8354 /*-----------------------------------------------------------------*/
8355 /* emitPtrByteGet - emits code to get a byte into WREG from an */
8356 /* arbitrary pointer (__code, __data, generic) */
8357 /*-----------------------------------------------------------------*/
8359 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8366 if (!alreadyAddressed) setup_fsr (src);
8367 emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8371 assert( AOP_SIZE(src) == 2 );
8373 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8375 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8376 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8377 call_libraryfunc ("__gptrget1");
8381 assert( AOP_SIZE(src) == 3 );
8383 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8385 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8387 call_libraryfunc ("__gptrget1");
8391 assert( !"unhandled pointer type" );
8396 /*-----------------------------------------------------------------*/
8397 /* emitPtrByteSet - emits code to set a byte from src through a */
8398 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
8399 /*-----------------------------------------------------------------*/
8401 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8408 if (!alreadyAddressed) setup_fsr (dst);
8409 emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8413 assert( !"trying to assign to __code pointer" );
8417 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8419 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8421 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8423 call_libraryfunc ("__gptrput1");
8427 assert( !"unhandled pointer type" );
8432 /*-----------------------------------------------------------------*/
8433 /* genUnpackBits - generates code for unpacking bits */
8434 /*-----------------------------------------------------------------*/
8435 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8437 int rsize; /* result size */
8438 sym_link *etype; /* bitfield type information */
8439 int blen; /* bitfield length */
8440 int bstr; /* bitfield starting bit within byte */
8443 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8444 etype = getSpec(operandType(result));
8445 rsize = getSize (operandType (result));
8446 blen = SPEC_BLEN (etype);
8447 bstr = SPEC_BSTR (etype);
8449 /* single bit field case */
8451 if (ifx) { /* that is for an if statement */
8454 resolveIfx(&rIfx,ifx);
8455 if (ptype == -1) /* direct */
8456 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8458 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8459 emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8460 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8464 assert (!pic14_sameRegs (AOP(result), AOP(left)));
8465 for (i=0; i < AOP_SIZE(result); i++)
8466 emitpcode (POC_CLRF, popGet (AOP(result), i));
8471 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8472 /* adjust result below */
8479 emitPtrByteGet (left, ptype, FALSE);
8480 emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8482 /* adjust result below */
8486 assert( !"unhandled pointer type" );
8489 /* move sign-/zero extended bit to result */
8490 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8491 emitpcode (POC_INCF, popGet (AOP(result), 0));
8493 emitpcode (POC_DECF, popGet (AOP(result), 0));
8495 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8499 else if (blen <= 8 && ((blen + bstr) <= 8))
8504 for (i=0; i < AOP_SIZE(result); i++)
8505 emitpcode (POC_CLRF, popGet (AOP(result), i));
8510 mov2w(AOP(left), 0);
8517 emitPtrByteGet (left, ptype, FALSE);
8521 assert( !"unhandled pointer type" );
8525 emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8526 movwf(AOP(result), 0);
8527 AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8529 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8531 /* signed bitfield */
8532 assert (bstr + blen > 0);
8533 emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8534 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8535 emitpcode(POC_IORWF, popGet(AOP(result),0));
8537 addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8541 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8545 /*-----------------------------------------------------------------*/
8546 /* genDataPointerGet - generates code when ptr offset is known */
8547 /*-----------------------------------------------------------------*/
8548 static void genDataPointerGet (operand *left,
8552 int size , offset = 0;
8555 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8558 /* optimization - most of the time, left and result are the same
8559 * address, but different types. for the pic code, we could omit
8562 aopOp(result,ic,TRUE);
8564 if (pic14_sameRegs (AOP(left), AOP(result)))
8567 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8569 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8571 size = AOP_SIZE(result);
8572 if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8576 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8577 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8581 freeAsmop(left,NULL,ic,TRUE);
8582 freeAsmop(result,NULL,ic,TRUE);
8586 /*-----------------------------------------------------------------*/
8587 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
8588 /*-----------------------------------------------------------------*/
8589 static void genNearPointerGet (operand *left,
8594 sym_link *ltype = operandType(left);
8595 sym_link *rtype = operandType(result);
8596 sym_link *retype= getSpec(rtype); /* bitfield type information */
8600 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8603 aopOp(left,ic,FALSE);
8605 /* if left is rematerialisable and
8606 result is not bit variable type and
8607 the left is pointer to data space i.e
8608 lower 128 bytes of space */
8609 if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
8610 !IS_BITVAR(retype) &&
8611 PIC_IS_DATA_PTR(ltype)) {
8612 genDataPointerGet (left,result,ic);
8616 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8617 aopOp (result,ic,FALSE);
8619 /* Check if can access directly instead of via a pointer */
8620 if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8621 && AOP_SIZE(result) == 1)
8626 if (IS_BITFIELD(getSpec(operandType(result))))
8628 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8632 /* If the pointer value is not in a the FSR then need to put it in */
8633 /* Must set/reset IRP bit for use with FSR. */
8638 /* if bitfield then unpack the bits */
8640 /* we have can just get the values */
8641 int size = AOP_SIZE(result);
8644 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8648 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8650 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8651 if (AOP_TYPE(result) == AOP_LIT) {
8652 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8654 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8656 if (size && !direct)
8657 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8662 /* now some housekeeping stuff */
8664 /* we had to allocate for this iCode */
8665 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8666 freeAsmop(NULL,aop,ic,TRUE);
8668 /* we did not allocate which means left
8669 already in a pointer register, then
8670 if size > 0 && this could be used again
8671 we have to point it back to where it
8673 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8674 if (AOP_SIZE(result) > 1 &&
8675 !OP_SYMBOL(left)->remat &&
8676 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8678 int size = AOP_SIZE(result) - 1;
8680 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8686 freeAsmop(left,NULL,ic,TRUE);
8687 freeAsmop(result,NULL,ic,TRUE);
8692 /*-----------------------------------------------------------------*/
8693 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch */
8694 /*-----------------------------------------------------------------*/
8695 static void genPagedPointerGet (operand *left,
8702 sym_link *rtype, *retype;
8705 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8707 rtype = operandType(result);
8708 retype= getSpec(rtype);
8710 aopOp(left,ic,FALSE);
8712 /* if the value is already in a pointer register
8713 then don't need anything more */
8714 if (!AOP_INPREG(AOP(left))) {
8715 /* otherwise get a free pointer register */
8717 preg = getFreePtr(ic,&aop,FALSE);
8718 pic14_emitcode("mov","%s,%s",
8720 aopGet(AOP(left),0,FALSE,TRUE));
8721 rname = preg->name ;
8723 rname = aopGet(AOP(left),0,FALSE,FALSE);
8725 freeAsmop(left,NULL,ic,TRUE);
8726 aopOp (result,ic,FALSE);
8728 /* if bitfield then unpack the bits */
8729 if (IS_BITFIELD(retype))
8730 genUnpackBits (result,left,rname,PPOINTER,0);
8732 /* we have can just get the values */
8733 int size = AOP_SIZE(result);
8738 pic14_emitcode("movx","a,@%s",rname);
8739 aopPut(AOP(result),"a",offset);
8744 pic14_emitcode("inc","%s",rname);
8748 /* now some housekeeping stuff */
8750 /* we had to allocate for this iCode */
8751 freeAsmop(NULL,aop,ic,TRUE);
8753 /* we did not allocate which means left
8754 already in a pointer register, then
8755 if size > 0 && this could be used again
8756 we have to point it back to where it
8758 if (AOP_SIZE(result) > 1 &&
8759 !OP_SYMBOL(left)->remat &&
8760 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8762 int size = AOP_SIZE(result) - 1;
8764 pic14_emitcode("dec","%s",rname);
8769 freeAsmop(result,NULL,ic,TRUE);
8774 /*-----------------------------------------------------------------*/
8775 /* genFarPointerGet - gget value from far space */
8776 /*-----------------------------------------------------------------*/
8777 static void genFarPointerGet (operand *left,
8778 operand *result, iCode *ic)
8781 sym_link *retype = getSpec(operandType(result));
8784 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8786 aopOp(left,ic,FALSE);
8788 /* if the operand is already in dptr
8789 then we do nothing else we move the value to dptr */
8790 if (AOP_TYPE(left) != AOP_STR) {
8791 /* if this is remateriazable */
8792 if (AOP_TYPE(left) == AOP_IMMD)
8793 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8794 else { /* we need to get it byte by byte */
8795 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8796 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8797 if (options.model == MODEL_FLAT24)
8799 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8803 /* so dptr know contains the address */
8804 freeAsmop(left,NULL,ic,TRUE);
8805 aopOp(result,ic,FALSE);
8807 /* if bit then unpack */
8808 if (IS_BITFIELD(retype))
8809 genUnpackBits(result,left,"dptr",FPOINTER,0);
8811 size = AOP_SIZE(result);
8815 pic14_emitcode("movx","a,@dptr");
8816 aopPut(AOP(result),"a",offset++);
8818 pic14_emitcode("inc","dptr");
8822 freeAsmop(result,NULL,ic,TRUE);
8827 /*-----------------------------------------------------------------*/
8828 /* genCodePointerGet - get value from code space */
8829 /*-----------------------------------------------------------------*/
8830 static void genCodePointerGet (operand *left,
8831 operand *result, iCode *ic)
8834 sym_link *retype = getSpec(operandType(result));
8836 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8838 aopOp(left,ic,FALSE);
8840 /* if the operand is already in dptr
8841 then we do nothing else we move the value to dptr */
8842 if (AOP_TYPE(left) != AOP_STR) {
8843 /* if this is remateriazable */
8844 if (AOP_TYPE(left) == AOP_IMMD)
8845 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8846 else { /* we need to get it byte by byte */
8847 pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8848 pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8849 if (options.model == MODEL_FLAT24)
8851 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8855 /* so dptr know contains the address */
8856 freeAsmop(left,NULL,ic,TRUE);
8857 aopOp(result,ic,FALSE);
8859 /* if bit then unpack */
8860 if (IS_BITFIELD(retype))
8861 genUnpackBits(result,left,"dptr",CPOINTER,0);
8863 size = AOP_SIZE(result);
8867 pic14_emitcode("clr","a");
8868 pic14_emitcode("movc","a,@a+dptr");
8869 aopPut(AOP(result),"a",offset++);
8871 pic14_emitcode("inc","dptr");
8875 freeAsmop(result,NULL,ic,TRUE);
8878 /*-----------------------------------------------------------------*/
8879 /* genGenPointerGet - gget value from generic pointer space */
8880 /*-----------------------------------------------------------------*/
8881 static void genGenPointerGet (operand *left,
8882 operand *result, iCode *ic)
8885 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8886 aopOp(left,ic,FALSE);
8887 aopOp(result,ic,FALSE);
8890 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8892 if (IS_BITFIELD(getSpec(operandType(result))))
8894 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8899 /* emit call to __gptrget */
8900 char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8901 int size = AOP_SIZE(result);
8904 assert (size > 0 && size <= 4);
8906 /* pass arguments */
8907 assert (AOP_SIZE(left) == 3);
8908 mov2w(AOP(left), 0);
8909 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8910 mov2w(AOP(left), 1);
8911 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8912 mov2w(AOP(left), 2);
8913 call_libraryfunc (func[size]);
8916 movwf (AOP(result), --size);
8918 emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8919 movwf (AOP(result), size);
8923 freeAsmop(left,NULL,ic,TRUE);
8924 freeAsmop(result,NULL,ic,TRUE);
8928 /*-----------------------------------------------------------------*/
8929 /* genConstPointerGet - get value from const generic pointer space */
8930 /*-----------------------------------------------------------------*/
8931 static void genConstPointerGet (operand *left,
8932 operand *result, iCode *ic)
8934 //sym_link *retype = getSpec(operandType(result));
8936 symbol *albl, *blbl;//, *clbl;
8943 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8944 aopOp(left,ic,FALSE);
8945 aopOp(result,ic,FALSE);
8947 size = AOP_SIZE(result);
8949 DEBUGpic14_AopType(__LINE__,left,NULL,result);
8951 DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8953 lit = op_isLitLike (left);
8954 poc = lit ? POC_MOVLW : POC_MOVFW;
8956 if (IS_BITFIELD(getSpec(operandType(result))))
8958 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
8963 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
8964 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
8965 assert (size > 0 && size <= 4);
8968 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8970 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8971 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
8972 call_libraryfunc (func[size]);
8974 movwf(AOP(result),size-1);
8975 for (i = 1; i < size; i++)
8977 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
8978 movwf(AOP(result),size - 1 - i);
8983 freeAsmop(left,NULL,ic,TRUE);
8984 freeAsmop(result,NULL,ic,TRUE);
8987 /*-----------------------------------------------------------------*/
8988 /* genPointerGet - generate code for pointer get */
8989 /*-----------------------------------------------------------------*/
8990 static void genPointerGet (iCode *ic)
8992 operand *left, *result ;
8993 sym_link *type, *etype;
8997 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9000 result = IC_RESULT(ic) ;
9002 /* depending on the type of pointer we need to
9003 move it to the correct pointer register */
9004 type = operandType(left);
9005 etype = getSpec(type);
9007 if (IS_PTR_CONST(type))
9008 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9010 /* if left is of type of pointer then it is simple */
9011 if (IS_PTR(type) && !IS_FUNC(type->next))
9012 p_type = DCL_TYPE(type);
9014 /* we have to go by the storage class */
9015 p_type = PTR_TYPE(SPEC_OCLS(etype));
9017 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9019 if (SPEC_OCLS(etype)->codesp ) {
9020 DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9021 //p_type = CPOINTER ;
9024 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9025 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9026 /*p_type = FPOINTER ;*/
9028 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9029 DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9030 /* p_type = PPOINTER; */
9032 if (SPEC_OCLS(etype) == idata )
9033 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9034 /* p_type = IPOINTER; */
9036 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9037 /* p_type = POINTER ; */
9040 /* now that we have the pointer type we assign
9041 the pointer values */
9047 genNearPointerGet (left,result,ic);
9051 genPagedPointerGet(left,result,ic);
9055 genFarPointerGet (left,result,ic);
9059 genConstPointerGet (left,result,ic);
9063 genGenPointerGet (left,result,ic);
9066 assert ( !"unhandled pointer type" );
9072 /*-----------------------------------------------------------------*/
9073 /* genPackBits - generates code for packed bit storage */
9074 /*-----------------------------------------------------------------*/
9075 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9077 int blen; /* bitfield length */
9078 int bstr; /* bitfield starting bit within byte */
9079 int litval; /* source literal value (if AOP_LIT) */
9080 unsigned char mask; /* bitmask within current byte */
9083 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9085 blen = SPEC_BLEN (etype);
9086 bstr = SPEC_BSTR (etype);
9088 /* If the bitfield length is less than a byte and does not cross byte boundaries */
9089 if ((blen <= 8) && ((bstr + blen) <= 8))
9091 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9092 (unsigned char) (0xFF >> (8 - bstr)));
9094 if (AOP_TYPE (right) == AOP_LIT)
9096 /* Case with a bitfield length <8 and literal source */
9097 int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9104 if (AOP(result)->type == AOP_PCODE)
9105 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9107 pcop = popGet(AOP(result),0);
9108 emitpcode(lit?POC_BSF:POC_BCF,pcop);
9114 emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9118 assert( !"trying to assign to bitfield via pointer to __code space" );
9122 emitPtrByteGet(result, p_type, FALSE);
9124 emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9126 emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9128 emitPtrByteSet(result, p_type, TRUE);
9132 assert( !"unhandled pointer type" );
9134 } // switch (p_type)
9137 litval = lit << bstr;
9138 litval &= (~mask) & 0x00ff;
9143 mov2w (AOP(result), 0);
9144 if ((litval|mask) != 0x00ff)
9145 emitpcode(POC_ANDLW, popGetLit (mask));
9147 emitpcode(POC_IORLW, popGetLit (litval));
9148 movwf (AOP(result), 0);
9154 emitPtrByteGet(result, p_type, FALSE);
9155 if ((litval|mask) != 0x00ff)
9156 emitpcode(POC_ANDLW, popGetLit (mask));
9158 emitpcode(POC_IORLW, popGetLit (litval));
9159 emitPtrByteSet(result, p_type, TRUE);
9163 assert( !"trying to assign to bitfield via pointer to __code space" );
9167 assert( !"unhandled pointer type" );
9174 /* right is no literal */
9179 /* Note more efficient code, of pre clearing bit then only setting it if required,
9180 * can only be done if it is known that the result is not a SFR */
9181 emitpcode(POC_RRFW,popGet(AOP(right),0));
9183 emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9185 emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9191 emitPtrByteGet (result, p_type, FALSE);
9192 emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9193 emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9194 emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9195 emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9196 emitPtrByteSet (result, p_type, TRUE);
9200 assert( !"trying to assign to bitfield via pointer to __code space" );
9204 assert( !"unhandled pointer type" );
9209 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9210 pCodeOp *temp = popGetTempReg ();
9212 mov2w (AOP(right), 0);
9214 emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9216 emitpcode(POC_MOVWF, temp);
9218 AccLsh (temp, bstr);
9224 mov2w (AOP(result), 0);
9225 emitpcode(POC_ANDLW, popGetLit (mask));
9226 emitpcode(POC_IORFW, temp);
9227 movwf (AOP(result), 0);
9233 emitPtrByteGet (result, p_type, FALSE);
9234 emitpcode(POC_ANDLW, popGetLit (mask));
9235 emitpcode(POC_IORFW, temp);
9236 emitPtrByteSet (result, p_type, TRUE);
9240 assert( !"trying to assign to bitfield via pointer to __code space" );
9244 assert( !"unhandled pointer type" );
9248 popReleaseTempReg (temp);
9250 } // if (AOP(right)->type != AOP_LIT)
9252 } // if (blen <= 8 && ((blen + bstr) <= 8))
9254 assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9257 /*-----------------------------------------------------------------*/
9258 /* genDataPointerSet - remat pointer to data space */
9259 /*-----------------------------------------------------------------*/
9260 static void genDataPointerSet(operand *right,
9264 int size, offset = 0 ;
9268 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9269 aopOp(right,ic,FALSE);
9270 aopOp(result,ic,FALSE);
9272 assert (IS_SYMOP(result));
9273 assert (IS_PTR(OP_SYM_TYPE(result)));
9275 if (AOP_TYPE(right) == AOP_LIT)
9278 size = AOP_SIZE(right);
9279 ressize = getSize(OP_SYM_ETYPE(result));
9280 if (size > ressize) size = ressize;
9281 //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9283 //assert( !"what's going on here?" );
9286 if ( AOP_TYPE(result) == AOP_PCODE) {
9287 fprintf(stderr,"genDataPointerSet %s, %d\n",
9288 AOP(result)->aopu.pcop->name,
9289 PCOI(AOP(result)->aopu.pcop)->offset);
9293 // tsd, was l+1 - the underline `_' prefix was being stripped
9295 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9297 if (AOP_TYPE(right) == AOP_LIT) {
9298 unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9299 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9301 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9302 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9304 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9307 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9308 emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9309 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9315 freeAsmop(right,NULL,ic,TRUE);
9316 freeAsmop(result,NULL,ic,TRUE);
9319 /*-----------------------------------------------------------------*/
9320 /* genNearPointerSet - pic14_emitcode for near pointer put */
9321 /*-----------------------------------------------------------------*/
9322 static void genNearPointerSet (operand *right,
9327 sym_link *ptype = operandType(result);
9328 sym_link *retype = getSpec(operandType(right));
9329 sym_link *letype = getSpec(ptype);
9334 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9335 aopOp(result,ic,FALSE);
9338 /* if the result is rematerializable &
9339 in data space & not a bit variable */
9340 //if (AOP_TYPE(result) == AOP_IMMD &&
9341 if (AOP_TYPE(result) == AOP_PCODE &&
9342 PIC_IS_DATA_PTR(ptype) &&
9343 !IS_BITVAR (retype) &&
9344 !IS_BITVAR (letype)) {
9345 genDataPointerSet (right,result,ic);
9346 freeAsmop(result,NULL,ic,TRUE);
9351 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9352 aopOp(right,ic,FALSE);
9353 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9355 /* Check if can access directly instead of via a pointer */
9356 if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9360 if (IS_BITFIELD (letype))
9362 genPackBits (letype, result, right, direct?-1:POINTER);
9366 /* If the pointer value is not in a the FSR then need to put it in */
9367 /* Must set/reset IRP bit for use with FSR. */
9368 /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9373 /* we have can just get the values */
9374 int size = AOP_SIZE(right);
9377 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9379 char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9381 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9383 if (AOP_TYPE(right) == AOP_LIT) {
9384 emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9386 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9389 emitpcode(POC_MOVWF,popGet(AOP(result),0));
9391 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9393 if (size && !direct)
9394 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9399 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9400 /* now some housekeeping stuff */
9402 /* we had to allocate for this iCode */
9403 freeAsmop(NULL,aop,ic,TRUE);
9405 /* we did not allocate which means left
9406 already in a pointer register, then
9407 if size > 0 && this could be used again
9408 we have to point it back to where it
9410 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9411 if (AOP_SIZE(right) > 1 &&
9412 !OP_SYMBOL(result)->remat &&
9413 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9415 int size = AOP_SIZE(right) - 1;
9417 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9421 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9424 freeAsmop(right,NULL,ic,TRUE);
9425 freeAsmop(result,NULL,ic,TRUE);
9429 /*-----------------------------------------------------------------*/
9430 /* genPagedPointerSet - pic14_emitcode for Paged pointer put */
9431 /*-----------------------------------------------------------------*/
9432 static void genPagedPointerSet (operand *right,
9442 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9444 retype= getSpec(operandType(right));
9446 aopOp(result,ic,FALSE);
9448 /* if the value is already in a pointer register
9449 then don't need anything more */
9450 if (!AOP_INPREG(AOP(result))) {
9451 /* otherwise get a free pointer register */
9453 preg = getFreePtr(ic,&aop,FALSE);
9454 pic14_emitcode("mov","%s,%s",
9456 aopGet(AOP(result),0,FALSE,TRUE));
9457 rname = preg->name ;
9459 rname = aopGet(AOP(result),0,FALSE,FALSE);
9461 freeAsmop(result,NULL,ic,TRUE);
9462 aopOp (right,ic,FALSE);
9464 /* if bitfield then unpack the bits */
9465 if (IS_BITFIELD(retype))
9466 genPackBits (retype,result,right,rname,PPOINTER);
9468 /* we have can just get the values */
9469 int size = AOP_SIZE(right);
9473 l = aopGet(AOP(right),offset,FALSE,TRUE);
9476 pic14_emitcode("movx","@%s,a",rname);
9479 pic14_emitcode("inc","%s",rname);
9485 /* now some housekeeping stuff */
9487 /* we had to allocate for this iCode */
9488 freeAsmop(NULL,aop,ic,TRUE);
9490 /* we did not allocate which means left
9491 already in a pointer register, then
9492 if size > 0 && this could be used again
9493 we have to point it back to where it
9495 if (AOP_SIZE(right) > 1 &&
9496 !OP_SYMBOL(result)->remat &&
9497 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9499 int size = AOP_SIZE(right) - 1;
9501 pic14_emitcode("dec","%s",rname);
9506 freeAsmop(right,NULL,ic,TRUE);
9511 /*-----------------------------------------------------------------*/
9512 /* genFarPointerSet - set value from far space */
9513 /*-----------------------------------------------------------------*/
9514 static void genFarPointerSet (operand *right,
9515 operand *result, iCode *ic)
9518 sym_link *retype = getSpec(operandType(right));
9521 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 aopOp(result,ic,FALSE);
9524 /* if the operand is already in dptr
9525 then we do nothing else we move the value to dptr */
9526 if (AOP_TYPE(result) != AOP_STR) {
9527 /* if this is remateriazable */
9528 if (AOP_TYPE(result) == AOP_IMMD)
9529 pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9530 else { /* we need to get it byte by byte */
9531 pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9532 pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9533 if (options.model == MODEL_FLAT24)
9535 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9539 /* so dptr know contains the address */
9540 freeAsmop(result,NULL,ic,TRUE);
9541 aopOp(right,ic,FALSE);
9543 /* if bit then unpack */
9544 if (IS_BITFIELD(retype))
9545 genPackBits(retype,result,right,"dptr",FPOINTER);
9547 size = AOP_SIZE(right);
9551 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9553 pic14_emitcode("movx","@dptr,a");
9555 pic14_emitcode("inc","dptr");
9559 freeAsmop(right,NULL,ic,TRUE);
9563 /*-----------------------------------------------------------------*/
9564 /* genGenPointerSet - set value from generic pointer space */
9565 /*-----------------------------------------------------------------*/
9566 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9568 sym_link *retype = getSpec(operandType(result));
9571 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9572 aopOp(right,ic,FALSE);
9573 aopOp(result,ic,FALSE);
9576 DEBUGpic14_AopType(__LINE__,right,NULL,result);
9578 if (IS_BITFIELD(retype))
9580 genPackBits (retype, result, right, GPOINTER);
9585 /* emit call to __gptrput */
9586 char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9587 int size = AOP_SIZE(right);
9590 /* The following assertion fails for
9591 * struct foo { char a; char b; } bar;
9592 * void demo(struct foo *dst, char c) { dst->b = c; }
9593 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
9594 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
9596 * The frontend seems to guarantee that IC_LEFT has the correct size,
9597 * it works fine both for larger and smaller types of `char c'.
9599 //assert (size == getSize(OP_SYM_ETYPE(result)));
9600 assert (size > 0 && size <= 4);
9602 /* pass arguments */
9603 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9609 mov2w_op (right, off);
9610 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9615 assert (AOP_SIZE(result) == 3);
9616 mov2w(AOP(result), 0);
9617 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9618 mov2w(AOP(result), 1);
9619 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9620 mov2w(AOP(result), 2);
9621 call_libraryfunc (func[size]);
9624 freeAsmop(right,NULL,ic,TRUE);
9625 freeAsmop(result,NULL,ic,TRUE);
9628 /*-----------------------------------------------------------------*/
9629 /* genPointerSet - stores the value into a pointer location */
9630 /*-----------------------------------------------------------------*/
9631 static void genPointerSet (iCode *ic)
9633 operand *right, *result ;
9634 sym_link *type, *etype;
9638 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9640 right = IC_RIGHT(ic);
9641 result = IC_RESULT(ic) ;
9643 /* depending on the type of pointer we need to
9644 move it to the correct pointer register */
9645 type = operandType(result);
9646 etype = getSpec(type);
9647 /* if left is of type of pointer then it is simple */
9648 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9649 p_type = DCL_TYPE(type);
9652 /* we have to go by the storage class */
9653 p_type = PTR_TYPE(SPEC_OCLS(etype));
9655 /* if (SPEC_OCLS(etype)->codesp ) { */
9656 /* p_type = CPOINTER ; */
9659 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9660 /* p_type = FPOINTER ; */
9662 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9663 /* p_type = PPOINTER ; */
9665 /* if (SPEC_OCLS(etype) == idata ) */
9666 /* p_type = IPOINTER ; */
9668 /* p_type = POINTER ; */
9671 /* now that we have the pointer type we assign
9672 the pointer values */
9678 genNearPointerSet (right,result,ic);
9682 genPagedPointerSet (right,result,ic);
9686 genFarPointerSet (right,result,ic);
9690 genGenPointerSet (right,result,ic);
9694 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9695 "genPointerSet: illegal pointer type");
9699 /*-----------------------------------------------------------------*/
9700 /* genIfx - generate code for Ifx statement */
9701 /*-----------------------------------------------------------------*/
9702 static void genIfx (iCode *ic, iCode *popIc)
9704 operand *cond = IC_COND(ic);
9708 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9710 aopOp(cond,ic,FALSE);
9712 /* get the value into acc */
9713 if (AOP_TYPE(cond) != AOP_CRY)
9714 pic14_toBoolean(cond);
9718 /* if there was something to be popped then do it */
9724 /* This assumes that CARRY is set iff cond is true */
9727 assert (!IC_FALSE(ic));
9728 emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9730 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9732 assert (IC_FALSE(ic));
9733 emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9735 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9739 static int hasWarned = 0;
9742 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9749 /* now Z is set iff !cond */
9752 assert (!IC_FALSE(ic));
9754 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9757 emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9763 /* the result is now in the accumulator */
9764 freeAsmop(cond,NULL,ic,TRUE);
9767 /*-----------------------------------------------------------------*/
9768 /* genAddrOf - generates code for address of */
9769 /*-----------------------------------------------------------------*/
9770 static void genAddrOf (iCode *ic)
9772 operand *right, *result, *left;
9776 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9779 //aopOp(IC_RESULT(ic),ic,FALSE);
9781 aopOp((left=IC_LEFT(ic)),ic,FALSE);
9782 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9783 aopOp((result=IC_RESULT(ic)),ic,TRUE);
9785 DEBUGpic14_AopType(__LINE__,left,right,result);
9786 assert (IS_SYMOP (left));
9788 /* sanity check: generic pointers to code space are not yet supported,
9789 * pionters to codespace must not be assigned addresses of __data values. */
9791 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9792 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)));
9793 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)));
9794 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)));
9795 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)));
9798 if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9799 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9800 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9801 OP_SYMBOL(left)->name);
9802 } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9803 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9804 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9805 OP_SYMBOL(left)->name);
9808 size = AOP_SIZE(IC_RESULT(ic));
9809 if (IS_GENPTR(OP_SYM_TYPE(result))) {
9811 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9816 /* fixing bug #863624, reported from (errolv) */
9817 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9818 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9821 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9822 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9827 if (IS_GENPTR(OP_SYM_TYPE(result)))
9829 /* provide correct tag */
9830 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9831 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9832 movwf (AOP(result), 2);
9835 freeAsmop(left,NULL,ic,FALSE);
9836 freeAsmop(result,NULL,ic,TRUE);
9841 /*-----------------------------------------------------------------*/
9842 /* genFarFarAssign - assignment when both are in far space */
9843 /*-----------------------------------------------------------------*/
9844 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9846 int size = AOP_SIZE(right);
9849 /* first push the right side on to the stack */
9851 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9853 pic14_emitcode ("push","acc");
9856 freeAsmop(right,NULL,ic,FALSE);
9857 /* now assign DPTR to result */
9858 aopOp(result,ic,FALSE);
9859 size = AOP_SIZE(result);
9861 pic14_emitcode ("pop","acc");
9862 aopPut(AOP(result),"a",--offset);
9864 freeAsmop(result,NULL,ic,FALSE);
9869 /*-----------------------------------------------------------------*/
9870 /* genAssign - generate code for assignment */
9871 /*-----------------------------------------------------------------*/
9872 static void genAssign (iCode *ic)
9874 operand *result, *right;
9875 int size, offset,know_W;
9876 unsigned long lit = 0L;
9878 result = IC_RESULT(ic);
9879 right = IC_RIGHT(ic) ;
9882 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9884 /* if they are the same */
9885 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9888 aopOp(right,ic,FALSE);
9889 aopOp(result,ic,TRUE);
9891 DEBUGpic14_AopType(__LINE__,NULL,right,result);
9893 /* if they are the same registers */
9894 if (pic14_sameRegs(AOP(right),AOP(result)))
9897 /* special case: assign from __code */
9898 if (!IS_ITEMP(right) /* --> iTemps never reside in __code */
9899 && IS_SYMOP (right) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9900 && !IS_FUNC(OP_SYM_TYPE(right)) /* --> we would want its address instead of the first instruction */
9901 && !IS_CODEPTR(OP_SYM_TYPE(right)) /* --> get symbols address instread */
9902 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9904 emitpComment ("genAssign from CODESPACE");
9905 genConstPointerGet (right, result, ic);
9909 /* just for symmetry reasons... */
9910 if (!IS_ITEMP(result)
9911 && IS_SYMOP (result)
9912 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9914 assert ( !"cannot write to CODESPACE" );
9917 /* if the result is a bit */
9918 if (AOP_TYPE(result) == AOP_CRY) {
9920 /* if the right size is a literal then
9921 we know what the value is */
9922 if (AOP_TYPE(right) == AOP_LIT) {
9924 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9925 popGet(AOP(result),0));
9927 if (((int) operandLitValue(right)))
9928 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9929 AOP(result)->aopu.aop_dir,
9930 AOP(result)->aopu.aop_dir);
9932 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9933 AOP(result)->aopu.aop_dir,
9934 AOP(result)->aopu.aop_dir);
9938 /* the right is also a bit variable */
9939 if (AOP_TYPE(right) == AOP_CRY) {
9940 emitpcode(POC_BCF, popGet(AOP(result),0));
9941 emitpcode(POC_BTFSC, popGet(AOP(right),0));
9942 emitpcode(POC_BSF, popGet(AOP(result),0));
9944 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9945 AOP(result)->aopu.aop_dir,
9946 AOP(result)->aopu.aop_dir);
9947 pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9948 AOP(right)->aopu.aop_dir,
9949 AOP(right)->aopu.aop_dir);
9950 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9951 AOP(result)->aopu.aop_dir,
9952 AOP(result)->aopu.aop_dir);
9957 emitpcode(POC_BCF, popGet(AOP(result),0));
9958 pic14_toBoolean(right);
9960 emitpcode(POC_BSF, popGet(AOP(result),0));
9961 //aopPut(AOP(result),"a",0);
9965 /* bit variables done */
9967 size = AOP_SIZE(result);
9969 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
9970 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9971 if(aopIdx(AOP(result),0) == 4) {
9972 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9973 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9974 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9977 DEBUGpic14_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
9983 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9984 if(AOP_TYPE(right) == AOP_LIT) {
9985 lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
9987 if(know_W != (int)(lit&0xff))
9988 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9990 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9992 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9994 } else if (AOP_TYPE(right) == AOP_CRY) {
9995 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9997 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9998 emitpcode(POC_INCF, popGet(AOP(result),0));
10001 mov2w_op (right, offset);
10002 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10010 freeAsmop (right,NULL,ic,FALSE);
10011 freeAsmop (result,NULL,ic,TRUE);
10014 /*-----------------------------------------------------------------*/
10015 /* genJumpTab - genrates code for jump table */
10016 /*-----------------------------------------------------------------*/
10017 static void genJumpTab (iCode *ic)
10023 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10025 aopOp(IC_JTCOND(ic),ic,FALSE);
10026 /* get the condition into accumulator */
10027 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10029 /* multiply by three */
10030 pic14_emitcode("add","a,acc");
10031 pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10033 jtab = newiTempLabel(NULL);
10034 pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10035 pic14_emitcode("jmp","@a+dptr");
10036 pic14_emitcode("","%05d_DS_:",jtab->key+100);
10038 emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10039 emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10040 emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10041 emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10043 emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10044 emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10045 emitpLabel(jtab->key);
10047 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10049 /* now generate the jump labels */
10050 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10051 jtab = setNextItem(IC_JTLABELS(ic))) {
10052 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10053 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10059 /*-----------------------------------------------------------------*/
10060 /* genMixedOperation - gen code for operators between mixed types */
10061 /*-----------------------------------------------------------------*/
10063 TSD - Written for the PIC port - but this unfortunately is buggy.
10064 This routine is good in that it is able to efficiently promote
10065 types to different (larger) sizes. Unfortunately, the temporary
10066 variables that are optimized out by this routine are sometimes
10067 used in other places. So until I know how to really parse the
10068 iCode tree, I'm going to not be using this routine :(.
10070 static int genMixedOperation (iCode *ic)
10074 operand *result = IC_RESULT(ic);
10075 sym_link *ctype = operandType(IC_LEFT(ic));
10076 operand *right = IC_RIGHT(ic);
10082 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10084 pic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10090 nextright = IC_RIGHT(nextic);
10091 nextleft = IC_LEFT(nextic);
10092 nextresult = IC_RESULT(nextic);
10094 aopOp(right,ic,FALSE);
10095 aopOp(result,ic,FALSE);
10096 aopOp(nextright, nextic, FALSE);
10097 aopOp(nextleft, nextic, FALSE);
10098 aopOp(nextresult, nextic, FALSE);
10100 if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10102 operand *t = right;
10106 pic14_emitcode(";remove right +","");
10108 } else if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10110 operand *t = right;
10114 pic14_emitcode(";remove left +","");
10118 big = AOP_SIZE(nextleft);
10119 small = AOP_SIZE(nextright);
10121 switch(nextic->op) {
10124 pic14_emitcode(";optimize a +","");
10125 /* if unsigned or not an integral type */
10126 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10127 pic14_emitcode(";add a bit to something","");
10130 pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10132 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10133 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10134 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10136 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10144 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10145 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10146 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10149 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10151 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10152 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10153 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10154 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10155 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10158 pic14_emitcode("rlf","known_zero,w");
10165 if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10166 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10167 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10169 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10179 freeAsmop(right,NULL,ic,TRUE);
10180 freeAsmop(result,NULL,ic,TRUE);
10181 freeAsmop(nextright,NULL,ic,TRUE);
10182 freeAsmop(nextleft,NULL,ic,TRUE);
10184 nextic->generated = 1;
10191 /*-----------------------------------------------------------------*/
10192 /* genCast - gen code for casting */
10193 /*-----------------------------------------------------------------*/
10194 static void genCast (iCode *ic)
10196 operand *result = IC_RESULT(ic);
10197 sym_link *restype = operandType(result);
10198 sym_link *rtype = operandType(IC_RIGHT(ic));
10199 operand *right = IC_RIGHT(ic);
10203 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10204 /* if they are equivalent then do nothing */
10205 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10208 aopOp(right,ic,FALSE) ;
10209 aopOp(result,ic,FALSE);
10211 DEBUGpic14_AopType(__LINE__,NULL,right,result);
10213 /* if the result is a bit */
10214 if (AOP_TYPE(result) == AOP_CRY) {
10215 assert(!"assigning to bit variables is not supported");
10218 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10220 size = AOP_SIZE(result);
10222 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10224 emitpcode(POC_CLRF, popGet(AOP(result),0));
10225 emitpcode(POC_BTFSC, popGet(AOP(right),0));
10226 emitpcode(POC_INCF, popGet(AOP(result),0));
10229 emitpcode(POC_CLRF, popGet(AOP(result),offset++));
10234 if (IS_PTR(restype))
10236 operand *result = IC_RESULT(ic);
10237 //operand *left = IC_LEFT(ic);
10238 operand *right = IC_RIGHT(ic);
10241 /* copy common part */
10242 int max, size = AOP_SIZE(result);
10243 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10244 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10246 /* warn if we discard generic opinter tag */
10247 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10249 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10255 mov2w_op (right, size);
10256 movwf (AOP(result), size);
10259 /* upcast into generic pointer type? */
10260 if (IS_GENPTR(restype)
10261 && (size < AOP_SIZE(result))
10262 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10264 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10267 switch (DCL_TYPE(rtype))
10269 case POINTER: /* __data */
10270 case FPOINTER: /* __data */
10271 assert (AOP_SIZE(right) == 2);
10272 tag = GPTRTAG_DATA;
10275 case CPOINTER: /* __code */
10276 assert (AOP_SIZE(right) == 2);
10277 tag = GPTRTAG_CODE;
10280 case GPOINTER: /* unknown destination, __data or __code */
10281 /* assume __data space (address of immediate) */
10282 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10283 if (AOP(right)->code)
10284 tag = GPTRTAG_CODE;
10286 tag = GPTRTAG_DATA;
10290 assert (!"unhandled pointer type");
10293 /* convert other values into pointers to __data space */
10294 tag = GPTRTAG_DATA;
10297 assert (AOP_SIZE(result) == 3);
10299 emitpcode(POC_CLRF, popGet(AOP(result), 2));
10301 emitpcode(POC_MOVLW, popGetLit(tag));
10302 movwf(AOP(result), 2);
10305 addSign(result, max, 0);
10310 /* if they are the same size : or less */
10311 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10313 /* if they are in the same place */
10314 if (pic14_sameRegs(AOP(right),AOP(result)))
10317 DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10318 if (IS_PTR_CONST(rtype))
10319 DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10320 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10321 DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10323 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10324 emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10325 emitpcode(POC_MOVWF, popGet(AOP(result),0));
10326 emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10327 emitpcode(POC_MOVWF, popGet(AOP(result),1));
10328 if(AOP_SIZE(result) <2)
10329 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10333 /* if they in different places then copy */
10334 size = AOP_SIZE(result);
10337 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10338 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10340 //aopPut(AOP(result),
10341 // aopGet(AOP(right),offset,FALSE,FALSE),
10350 /* so we now know that the size of destination is greater
10351 than the size of the source.
10352 Now, if the next iCode is an operator then we might be
10353 able to optimize the operation without performing a cast.
10355 if(0 && genMixedOperation(ic)) {
10356 /* XXX: cannot optimize: must copy regs! */
10360 /* we move to result for the size of source */
10361 size = AOP_SIZE(right);
10364 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10365 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10369 addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10372 freeAsmop(right,NULL,ic,TRUE);
10373 freeAsmop(result,NULL,ic,TRUE);
10377 /*-----------------------------------------------------------------*/
10378 /* genDjnz - generate decrement & jump if not zero instrucion */
10379 /*-----------------------------------------------------------------*/
10380 static int genDjnz (iCode *ic, iCode *ifx)
10382 symbol *lbl, *lbl1;
10384 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10389 /* if the if condition has a false label
10390 then we cannot save */
10394 /* if the minus is not of the form
10396 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10397 !IS_OP_LITERAL(IC_RIGHT(ic)))
10400 if (operandLitValue(IC_RIGHT(ic)) != 1)
10403 /* if the size of this greater than one then no
10405 if (getSize(operandType(IC_RESULT(ic))) > 1)
10408 /* otherwise we can save BIG */
10409 lbl = newiTempLabel(NULL);
10410 lbl1= newiTempLabel(NULL);
10412 aopOp(IC_RESULT(ic),ic,FALSE);
10414 if (IS_AOP_PREG(IC_RESULT(ic))) {
10415 pic14_emitcode("dec","%s",
10416 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10417 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10418 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10422 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10423 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10425 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10426 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10429 /* pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10430 /* pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10431 /* pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10432 /* pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10435 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10436 ifx->generated = 1;
10440 /*-----------------------------------------------------------------*/
10441 /* genReceive - generate code for a receive iCode */
10442 /*-----------------------------------------------------------------*/
10443 static void genReceive (iCode *ic)
10446 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10448 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10449 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10450 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10452 int size = getSize(operandType(IC_RESULT(ic)));
10453 int offset = fReturnSizePic - size;
10455 pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10456 fReturn[fReturnSizePic - offset - 1] : "acc"));
10459 aopOp(IC_RESULT(ic),ic,FALSE);
10460 size = AOP_SIZE(IC_RESULT(ic));
10463 pic14_emitcode ("pop","acc");
10464 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10469 aopOp(IC_RESULT(ic),ic,FALSE);
10471 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10472 assignResultValue(IC_RESULT(ic));
10475 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10478 /*-----------------------------------------------------------------*/
10479 /* genDummyRead - generate code for dummy read of volatiles */
10480 /*-----------------------------------------------------------------*/
10482 genDummyRead (iCode * ic)
10485 pic14_emitcode ("; genDummyRead","");
10486 pic14_emitcode ("; not implemented","");
10491 /*-----------------------------------------------------------------*/
10492 /* genpic14Code - generate code for pic14 based controllers */
10493 /*-----------------------------------------------------------------*/
10495 * At this point, ralloc.c has gone through the iCode and attempted
10496 * to optimize in a way suitable for a PIC. Now we've got to generate
10497 * PIC instructions that correspond to the iCode.
10499 * Once the instructions are generated, we'll pass through both the
10500 * peep hole optimizer and the pCode optimizer.
10501 *-----------------------------------------------------------------*/
10503 void genpic14Code (iCode *lic)
10510 lineHead = lineCurr = NULL;
10512 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10515 /* if debug information required */
10516 if (options.debug && debugFile && currFunc) {
10517 debugFile->writeFunction (currFunc, lic);
10521 for (ic = lic ; ic ; ic = ic->next ) {
10523 //DEBUGpic14_emitcode(";ic","");
10524 //fprintf (stderr, "in ic loop\n");
10525 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10526 //ic->lineno, printCLine(ic->filename, ic->lineno));
10528 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10530 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10531 cline = printCLine (ic->filename, ic->lineno);
10532 if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10533 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10534 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10537 if (options.iCodeInAsm) {
10538 char *iLine = printILine(ic);
10539 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10542 /* if the result is marked as
10543 spilt and rematerializable or code for
10544 this has already been generated then
10546 if (resultRemat(ic) || ic->generated )
10549 /* depending on the operation */
10568 /* IPOP happens only when trying to restore a
10569 spilt live range, if there is an ifx statement
10570 following this pop then the if statement might
10571 be using some of the registers being popped which
10572 would destory the contents of the register so
10573 we need to check for this condition and handle it */
10575 ic->next->op == IFX &&
10576 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10577 genIfx (ic->next,ic);
10595 genEndFunction (ic);
10615 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10632 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10636 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10643 /* note these two are xlated by algebraic equivalence
10644 during parsing SDCC.y */
10645 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10646 "got '>=' or '<=' shouldn't have come here");
10650 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10662 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10666 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10670 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10694 genRightShift (ic);
10697 case GET_VALUE_AT_ADDRESS:
10702 if (POINTER_SET(ic))
10729 addSet(&_G.sendSet,ic);
10732 case DUMMY_READ_VOLATILE:
10737 fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10744 /* now we are ready to call the
10745 peep hole optimizer */
10746 if (!options.nopeep) {
10747 peepHole (&lineHead);
10749 /* now do the actual printing */
10750 printLine (lineHead,codeOutBuf);
10753 DFPRINTF((stderr,"printing pBlock\n\n"));
10754 printpBlock(stdout,pb);
10760 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10761 * (meaning: representing its own address) or not (referencing its contents).
10762 * This can only be decided based on the operand's type. */
10764 aop_isLitLike (asmop *aop)
10767 if (aop->type == AOP_LIT) return 1;
10768 if (aop->type == AOP_IMMD) return 1;
10769 if ((aop->type == AOP_PCODE) &&
10770 ((aop->aopu.pcop->type == PO_LITERAL)))
10772 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10773 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10780 op_isLitLike (operand *op)
10783 if (aop_isLitLike (AOP(op))) return 1;
10784 if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10785 if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;