1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
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 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
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"
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
68 /* max_key keeps track of the largest label number used in
69 a function. This is then used to adjust the label offset
70 for the next function.
73 static int GpsuedoStkPtr=0;
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
80 void pic16_pushpCodeOp(pCodeOp *pcop);
81 void pic16_poppCodeOp(pCodeOp *pcop);
85 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
87 /* this is the down and dirty file with all kinds of
88 kludgy & hacky stuff. This is what it is all about
89 CODE GENERATION for a specific MCU . some of the
90 routines may be reusable, will have to see */
92 static char *zero = "#0x00";
93 static char *one = "#0x01";
94 static char *spname = "sp";
98 * Function return value policy (MSB-->LSB):
100 * 16 bits -> PRODL:WREG
101 * 24 bits -> PRODH:PRODL:WREG
102 * 32 bits -> FSR0L:PRODH:PRODL:WREG
103 * >32 bits -> on stack, and FSR0 points to the beginning
108 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
109 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
110 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
111 static char **fReturn = fReturnpic16;
113 static char *accUse[] = {"WREG"};
115 //static short rbank = -1;
128 /* Resolved ifx structure. This structure stores information
129 about an iCode ifx that makes it easier to generate code.
131 typedef struct resolvedIfx {
132 symbol *lbl; /* pointer to a label */
133 int condition; /* true or false ifx */
134 int generated; /* set true when the code associated with the ifx
138 extern int pic16_ptrRegReq ;
139 extern int pic16_nRegs;
140 extern FILE *codeOutFile;
141 static void saverbank (int, iCode *,bool);
143 static lineNode *lineHead = NULL;
144 static lineNode *lineCurr = NULL;
146 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
147 0xE0, 0xC0, 0x80, 0x00};
148 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
149 0x07, 0x03, 0x01, 0x00};
153 /*-----------------------------------------------------------------*/
154 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
155 /* exponent of 2 is returned, otherwise -1 is */
157 /* note that this is similar to the function `powof2' in SDCCsymt */
161 /*-----------------------------------------------------------------*/
162 static int my_powof2 (unsigned long num)
165 if( (num & (num-1)) == 0) {
178 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
180 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
182 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
183 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
184 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
185 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
186 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
187 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
188 ((result) ? AOP_SIZE(result) : 0));
191 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
194 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
196 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
197 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
198 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
199 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
200 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
201 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
205 void pic16_emitpcomment (char *fmt, ...)
208 char lb[INITIAL_INLINEASM];
214 vsprintf(lb+1,fmt,ap);
216 while (isspace(*lbp)) lbp++;
219 lineCurr = (lineCurr ?
220 connectLine(lineCurr,newLineNode(lb)) :
221 (lineHead = newLineNode(lb)));
222 lineCurr->isInline = _G.inLine;
223 lineCurr->isDebug = _G.debugLine;
225 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
228 // fprintf(stderr, "%s\n", lb);
231 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
234 char lb[INITIAL_INLINEASM];
237 if(!pic16_debug_verbose)
244 sprintf(lb,"%s\t",inst);
246 sprintf(lb,"%s",inst);
247 vsprintf(lb+(strlen(lb)),fmt,ap);
251 while (isspace(*lbp)) lbp++;
254 lineCurr = (lineCurr ?
255 connectLine(lineCurr,newLineNode(lb)) :
256 (lineHead = newLineNode(lb)));
257 lineCurr->isInline = _G.inLine;
258 lineCurr->isDebug = _G.debugLine;
260 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
263 // fprintf(stderr, "%s\n", lb);
266 void pic16_emitpLabel(int key)
268 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
271 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
275 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
277 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
279 // fprintf(stderr, "%s\n", pcop->name);
282 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
285 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
291 #define pic16_emitcode DEBUGpic16_emitcode
293 /*-----------------------------------------------------------------*/
294 /* pic16_emitcode - writes the code into a file : for now it is simple */
295 /*-----------------------------------------------------------------*/
296 void pic16_emitcode (char *inst,char *fmt, ...)
299 char lb[INITIAL_INLINEASM];
306 sprintf(lb,"%s\t",inst);
308 sprintf(lb,"%s",inst);
309 vsprintf(lb+(strlen(lb)),fmt,ap);
313 while (isspace(*lbp)) lbp++;
316 lineCurr = (lineCurr ?
317 connectLine(lineCurr,newLineNode(lb)) :
318 (lineHead = newLineNode(lb)));
319 lineCurr->isInline = _G.inLine;
320 lineCurr->isDebug = _G.debugLine;
322 // VR fprintf(stderr, "lb = <%s>\n", lbp);
324 // if(pic16_debug_verbose)
325 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
334 /*-----------------------------------------------------------------*/
335 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
337 bool r0iu = FALSE , r1iu = FALSE;
338 bool r0ou = FALSE , r1ou = FALSE;
340 //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
348 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
353 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
354 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
356 /* if no usage of r0 then return it */
357 if (!r0iu && !r0ou) {
358 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
364 /* if no usage of r1 then return it */
365 if (!r1iu && !r1ou) {
366 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
367 (*aopp)->type = AOP_R1;
369 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
372 /* now we know they both have usage */
373 /* if r0 not used in this instruction */
375 /* push it if not already pushed */
377 //pic16_emitcode ("push","%s",
378 // pic16_regWithIdx(R0_IDX)->dname);
382 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
383 (*aopp)->type = AOP_R0;
385 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
388 /* if r1 not used then */
391 /* push it if not already pushed */
393 //pic16_emitcode ("push","%s",
394 // pic16_regWithIdx(R1_IDX)->dname);
398 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
399 (*aopp)->type = AOP_R1;
400 return pic16_regWithIdx(R1_IDX);
404 /* I said end of world but not quite end of world yet */
405 /* if this is a result then we can push it on the stack*/
407 (*aopp)->type = AOP_STK;
411 /* other wise this is true end of the world */
412 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
413 "getFreePtr should never reach here");
417 /*-----------------------------------------------------------------*/
418 /* newAsmop - creates a new asmOp */
419 /*-----------------------------------------------------------------*/
420 static asmop *newAsmop (short type)
424 aop = Safe_calloc(1,sizeof(asmop));
429 static void genSetDPTR(int n)
433 pic16_emitcode(";", "Select standard DPTR");
434 pic16_emitcode("mov", "dps, #0x00");
438 pic16_emitcode(";", "Select alternate DPTR");
439 pic16_emitcode("mov", "dps, #0x01");
443 /*-----------------------------------------------------------------*/
444 /* resolveIfx - converts an iCode ifx into a form more useful for */
445 /* generating code */
446 /*-----------------------------------------------------------------*/
447 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
452 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
454 resIfx->condition = 1; /* assume that the ifx is true */
455 resIfx->generated = 0; /* indicate that the ifx has not been used */
458 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
460 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
461 __FUNCTION__,__LINE__,resIfx->lbl->key);
465 resIfx->lbl = IC_TRUE(ifx);
467 resIfx->lbl = IC_FALSE(ifx);
468 resIfx->condition = 0;
472 DEBUGpic16_emitcode("; ***","ifx true is non-null");
474 DEBUGpic16_emitcode("; ***","ifx false is non-null");
478 // DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
482 /*-----------------------------------------------------------------*/
483 /* pointerCode - returns the code for a pointer type */
484 /*-----------------------------------------------------------------*/
485 static int pointerCode (sym_link *etype)
488 return PTR_TYPE(SPEC_OCLS(etype));
492 /*-----------------------------------------------------------------*/
493 /* aopForSym - for a true symbol */
494 /*-----------------------------------------------------------------*/
495 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
498 memmap *space= SPEC_OCLS(sym->etype);
500 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
501 /* if already has one */
503 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
507 /* assign depending on the storage class */
508 /* if it is on the stack or indirectly addressable */
509 /* space we need to assign either r0 or r1 to it */
510 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
512 DEBUGpic16_emitcode("; ***", "sum->onStack || sym->iaccess");
514 sym->aop = aop = newAsmop(0);
515 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
516 aop->size = getSize(sym->type);
518 /* now assign the address of the variable to
519 the pointer register */
520 if (aop->type != AOP_STK) {
524 pic16_emitcode("push","acc");
526 pic16_emitcode("mov","a,_bp");
527 pic16_emitcode("add","a,#0x%02x",
529 ((char)(sym->stack - _G.nRegsSaved )) :
530 ((char)sym->stack)) & 0xff);
531 pic16_emitcode("mov","%s,a",
532 aop->aopu.aop_ptr->name);
535 pic16_emitcode("pop","acc");
537 pic16_emitcode("mov","%s,#%s",
538 aop->aopu.aop_ptr->name,
540 aop->paged = space->paged;
542 aop->aopu.aop_stk = sym->stack;
546 if (sym->onStack && options.stack10bit)
548 /* It's on the 10 bit stack, which is located in
552 //DEBUGpic16_emitcode(";","%d",__LINE__);
555 pic16_emitcode("push","acc");
557 pic16_emitcode("mov","a,_bp");
558 pic16_emitcode("add","a,#0x%02x",
560 ((char)(sym->stack - _G.nRegsSaved )) :
561 ((char)sym->stack)) & 0xff);
564 pic16_emitcode ("mov","dpx1,#0x40");
565 pic16_emitcode ("mov","dph1,#0x00");
566 pic16_emitcode ("mov","dpl1, a");
570 pic16_emitcode("pop","acc");
572 sym->aop = aop = newAsmop(AOP_DPTR2);
573 aop->size = getSize(sym->type);
577 //DEBUGpic16_emitcode(";","%d",__LINE__);
578 /* if in bit space */
579 if (IN_BITSPACE(space)) {
580 sym->aop = aop = newAsmop (AOP_CRY);
581 aop->aopu.aop_dir = sym->rname ;
582 aop->size = getSize(sym->type);
583 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
586 /* if it is in direct space */
587 if (IN_DIRSPACE(space)) {
588 sym->aop = aop = newAsmop (AOP_DIR);
589 aop->aopu.aop_dir = sym->rname ;
590 aop->size = getSize(sym->type);
591 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
592 pic16_allocDirReg( IC_LEFT(ic) );
597 /* special case for a function */
598 if (IS_FUNC(sym->type)) {
599 sym->aop = aop = newAsmop(AOP_IMMD);
600 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
601 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
602 strcpy(aop->aopu.aop_immd,sym->rname);
603 aop->size = FPTRSIZE;
604 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
610 /* only remaining is far space */
611 /* in which case DPTR gets the address */
612 sym->aop = aop = newAsmop(AOP_PCODE);
614 /* change the next if to 1 to revert to good old immediate code */
615 if(IN_CODESPACE(space)) {
616 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
617 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
618 PCOI(aop->aopu.pcop)->index = 0;
620 /* try to allocate via direct register */
621 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
622 // aop->size = getSize( sym->type );
625 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
626 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
629 if(!pic16_allocDirReg (IC_LEFT(ic)))
633 if(IN_DIRSPACE( space ))
635 else if(IN_CODESPACE( space ))
636 aop->size = FPTRSIZE;
637 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
638 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
643 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
645 /* if it is in code space */
646 if (IN_CODESPACE(space))
652 /*-----------------------------------------------------------------*/
653 /* aopForRemat - rematerialzes an object */
654 /*-----------------------------------------------------------------*/
655 static asmop *aopForRemat (operand *op) // x symbol *sym)
657 symbol *sym = OP_SYMBOL(op);
658 iCode *ic = NULL, *oldic;
659 asmop *aop = newAsmop(AOP_PCODE);
665 ic = sym->rematiCode;
667 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
669 if(IS_OP_POINTER(op)) {
670 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
676 // pic16_emitpcomment("ic: %s\n", printILine(ic));
679 val += (int) operandLitValue(IC_RIGHT(ic));
680 } else if (ic->op == '-') {
681 val -= (int) operandLitValue(IC_RIGHT(ic));
685 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
688 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
690 if(!op->isaddr)viaimmd++; else viaimmd=0;
692 /* set the following if to 1 to revert to good old immediate code */
693 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
696 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
698 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
701 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
703 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
706 PCOI(aop->aopu.pcop)->index = val;
708 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
710 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
711 // aop->size = AOP_SIZE( IC_LEFT(ic) );
715 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
716 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
718 val, IS_PTR_CONST(operandType(op)));
720 val, IS_CODEPTR(operandType(op)));
723 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
725 pic16_allocDirReg (IC_LEFT(ic));
727 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
733 static int aopIdx (asmop *aop, int offset)
738 if(aop->type != AOP_REG)
741 return aop->aopu.aop_reg[offset]->rIdx;
744 /*-----------------------------------------------------------------*/
745 /* regsInCommon - two operands have some registers in common */
746 /*-----------------------------------------------------------------*/
747 static bool regsInCommon (operand *op1, operand *op2)
752 /* if they have registers in common */
753 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
756 sym1 = OP_SYMBOL(op1);
757 sym2 = OP_SYMBOL(op2);
759 if (sym1->nRegs == 0 || sym2->nRegs == 0)
762 for (i = 0 ; i < sym1->nRegs ; i++) {
767 for (j = 0 ; j < sym2->nRegs ;j++ ) {
771 if (sym2->regs[j] == sym1->regs[i])
779 /*-----------------------------------------------------------------*/
780 /* operandsEqu - equivalent */
781 /*-----------------------------------------------------------------*/
782 static bool operandsEqu ( operand *op1, operand *op2)
786 /* if they not symbols */
787 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
790 sym1 = OP_SYMBOL(op1);
791 sym2 = OP_SYMBOL(op2);
793 /* if both are itemps & one is spilt
794 and the other is not then false */
795 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
796 sym1->isspilt != sym2->isspilt )
799 /* if they are the same */
803 if (strcmp(sym1->rname,sym2->rname) == 0)
807 /* if left is a tmp & right is not */
811 (sym1->usl.spillLoc == sym2))
818 (sym2->usl.spillLoc == sym1))
824 /*-----------------------------------------------------------------*/
825 /* pic16_sameRegs - two asmops have the same registers */
826 /*-----------------------------------------------------------------*/
827 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
834 if (aop1->type != AOP_REG ||
835 aop2->type != AOP_REG )
838 if (aop1->size != aop2->size )
841 for (i = 0 ; i < aop1->size ; i++ )
842 if (aop1->aopu.aop_reg[i] !=
843 aop2->aopu.aop_reg[i] )
849 /*-----------------------------------------------------------------*/
850 /* pic16_aopOp - allocates an asmop for an operand : */
851 /*-----------------------------------------------------------------*/
852 void pic16_aopOp (operand *op, iCode *ic, bool result)
861 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
863 /* if this a literal */
864 if (IS_OP_LITERAL(op)) {
865 op->aop = aop = newAsmop(AOP_LIT);
866 aop->aopu.aop_lit = op->operand.valOperand;
867 aop->size = getSize(operandType(op));
872 sym_link *type = operandType(op);
874 if(IS_PTR_CONST(type))
878 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
881 /* if already has a asmop then continue */
885 /* if the underlying symbol has a aop */
886 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
887 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
888 op->aop = OP_SYMBOL(op)->aop;
892 /* if this is a true symbol */
893 if (IS_TRUE_SYMOP(op)) {
894 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
895 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
899 /* this is a temporary : this has
905 e) can be a return use only */
909 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
910 /* if the type is a conditional */
911 if (sym->regType == REG_CND) {
912 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
917 /* if it is spilt then two situations
919 b) has a spill location */
920 if (sym->isspilt || sym->nRegs == 0) {
922 DEBUGpic16_emitcode(";","%d",__LINE__);
923 /* rematerialize it NOW */
926 sym->aop = op->aop = aop =
928 aop->size = getSize(sym->type);
929 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
936 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
937 aop->size = getSize(sym->type);
938 for ( i = 0 ; i < 1 ; i++ ) {
939 aop->aopu.aop_str[i] = accUse[i];
940 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
942 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
943 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
951 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
952 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
953 //pic16_allocDirReg (IC_LEFT(ic));
954 aop->size = getSize(sym->type);
959 aop = op->aop = sym->aop = newAsmop(AOP_STR);
960 aop->size = getSize(sym->type);
961 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
962 aop->aopu.aop_str[i] = fReturn[i];
964 DEBUGpic16_emitcode(";","%d",__LINE__);
968 /* else spill location */
969 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
970 /* force a new aop if sizes differ */
971 sym->usl.spillLoc->aop = NULL;
973 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
974 __FUNCTION__,__LINE__,
975 sym->usl.spillLoc->rname,
976 sym->rname, sym->usl.spillLoc->offset);
978 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
979 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
980 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
982 sym->usl.spillLoc->offset);
983 aop->size = getSize(sym->type);
989 sym_link *type = operandType(op);
991 if(IS_PTR_CONST(type))
995 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
998 /* must be in a register */
999 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1000 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1001 aop->size = sym->nRegs;
1002 for ( i = 0 ; i < sym->nRegs ;i++)
1003 aop->aopu.aop_reg[i] = sym->regs[i];
1006 /*-----------------------------------------------------------------*/
1007 /* pic16_freeAsmop - free up the asmop given to an operand */
1008 /*----------------------------------------------------------------*/
1009 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1026 /* depending on the asmop type only three cases need work AOP_RO
1027 , AOP_R1 && AOP_STK */
1029 switch (aop->type) {
1033 pic16_emitcode ("pop","ar0");
1037 bitVectUnSetBit(ic->rUsed,R0_IDX);
1043 pic16_emitcode ("pop","ar1");
1047 bitVectUnSetBit(ic->rUsed,R1_IDX);
1053 int stk = aop->aopu.aop_stk + aop->size;
1054 bitVectUnSetBit(ic->rUsed,R0_IDX);
1055 bitVectUnSetBit(ic->rUsed,R1_IDX);
1057 getFreePtr(ic,&aop,FALSE);
1059 if (options.stack10bit)
1061 /* I'm not sure what to do here yet... */
1064 "*** Warning: probably generating bad code for "
1065 "10 bit stack mode.\n");
1069 pic16_emitcode ("mov","a,_bp");
1070 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1071 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1073 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1077 pic16_emitcode("pop","acc");
1078 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1080 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1083 pic16_freeAsmop(op,NULL,ic,TRUE);
1085 pic16_emitcode("pop","ar0");
1090 pic16_emitcode("pop","ar1");
1098 /* all other cases just dealloc */
1102 OP_SYMBOL(op)->aop = NULL;
1103 /* if the symbol has a spill */
1105 SPIL_LOC(op)->aop = NULL;
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_aopGet - for fetching value of the aop */
1112 /*-----------------------------------------------------------------*/
1113 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1118 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1120 /* offset is greater than size then zero */
1121 if (offset > (aop->size - 1) &&
1122 aop->type != AOP_LIT)
1125 /* depending on type */
1126 switch (aop->type) {
1130 DEBUGpic16_emitcode(";","%d",__LINE__);
1131 /* if we need to increment it */
1132 while (offset > aop->coff) {
1133 pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1137 while (offset < aop->coff) {
1138 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1142 aop->coff = offset ;
1144 pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1145 return (dname ? "acc" : "a");
1147 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1148 rs = Safe_calloc(1,strlen(s)+1);
1154 DEBUGpic16_emitcode(";","%d",__LINE__);
1155 if (aop->type == AOP_DPTR2)
1160 while (offset > aop->coff) {
1161 pic16_emitcode ("inc","dptr");
1165 while (offset < aop->coff) {
1166 pic16_emitcode("lcall","__decdptr");
1172 pic16_emitcode("clr","a");
1173 pic16_emitcode("movc","a,@a+dptr");
1176 pic16_emitcode("movx","a,@dptr");
1179 if (aop->type == AOP_DPTR2)
1184 return (dname ? "acc" : "a");
1189 sprintf (s,"%s",aop->aopu.aop_immd);
1192 sprintf(s,"(%s >> %d)",
1197 aop->aopu.aop_immd);
1198 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1199 rs = Safe_calloc(1,strlen(s)+1);
1205 sprintf(s,"(%s + %d)",
1208 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1210 sprintf(s,"%s",aop->aopu.aop_dir);
1211 rs = Safe_calloc(1,strlen(s)+1);
1217 // return aop->aopu.aop_reg[offset]->dname;
1219 return aop->aopu.aop_reg[offset]->name;
1222 //pic16_emitcode(";","%d",__LINE__);
1223 return aop->aopu.aop_dir;
1226 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1227 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1229 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1232 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1233 rs = Safe_calloc(1,strlen(s)+1);
1238 aop->coff = offset ;
1239 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1242 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1244 return aop->aopu.aop_str[offset];
1248 pCodeOp *pcop = aop->aopu.pcop;
1249 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1251 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1252 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1253 sprintf(s,"%s", pcop->name);
1255 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1258 rs = Safe_calloc(1,strlen(s)+1);
1264 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1265 "aopget got unsupported aop->type");
1270 /*-----------------------------------------------------------------*/
1271 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1272 /*-----------------------------------------------------------------*/
1273 pCodeOp *pic16_popGetTempReg(void)
1277 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1278 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1279 PCOR(pcop)->r->wasUsed=1;
1280 PCOR(pcop)->r->isFree=0;
1282 /* push value on stack */
1283 pic16_pushpCodeOp( pcop );
1289 /*-----------------------------------------------------------------*/
1290 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1291 /*-----------------------------------------------------------------*/
1292 void pic16_popReleaseTempReg(pCodeOp *pcop)
1294 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1295 PCOR(pcop)->r->isFree = 1;
1297 pic16_poppCodeOp( pcop );
1300 /*-----------------------------------------------------------------*/
1301 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1302 /*-----------------------------------------------------------------*/
1303 pCodeOp *pic16_popGetLabel(unsigned int key)
1306 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1311 return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1314 /*-----------------------------------------------------------------*/
1315 /* pic16_popCopyReg - copy a pcode operator */
1316 /*-----------------------------------------------------------------*/
1317 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1321 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1322 pcor->pcop.type = pc->pcop.type;
1324 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1325 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1327 pcor->pcop.name = NULL;
1330 pcor->rIdx = pc->rIdx;
1333 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1338 /*-----------------------------------------------------------------*/
1339 /* pic16_popGetLit - asm operator to pcode operator conversion */
1340 /*-----------------------------------------------------------------*/
1341 pCodeOp *pic16_popGetLit(unsigned int lit)
1343 return pic16_newpCodeOpLit(lit);
1346 /*-----------------------------------------------------------------*/
1347 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1348 /*-----------------------------------------------------------------*/
1349 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1351 return pic16_newpCodeOpLit2(lit, arg2);
1355 /*-----------------------------------------------------------------*/
1356 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1357 /*-----------------------------------------------------------------*/
1358 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1360 return pic16_newpCodeOpImmd(name, offset,index, 0);
1364 /*-----------------------------------------------------------------*/
1365 /* pic16_popGet - asm operator to pcode operator conversion */
1366 /*-----------------------------------------------------------------*/
1367 pCodeOp *pic16_popGetWithString(char *str)
1373 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1377 pcop = pic16_newpCodeOp(str,PO_STR);
1382 /*-----------------------------------------------------------------*/
1383 /* pic16_popRegFromString - */
1384 /*-----------------------------------------------------------------*/
1385 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1388 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1389 pcop->type = PO_DIR;
1391 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1392 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1397 pcop->name = Safe_calloc(1,strlen(str)+1);
1398 strcpy(pcop->name,str);
1400 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1402 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1403 if(PCOR(pcop)->r == NULL) {
1404 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1405 // __FUNCTION__, __LINE__, str, size, offset);
1406 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1408 //fprintf(stderr, "allocating new register -> %s\n", str);
1410 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1412 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1414 PCOR(pcop)->instance = offset;
1419 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1423 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1425 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1426 PCOR(pcop)->rIdx = rIdx;
1427 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1428 PCOR(pcop)->r->isFree = 0;
1429 PCOR(pcop)->r->wasUsed = 1;
1431 pcop->type = PCOR(pcop)->r->pc_type;
1436 /*---------------------------------------------------------------------------------*/
1437 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1439 /*---------------------------------------------------------------------------------*/
1440 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1445 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1447 /* comment the following check, so errors to throw up */
1448 // if(!pcop2)return NULL;
1450 temp = pic16_popGet(aop_dst, offset);
1451 pcop2->pcop2 = temp;
1458 /*--------------------------------------------------------------------------------.-*/
1459 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1460 /* VR 030601 , adapted by Hans Dorn */
1461 /*--------------------------------------------------------------------------------.-*/
1462 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1466 pcop2 = (pCodeOpReg2 *)src;
1474 /*---------------------------------------------------------------------------------*/
1475 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1476 /* movff instruction */
1477 /*---------------------------------------------------------------------------------*/
1478 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1483 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1484 pcop2->pcop2 = pic16_popCopyReg(dst);
1486 /* the pCodeOp may be already allocated */
1487 pcop2 = (pCodeOpReg2 *)(src);
1488 pcop2->pcop2 = (pCodeOp *)(dst);
1495 /*-----------------------------------------------------------------*/
1496 /* pic16_popGet - asm operator to pcode operator conversion */
1497 /*-----------------------------------------------------------------*/
1498 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1500 //char *s = buffer ;
1504 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1505 /* offset is greater than
1508 // if (offset > (aop->size - 1) &&
1509 // aop->type != AOP_LIT)
1510 // return NULL; //zero;
1512 /* depending on type */
1513 switch (aop->type) {
1519 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1520 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1527 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1528 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1532 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1534 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1536 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1538 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1539 PCOR(pcop)->rIdx = rIdx;
1540 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1541 PCOR(pcop)->r->wasUsed=1;
1542 PCOR(pcop)->r->isFree=0;
1544 PCOR(pcop)->instance = offset;
1545 pcop->type = PCOR(pcop)->r->pc_type;
1546 // rs = aop->aopu.aop_reg[offset]->name;
1547 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1551 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1552 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1558 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1559 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1563 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1565 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1567 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1568 PCOR(pcop)->rIdx = rIdx;
1569 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1570 PCOR(pcop)->r->wasUsed=1;
1571 PCOR(pcop)->r->isFree=0;
1573 PCOR(pcop)->instance = offset;
1574 pcop->type = PCOR(pcop)->r->pc_type;
1575 rs = aop->aopu.aop_reg[offset]->name;
1576 DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1581 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1583 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1584 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1585 //if(PCOR(pcop)->r == NULL)
1586 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1590 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1591 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1594 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1595 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1598 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1600 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1601 pcop->type = PCOR(pcop)->r->pc_type;
1602 pcop->name = PCOR(pcop)->r->name;
1608 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1610 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1611 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1613 switch( aop->aopu.pcop->type ) {
1614 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1615 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1617 assert( 0 ); /* should never reach here */;
1620 PCOI(pcop)->offset = offset;
1625 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626 "pic16_popGet got unsupported aop->type");
1629 /*-----------------------------------------------------------------*/
1630 /* pic16_aopPut - puts a string for a aop */
1631 /*-----------------------------------------------------------------*/
1632 void pic16_aopPut (asmop *aop, char *s, int offset)
1637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1639 if (aop->size && offset > ( aop->size - 1)) {
1640 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1641 "pic16_aopPut got offset > aop->size");
1645 /* will assign value to value */
1646 /* depending on where it is ofcourse */
1647 switch (aop->type) {
1650 sprintf(d,"(%s + %d)",
1651 aop->aopu.aop_dir,offset);
1652 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1655 sprintf(d,"%s",aop->aopu.aop_dir);
1658 DEBUGpic16_emitcode(";","%d",__LINE__);
1660 pic16_emitcode("movf","%s,w",s);
1661 pic16_emitcode("movwf","%s",d);
1664 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1665 if(offset >= aop->size) {
1666 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1669 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1672 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1679 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1680 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1683 strcmp(s,"r0") == 0 ||
1684 strcmp(s,"r1") == 0 ||
1685 strcmp(s,"r2") == 0 ||
1686 strcmp(s,"r3") == 0 ||
1687 strcmp(s,"r4") == 0 ||
1688 strcmp(s,"r5") == 0 ||
1689 strcmp(s,"r6") == 0 ||
1690 strcmp(s,"r7") == 0 )
1691 pic16_emitcode("mov","%s,%s ; %d",
1692 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1696 if(strcmp(s,"W")==0 )
1697 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1699 pic16_emitcode("movwf","%s",
1700 aop->aopu.aop_reg[offset]->name);
1702 if(strcmp(s,zero)==0) {
1703 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1705 } else if(strcmp(s,"W")==0) {
1706 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1707 pcop->type = PO_GPR_REGISTER;
1709 PCOR(pcop)->rIdx = -1;
1710 PCOR(pcop)->r = NULL;
1712 DEBUGpic16_emitcode(";","%d",__LINE__);
1713 pcop->name = Safe_strdup(s);
1714 pic16_emitpcode(POC_MOVFW,pcop);
1715 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1716 } else if(strcmp(s,one)==0) {
1717 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1718 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1720 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1728 if (aop->type == AOP_DPTR2)
1734 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1735 "pic16_aopPut writting to code space");
1739 while (offset > aop->coff) {
1741 pic16_emitcode ("inc","dptr");
1744 while (offset < aop->coff) {
1746 pic16_emitcode("lcall","__decdptr");
1751 /* if not in accumulater */
1754 pic16_emitcode ("movx","@dptr,a");
1756 if (aop->type == AOP_DPTR2)
1764 while (offset > aop->coff) {
1766 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1768 while (offset < aop->coff) {
1770 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1776 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1781 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1783 if (strcmp(s,"r0") == 0 ||
1784 strcmp(s,"r1") == 0 ||
1785 strcmp(s,"r2") == 0 ||
1786 strcmp(s,"r3") == 0 ||
1787 strcmp(s,"r4") == 0 ||
1788 strcmp(s,"r5") == 0 ||
1789 strcmp(s,"r6") == 0 ||
1790 strcmp(s,"r7") == 0 ) {
1792 sprintf(buffer,"a%s",s);
1793 pic16_emitcode("mov","@%s,%s",
1794 aop->aopu.aop_ptr->name,buffer);
1796 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1801 if (strcmp(s,"a") == 0)
1802 pic16_emitcode("push","acc");
1804 pic16_emitcode("push","%s",s);
1809 /* if bit variable */
1810 if (!aop->aopu.aop_dir) {
1811 pic16_emitcode("clr","a");
1812 pic16_emitcode("rlc","a");
1815 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1818 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1821 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1823 lbl = newiTempLabel(NULL);
1825 if (strcmp(s,"a")) {
1828 pic16_emitcode("clr","c");
1829 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1830 pic16_emitcode("cpl","c");
1831 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1832 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1839 if (strcmp(aop->aopu.aop_str[offset],s))
1840 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1845 if (!offset && (strcmp(s,"acc") == 0))
1848 if (strcmp(aop->aopu.aop_str[offset],s))
1849 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1853 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1854 "pic16_aopPut got unsupported aop->type");
1860 /*-----------------------------------------------------------------*/
1861 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1862 /*-----------------------------------------------------------------*/
1863 static void mov2w (asmop *aop, int offset)
1869 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1871 if ( aop->type == AOP_PCODE ||
1872 aop->type == AOP_LIT )
1873 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1875 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1880 /* push pcop into stack */
1881 void pic16_pushpCodeOp(pCodeOp *pcop)
1883 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1886 /* pop pcop from stack */
1887 void pic16_poppCodeOp(pCodeOp *pcop)
1889 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1893 /*-----------------------------------------------------------------*/
1894 /* pushw - pushes wreg to stack */
1895 /*-----------------------------------------------------------------*/
1898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1899 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1903 /*-----------------------------------------------------------------*/
1904 /* pushaop - pushes aop to stack */
1905 /*-----------------------------------------------------------------*/
1906 void pushaop(asmop *aop, int offset)
1908 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1909 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1912 /*-----------------------------------------------------------------*/
1913 /* popaop - pops aop from stack */
1914 /*-----------------------------------------------------------------*/
1915 void popaop(asmop *aop, int offset)
1917 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1918 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1921 void popaopidx(asmop *aop, int offset, int index)
1925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1927 if(STACK_MODEL_LARGE)ofs++;
1929 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1930 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1933 /*-----------------------------------------------------------------*/
1934 /* reAdjustPreg - points a register back to where it should */
1935 /*-----------------------------------------------------------------*/
1936 static void reAdjustPreg (asmop *aop)
1940 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1942 if ((size = aop->size) <= 1)
1945 switch (aop->type) {
1949 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1953 if (aop->type == AOP_DPTR2)
1959 pic16_emitcode("lcall","__decdptr");
1962 if (aop->type == AOP_DPTR2)
1974 /*-----------------------------------------------------------------*/
1975 /* opIsGptr: returns non-zero if the passed operand is */
1976 /* a generic pointer type. */
1977 /*-----------------------------------------------------------------*/
1978 static int opIsGptr(operand *op)
1980 sym_link *type = operandType(op);
1982 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1983 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1991 /*-----------------------------------------------------------------*/
1992 /* pic16_getDataSize - get the operand data size */
1993 /*-----------------------------------------------------------------*/
1994 int pic16_getDataSize(operand *op)
1996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1999 return AOP_SIZE(op);
2001 // tsd- in the pic port, the genptr size is 1, so this code here
2002 // fails. ( in the 8051 port, the size was 4).
2005 size = AOP_SIZE(op);
2006 if (size == GPTRSIZE)
2008 sym_link *type = operandType(op);
2009 if (IS_GENPTR(type))
2011 /* generic pointer; arithmetic operations
2012 * should ignore the high byte (pointer type).
2015 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2022 /*-----------------------------------------------------------------*/
2023 /* pic16_outAcc - output Acc */
2024 /*-----------------------------------------------------------------*/
2025 void pic16_outAcc(operand *result)
2028 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2029 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2032 size = pic16_getDataSize(result);
2034 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2037 /* unsigned or positive */
2039 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2044 /*-----------------------------------------------------------------*/
2045 /* pic16_outBitC - output a bit C */
2046 /*-----------------------------------------------------------------*/
2047 void pic16_outBitC(operand *result)
2050 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2051 /* if the result is bit */
2052 if (AOP_TYPE(result) == AOP_CRY)
2053 pic16_aopPut(AOP(result),"c",0);
2055 pic16_emitcode("clr","a ; %d", __LINE__);
2056 pic16_emitcode("rlc","a");
2057 pic16_outAcc(result);
2061 /*-----------------------------------------------------------------*/
2062 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2063 /*-----------------------------------------------------------------*/
2064 void pic16_toBoolean(operand *oper)
2066 int size = AOP_SIZE(oper) - 1;
2069 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2071 if ( AOP_TYPE(oper) != AOP_ACC) {
2072 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2075 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2080 #if !defined(GEN_Not)
2081 /*-----------------------------------------------------------------*/
2082 /* genNot - generate code for ! operation */
2083 /*-----------------------------------------------------------------*/
2084 static void pic16_genNot (iCode *ic)
2089 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2090 /* assign asmOps to operand & result */
2091 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2092 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2094 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2095 /* if in bit space then a special case */
2096 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2097 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2098 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2099 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2101 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2102 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2103 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2108 size = AOP_SIZE(IC_LEFT(ic));
2110 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2111 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2112 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2115 pic16_toBoolean(IC_LEFT(ic));
2117 tlbl = newiTempLabel(NULL);
2118 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2119 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2120 pic16_outBitC(IC_RESULT(ic));
2123 /* release the aops */
2124 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2125 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2130 #if !defined(GEN_Cpl)
2131 /*-----------------------------------------------------------------*/
2132 /* genCpl - generate code for complement */
2133 /*-----------------------------------------------------------------*/
2134 static void pic16_genCpl (iCode *ic)
2140 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2141 /* assign asmOps to operand & result */
2142 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2143 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2145 /* if both are in bit space then
2147 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2148 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2150 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2151 pic16_emitcode("cpl","c");
2152 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2156 size = AOP_SIZE(IC_RESULT(ic));
2159 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2161 pic16_emitcode("cpl","a");
2162 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2164 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2165 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2167 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2168 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2176 /* release the aops */
2177 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2178 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2182 /*-----------------------------------------------------------------*/
2183 /* genUminusFloat - unary minus for floating points */
2184 /*-----------------------------------------------------------------*/
2185 static void genUminusFloat(operand *op,operand *result)
2187 int size ,offset =0 ;
2190 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2191 /* for this we just need to flip the
2192 first it then copy the rest in place */
2193 size = AOP_SIZE(op) - 1;
2194 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2198 pic16_emitcode("cpl","acc.7");
2199 pic16_aopPut(AOP(result),"a",3);
2202 pic16_aopPut(AOP(result),
2203 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2209 /*-----------------------------------------------------------------*/
2210 /* genUminus - unary minus code generation */
2211 /*-----------------------------------------------------------------*/
2212 static void genUminus (iCode *ic)
2215 sym_link *optype, *rtype;
2218 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2220 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2221 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2223 /* if both in bit space then special
2225 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2226 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2228 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2229 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2230 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2235 optype = operandType(IC_LEFT(ic));
2236 rtype = operandType(IC_RESULT(ic));
2238 /* if float then do float stuff */
2239 if (IS_FLOAT(optype)) {
2240 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2244 /* otherwise subtract from zero by taking the 2's complement */
2245 size = AOP_SIZE(IC_LEFT(ic));
2247 for(i=0; i<size; i++) {
2248 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2249 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2251 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2252 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2256 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2257 for(i=1; i<size; i++) {
2259 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2263 /* release the aops */
2264 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2265 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2268 /*-----------------------------------------------------------------*/
2269 /* saveRegisters - will look for a call and save the registers */
2270 /*-----------------------------------------------------------------*/
2271 static void saveRegisters(iCode *lic)
2278 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2280 for (ic = lic ; ic ; ic = ic->next)
2281 if (ic->op == CALL || ic->op == PCALL)
2285 fprintf(stderr,"found parameter push with no function call\n");
2289 /* if the registers have been saved already then
2291 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2294 /* find the registers in use at this time
2295 and push them away to safety */
2296 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2300 if (options.useXstack) {
2301 if (bitVectBitValue(rsave,R0_IDX))
2302 pic16_emitcode("mov","b,r0");
2303 pic16_emitcode("mov","r0,%s",spname);
2304 for (i = 0 ; i < pic16_nRegs ; i++) {
2305 if (bitVectBitValue(rsave,i)) {
2307 pic16_emitcode("mov","a,b");
2309 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2310 pic16_emitcode("movx","@r0,a");
2311 pic16_emitcode("inc","r0");
2314 pic16_emitcode("mov","%s,r0",spname);
2315 if (bitVectBitValue(rsave,R0_IDX))
2316 pic16_emitcode("mov","r0,b");
2318 //for (i = 0 ; i < pic16_nRegs ; i++) {
2319 // if (bitVectBitValue(rsave,i))
2320 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2323 dtype = operandType(IC_LEFT(ic));
2324 if (currFunc && dtype &&
2325 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2326 IFFUNC_ISISR(currFunc->type) &&
2329 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2332 /*-----------------------------------------------------------------*/
2333 /* unsaveRegisters - pop the pushed registers */
2334 /*-----------------------------------------------------------------*/
2335 static void unsaveRegisters (iCode *ic)
2340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2341 /* find the registers in use at this time
2342 and push them away to safety */
2343 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2346 if (options.useXstack) {
2347 pic16_emitcode("mov","r0,%s",spname);
2348 for (i = pic16_nRegs ; i >= 0 ; i--) {
2349 if (bitVectBitValue(rsave,i)) {
2350 pic16_emitcode("dec","r0");
2351 pic16_emitcode("movx","a,@r0");
2353 pic16_emitcode("mov","b,a");
2355 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2359 pic16_emitcode("mov","%s,r0",spname);
2360 if (bitVectBitValue(rsave,R0_IDX))
2361 pic16_emitcode("mov","r0,b");
2363 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2364 // if (bitVectBitValue(rsave,i))
2365 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2371 /*-----------------------------------------------------------------*/
2373 /*-----------------------------------------------------------------*/
2374 static void pushSide(operand * oper, int size)
2377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2379 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2380 if (AOP_TYPE(oper) != AOP_REG &&
2381 AOP_TYPE(oper) != AOP_DIR &&
2383 pic16_emitcode("mov","a,%s",l);
2384 pic16_emitcode("push","acc");
2386 pic16_emitcode("push","%s",l);
2391 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2393 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2395 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2396 pic16_emitpcode(POC_MOVFW, src);
2397 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2399 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2400 src, pic16_popGet(AOP(op), offset)));
2405 /*-----------------------------------------------------------------*/
2406 /* assignResultValue - assign results to oper, rescall==1 is */
2407 /* called from genCall() or genPCall() */
2408 /*-----------------------------------------------------------------*/
2409 static void assignResultValue(operand * oper, int rescall)
2411 int size = AOP_SIZE(oper);
2413 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2414 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2417 /* assign result from a call/pcall function() */
2419 /* function results are stored in a special order,
2420 * see top of file with Function return policy, or manual */
2423 /* 8-bits, result in WREG */
2424 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2427 /* 16-bits, result in PRODL:WREG */
2428 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2432 /* 24-bits, result in PRODH:PRODL:WREG */
2433 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2437 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2438 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2441 /* >32-bits, result on stack, and FSR0 points to beginning.
2442 * Fix stack when done */
2445 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2446 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2448 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2453 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2454 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2455 if(STACK_MODEL_LARGE) {
2457 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2461 if(!GpsuedoStkPtr) {
2462 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2463 /* The last byte in the assignment is in W */
2465 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2470 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2471 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2473 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2479 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2481 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2491 /*-----------------------------------------------------------------*/
2492 /* genIpush - genrate code for pushing this gets a little complex */
2493 /*-----------------------------------------------------------------*/
2494 static void genIpush (iCode *ic)
2497 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2499 int size, offset = 0 ;
2503 /* if this is not a parm push : ie. it is spill push
2504 and spill push is always done on the local stack */
2505 if (!ic->parmPush) {
2507 /* and the item is spilt then do nothing */
2508 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2511 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2512 size = AOP_SIZE(IC_LEFT(ic));
2513 /* push it on the stack */
2515 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2520 pic16_emitcode("push","%s",l);
2525 /* this is a paramter push: in this case we call
2526 the routine to find the call and save those
2527 registers that need to be saved */
2530 /* then do the push */
2531 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2534 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2535 size = AOP_SIZE(IC_LEFT(ic));
2538 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2539 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2540 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2542 pic16_emitcode("mov","a,%s",l);
2543 pic16_emitcode("push","acc");
2545 pic16_emitcode("push","%s",l);
2548 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2552 /*-----------------------------------------------------------------*/
2553 /* genIpop - recover the registers: can happen only for spilling */
2554 /*-----------------------------------------------------------------*/
2555 static void genIpop (iCode *ic)
2557 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2562 /* if the temp was not pushed then */
2563 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2566 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2567 size = AOP_SIZE(IC_LEFT(ic));
2570 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2573 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2577 /*-----------------------------------------------------------------*/
2578 /* unsaverbank - restores the resgister bank from stack */
2579 /*-----------------------------------------------------------------*/
2580 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2582 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2590 if (options.useXstack) {
2592 r = getFreePtr(ic,&aop,FALSE);
2595 pic16_emitcode("mov","%s,_spx",r->name);
2596 pic16_emitcode("movx","a,@%s",r->name);
2597 pic16_emitcode("mov","psw,a");
2598 pic16_emitcode("dec","%s",r->name);
2601 pic16_emitcode ("pop","psw");
2604 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2605 if (options.useXstack) {
2606 pic16_emitcode("movx","a,@%s",r->name);
2607 //pic16_emitcode("mov","(%s+%d),a",
2608 // regspic16[i].base,8*bank+regspic16[i].offset);
2609 pic16_emitcode("dec","%s",r->name);
2612 pic16_emitcode("pop",""); //"(%s+%d)",
2613 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2616 if (options.useXstack) {
2618 pic16_emitcode("mov","_spx,%s",r->name);
2619 pic16_freeAsmop(NULL,aop,ic,TRUE);
2625 /*-----------------------------------------------------------------*/
2626 /* saverbank - saves an entire register bank on the stack */
2627 /*-----------------------------------------------------------------*/
2628 static void saverbank (int bank, iCode *ic, bool pushPsw)
2630 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2636 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2637 if (options.useXstack) {
2640 r = getFreePtr(ic,&aop,FALSE);
2641 pic16_emitcode("mov","%s,_spx",r->name);
2645 for (i = 0 ; i < pic16_nRegs ;i++) {
2646 if (options.useXstack) {
2647 pic16_emitcode("inc","%s",r->name);
2648 //pic16_emitcode("mov","a,(%s+%d)",
2649 // regspic16[i].base,8*bank+regspic16[i].offset);
2650 pic16_emitcode("movx","@%s,a",r->name);
2652 pic16_emitcode("push","");// "(%s+%d)",
2653 //regspic16[i].base,8*bank+regspic16[i].offset);
2657 if (options.useXstack) {
2658 pic16_emitcode("mov","a,psw");
2659 pic16_emitcode("movx","@%s,a",r->name);
2660 pic16_emitcode("inc","%s",r->name);
2661 pic16_emitcode("mov","_spx,%s",r->name);
2662 pic16_freeAsmop (NULL,aop,ic,TRUE);
2665 pic16_emitcode("push","psw");
2667 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2675 /*-----------------------------------------------------------------*/
2676 /* genCall - generates a call statement */
2677 /*-----------------------------------------------------------------*/
2678 static void genCall (iCode *ic)
2683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2685 /* if caller saves & we have not saved then */
2689 /* if we are calling a function that is not using
2690 * the same register bank then we need to save the
2691 * destination registers on the stack */
2692 dtype = operandType(IC_LEFT(ic));
2693 if (currFunc && dtype &&
2694 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2695 IFFUNC_ISISR(currFunc->type) &&
2698 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2700 /* if send set is not empty the assign */
2704 /* For the Pic port, there is no data stack.
2705 * So parameters passed to functions are stored
2706 * in registers. (The pCode optimizer will get
2707 * rid of most of these :). */
2709 int psuedoStkPtr=-1;
2710 int firstTimeThruLoop = 1;
2712 _G.sendSet = reverseSet(_G.sendSet);
2714 /* First figure how many parameters are getting passed */
2715 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2716 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2717 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2718 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2721 stackParms = psuedoStkPtr;
2723 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2724 int size, offset = 0;
2726 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2727 size = AOP_SIZE(IC_LEFT(sic));
2730 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2731 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2732 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2734 if(!firstTimeThruLoop) {
2735 /* If this is not the first time we've been through the loop
2736 * then we need to save the parameter in a temporary
2737 * register. The last byte of the last parameter is
2741 --psuedoStkPtr; // sanity check
2744 firstTimeThruLoop=0;
2746 mov2w (AOP(IC_LEFT(sic)), offset);
2749 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2755 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2756 OP_SYMBOL(IC_LEFT(ic))->rname :
2757 OP_SYMBOL(IC_LEFT(ic))->name));
2760 /* if we need assign a result value */
2761 if ((IS_ITEMP(IC_RESULT(ic)) &&
2762 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2763 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2764 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2767 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2770 assignResultValue(IC_RESULT(ic), 1);
2772 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2773 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2775 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2779 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2780 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2781 if(STACK_MODEL_LARGE) {
2783 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2787 /* adjust the stack for parameters if required */
2788 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2790 if (ic->parmBytes) {
2793 if (ic->parmBytes > 3) {
2794 pic16_emitcode("mov","a,%s",spname);
2795 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2796 pic16_emitcode("mov","%s,a",spname);
2798 for ( i = 0 ; i < ic->parmBytes ;i++)
2799 pic16_emitcode("dec","%s",spname);
2802 /* if register bank was saved then pop them */
2804 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2806 /* if we hade saved some registers then unsave them */
2807 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2808 unsaveRegisters (ic);
2813 /*-----------------------------------------------------------------*/ // patch 14
2814 /* genPcall - generates a call by pointer statement */
2815 /*-----------------------------------------------------------------*/
2817 // new version, created from genCall
2819 static void genPcall (iCode *ic)
2823 symbol *retlbl = newiTempLabel(NULL);
2824 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2826 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2828 /* if caller saves & we have not saved then */
2832 /* if we are calling a function that is not using
2833 * the same register bank then we need to save the
2834 * destination registers on the stack */
2835 dtype = operandType(IC_LEFT(ic));
2836 if (currFunc && dtype &&
2837 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2838 IFFUNC_ISISR(currFunc->type) &&
2841 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2843 /* if send set is not empty the assign */
2847 /* For the Pic port, there is no data stack.
2848 * So parameters passed to functions are stored
2849 * in registers. (The pCode optimizer will get
2850 * rid of most of these :). */
2852 int psuedoStkPtr=-1;
2853 int firstTimeThruLoop = 1;
2855 _G.sendSet = reverseSet(_G.sendSet);
2857 /* First figure how many parameters are getting passed */
2858 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2859 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2860 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2861 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2864 stackParms = psuedoStkPtr;
2866 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2867 int size, offset = 0;
2869 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2870 size = AOP_SIZE(IC_LEFT(sic));
2873 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2874 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2875 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2877 if(!firstTimeThruLoop) {
2878 /* If this is not the first time we've been through the loop
2879 * then we need to save the parameter in a temporary
2880 * register. The last byte of the last parameter is
2884 --psuedoStkPtr; // sanity check
2887 firstTimeThruLoop=0;
2889 mov2w (AOP(IC_LEFT(sic)), offset);
2892 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2897 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2899 // push return address
2900 // push $ on return stack, then replace with retlbl
2902 // Note: retlbl is supplied as dummy operand to PUSH
2903 // This has the nice side effect of keeping the label from being optimized out :o)
2904 pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));
2906 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2907 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2908 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2909 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2910 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2911 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2913 /* make the call by writing the pointer into pc */
2914 // FIXME Disabled writes to PCLATU because of gpsim problems
2916 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2918 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2919 // note: MOVFF to PCL not allowed
2920 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2921 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2923 /* return address is here: (X) */
2924 pic16_emitpLabel(retlbl->key);
2926 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2929 /* if we need assign a result value */
2930 if ((IS_ITEMP(IC_RESULT(ic)) &&
2931 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2932 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2933 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2936 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2939 assignResultValue(IC_RESULT(ic), 1);
2941 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2942 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2944 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2948 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2949 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2950 if(STACK_MODEL_LARGE) {
2952 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2956 /* adjust the stack for parameters if required */
2957 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2959 if (ic->parmBytes) {
2962 if (ic->parmBytes > 3) {
2963 pic16_emitcode("mov","a,%s",spname);
2964 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2965 pic16_emitcode("mov","%s,a",spname);
2967 for ( i = 0 ; i < ic->parmBytes ;i++)
2968 pic16_emitcode("dec","%s",spname);
2971 /* if register bank was saved then pop them */
2973 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2975 /* if we hade saved some registers then unsave them */
2976 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2977 unsaveRegisters (ic);
2982 // old version, kept for reference
2984 /*-----------------------------------------------------------------*/
2985 /* genPcall - generates a call by pointer statement */
2986 /*-----------------------------------------------------------------*/
2987 static void genPcall (iCode *ic)
2990 symbol *rlbl = newiTempLabel(NULL);
2993 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2994 /* if caller saves & we have not saved then */
2998 /* if we are calling a function that is not using
2999 the same register bank then we need to save the
3000 destination registers on the stack */
3001 dtype = operandType(IC_LEFT(ic));
3002 if (currFunc && dtype &&
3003 IFFUNC_ISISR(currFunc->type) &&
3004 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3005 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3008 /* push the return address on to the stack */
3009 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3010 pic16_emitcode("push","acc");
3011 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3012 pic16_emitcode("push","acc");
3014 if (options.model == MODEL_FLAT24)
3016 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3017 pic16_emitcode("push","acc");
3020 /* now push the calling address */
3021 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3023 pushSide(IC_LEFT(ic), FPTRSIZE);
3025 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3027 /* if send set is not empty the assign */
3031 for (sic = setFirstItem(_G.sendSet) ; sic ;
3032 sic = setNextItem(_G.sendSet)) {
3033 int size, offset = 0;
3034 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3035 size = AOP_SIZE(IC_LEFT(sic));
3037 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3039 if (strcmp(l,fReturn[offset]))
3040 pic16_emitcode("mov","%s,%s",
3045 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3050 pic16_emitcode("ret","");
3051 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3054 /* if we need assign a result value */
3055 if ((IS_ITEMP(IC_RESULT(ic)) &&
3056 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3057 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3058 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3061 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3064 assignResultValue(IC_RESULT(ic), 1);
3066 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3069 /* adjust the stack for parameters if
3071 if (ic->parmBytes) {
3073 if (ic->parmBytes > 3) {
3074 pic16_emitcode("mov","a,%s",spname);
3075 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3076 pic16_emitcode("mov","%s,a",spname);
3078 for ( i = 0 ; i < ic->parmBytes ;i++)
3079 pic16_emitcode("dec","%s",spname);
3083 /* if register bank was saved then unsave them */
3084 if (currFunc && dtype &&
3085 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3086 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3088 /* if we hade saved some registers then
3091 unsaveRegisters (ic);
3097 /*-----------------------------------------------------------------*/
3098 /* resultRemat - result is rematerializable */
3099 /*-----------------------------------------------------------------*/
3100 static int resultRemat (iCode *ic)
3102 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3103 if (SKIP_IC(ic) || ic->op == IFX)
3106 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3107 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3108 if (sym->remat && !POINTER_SET(ic))
3115 #if defined(__BORLANDC__) || defined(_MSC_VER)
3116 #define STRCASECMP stricmp
3118 #define STRCASECMP strcasecmp
3122 /*-----------------------------------------------------------------*/
3123 /* inExcludeList - return 1 if the string is in exclude Reg list */
3124 /*-----------------------------------------------------------------*/
3125 static bool inExcludeList(char *s)
3127 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3131 if (options.excludeRegs[i] &&
3132 STRCASECMP(options.excludeRegs[i],"none") == 0)
3135 for ( i = 0 ; options.excludeRegs[i]; i++) {
3136 if (options.excludeRegs[i] &&
3137 STRCASECMP(s,options.excludeRegs[i]) == 0)
3144 /*-----------------------------------------------------------------*/
3145 /* genFunction - generated code for function entry */
3146 /*-----------------------------------------------------------------*/
3147 static void genFunction (iCode *ic)
3152 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3154 labelOffset += (max_key+4);
3159 ftype = operandType(IC_LEFT(ic));
3160 sym = OP_SYMBOL(IC_LEFT(ic));
3162 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3163 /* create an absolute section at the interrupt vector:
3164 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3172 sym = OP_SYMBOL( IC_LEFT(ic));
3174 if(interrupts[i]->name
3175 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3182 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3183 __FILE__, __LINE__, sym->name);
3186 _G.interruptvector = found;
3189 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3190 asym = newSymbol(asymname, 0);
3192 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3193 pic16_addpBlock( apb );
3195 pic16_addpCode2pBlock(apb,
3196 pic16_newpCodeCharP(";-----------------------------------------"));
3199 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3201 pic16_addpCode2pBlock(apb,
3202 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3204 /* mark the end of this tiny function */
3205 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3210 abSym = Safe_calloc(1, sizeof(absSym));
3211 abSym->name = Safe_strdup( asymname );
3213 switch( _G.interruptvector ) {
3214 case 0: abSym->address = 0x000000; break;
3215 case 1: abSym->address = 0x000008; break;
3216 case 2: abSym->address = 0x000018; break;
3219 addSet(&absSymSet, abSym);
3224 /* create the function header */
3225 pic16_emitcode(";","-----------------------------------------");
3226 pic16_emitcode(";"," function %s",sym->name);
3227 pic16_emitcode(";","-----------------------------------------");
3229 pic16_emitcode("","%s:",sym->rname);
3230 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3236 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3237 if(!strcmp(ab->name, sym->name)) {
3238 pic16_pBlockConvert2Absolute(pb);
3245 if(IFFUNC_ISNAKED(ftype)) {
3246 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3250 /* if critical function then turn interrupts off */
3251 if (IFFUNC_ISCRITICAL(ftype))
3252 pic16_emitcode("clr","ea");
3254 /* if this is an interrupt service routine then
3255 * save acc, b, dpl, dph */
3256 if (IFFUNC_ISISR(sym->type)) {
3258 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3259 if(!(_G.interruptvector == 1)) {
3261 /* do not save WREG,STATUS,BSR for high priority interrupts
3262 * because they are stored in the hardware shadow registers already */
3264 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3265 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3266 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3269 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3270 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3271 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3272 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3274 // pic16_pBlockConvert2ISR(pb);
3276 /* if any registers used */
3277 if (sym->regsUsed) {
3278 /* save the registers used */
3279 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3280 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3281 if (bitVectBitValue(sym->regsUsed,i)) {
3282 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3283 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3284 // pic16_regWithIdx(i)->name);
3286 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3292 /* emit code to setup stack frame if user enabled,
3293 * and function is not main() */
3295 // fprintf(stderr, "function name: %s\n", sym->name);
3296 if(strcmp(sym->name, "main")) {
3297 if(!options.ommitFramePtr || sym->regsUsed) {
3298 /* setup the stack frame */
3299 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3300 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3301 if(STACK_MODEL_LARGE)
3302 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3306 /* if callee-save to be used for this function
3307 * then save the registers being used in this function */
3308 if (IFFUNC_CALLEESAVES(sym->type)) {
3311 // fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
3313 /* if any registers used */
3314 if (sym->regsUsed) {
3315 /* save the registers used */
3316 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3317 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3318 if (bitVectBitValue(sym->regsUsed,i)) {
3320 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3321 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3322 // pic16_regWithIdx(i)->name);
3324 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3326 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3327 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3328 // &pic16_pc_postdec1, 0));
3340 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3342 if (options.useXstack) {
3343 pic16_emitcode("mov","r0,%s",spname);
3344 pic16_emitcode("mov","a,_bp");
3345 pic16_emitcode("movx","@r0,a");
3346 pic16_emitcode("inc","%s",spname);
3348 /* set up the stack */
3349 pic16_emitcode ("push","_bp"); /* save the callers stack */
3351 pic16_emitcode ("mov","_bp,%s",spname);
3354 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3356 /* adjust the stack for the function */
3361 werror(W_STACK_OVERFLOW,sym->name);
3363 if (i > 3 && sym->recvSize < 4) {
3364 pic16_emitcode ("mov","a,sp");
3365 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3366 pic16_emitcode ("mov","sp,a");
3369 pic16_emitcode("inc","sp");
3373 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3375 pic16_emitcode ("mov","a,_spx");
3376 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3377 pic16_emitcode ("mov","_spx,a");
3382 /*-----------------------------------------------------------------*/
3383 /* genEndFunction - generates epilogue for functions */
3384 /*-----------------------------------------------------------------*/
3385 static void genEndFunction (iCode *ic)
3387 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3391 if(IFFUNC_ISNAKED(sym->type)) {
3392 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3397 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3399 pic16_emitcode ("mov","%s,_bp",spname);
3403 /* if use external stack but some variables were
3404 added to the local stack then decrement the
3406 if (options.useXstack && sym->stack) {
3407 pic16_emitcode("mov","a,sp");
3408 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3409 pic16_emitcode("mov","sp,a");
3414 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3415 if (options.useXstack) {
3416 pic16_emitcode("mov","r0,%s",spname);
3417 pic16_emitcode("movx","a,@r0");
3418 pic16_emitcode("mov","_bp,a");
3419 pic16_emitcode("dec","%s",spname);
3423 pic16_emitcode ("pop","_bp");
3428 /* restore the register bank */
3429 if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3430 pic16_emitcode ("pop","psw");
3432 if (IFFUNC_ISISR(sym->type)) {
3434 /* now we need to restore the registers */
3436 /* if any registers used */
3437 if (sym->regsUsed) {
3440 /* restore registers used */
3441 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3442 for ( i = sym->regsUsed->size; i >= 0; i--) {
3443 if (bitVectBitValue(sym->regsUsed,i)) {
3444 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3445 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3446 // pic16_regWithIdx(i)->name);
3448 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3450 PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3455 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3456 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3457 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3458 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3460 if(!(_G.interruptvector == 1)) {
3461 /* do not restore interrupt vector for WREG,STATUS,BSR
3462 * for high priority interrupt, see genFunction */
3464 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3465 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3466 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3469 _G.interruptvector = 0; /* sanity check */
3471 // pic16_pBlockConvert2ISR(pb);
3474 /* if debug then send end of function */
3475 /* if (options.debug && currFunc) */
3478 pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3479 FileBaseName(ic->filename),currFunc->lastLine,
3480 ic->level,ic->block);
3481 if (IS_STATIC(currFunc->etype))
3482 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
3484 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3489 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_status));
3490 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3491 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_status));
3492 pic16_emitpcode(POC_SWAPF, pic16_popCopyReg(&pic16_pc_wsave));
3493 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3496 pic16_emitpcodeNULLop(POC_RETFIE);
3499 if (IFFUNC_ISCRITICAL(sym->type))
3500 pic16_emitcode("setb","ea");
3502 /* if any registers used */
3503 if (sym->regsUsed) {
3505 /* save the registers used */
3506 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3507 for ( i = sym->regsUsed->size; i >= 0; i--) {
3508 if (bitVectBitValue(sym->regsUsed,i)) {
3509 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3510 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3511 // pic16_regWithIdx(i)->name);
3513 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3515 PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3521 /* if debug then send end of function */
3524 pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3525 FileBaseName(ic->filename),currFunc->lastLine,
3526 ic->level,ic->block);
3527 if (IS_STATIC(currFunc->etype))
3528 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
3530 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3534 /* insert code to restore stack frame, if user enabled it
3535 * and function is not main() */
3537 if(strcmp(sym->name, "main")) {
3538 if(!options.ommitFramePtr || sym->regsUsed) {
3539 /* restore stack frame */
3540 if(STACK_MODEL_LARGE)
3541 pic16_emitpcode(POC_MOVFF,
3542 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3543 pic16_emitpcode(POC_MOVFF,
3544 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3548 pic16_emitcode ("return","");
3549 pic16_emitpcodeNULLop(POC_RETURN);
3551 /* Mark the end of a function */
3552 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3558 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3560 // (AOP(left)->aopu.pcop->type == PO_DIR)?
3562 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3563 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3564 pic16_emitpcode(POC_MOVWF, dest);
3566 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3567 pic16_popGet(AOP(op), offset), dest));
3571 /*-----------------------------------------------------------------*/
3572 /* genRet - generate code for return statement */
3573 /*-----------------------------------------------------------------*/
3574 static void genRet (iCode *ic)
3579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3580 /* if we have no return value then
3581 * just generate the "ret" */
3586 /* we have something to return then
3587 * move the return value into place */
3588 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3589 size = AOP_SIZE(IC_LEFT(ic));
3593 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3594 // pic16_emitpcode(POC_MOVFF,
3595 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3598 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3599 // pic16_emitpcode(POC_MOVFF,
3600 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3603 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3604 // pic16_emitpcode(POC_MOVFF,
3605 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3608 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3610 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3611 // pic16_emitpcode(POC_MOVFF,
3612 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3615 /* >32-bits, setup stack and FSR0 */
3617 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3618 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3620 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3622 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3627 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3628 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3630 if(STACK_MODEL_LARGE) {
3631 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3632 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3634 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3639 /* old code, left here for reference -- VR */
3643 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3645 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3646 pic16_emitpcomment("push %s",l);
3649 DEBUGpic16_emitcode(";", "%d", __LINE__);
3650 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3651 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3653 if (strcmp(fReturn[offset],l)) {
3654 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3655 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3656 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3658 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3662 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3672 if (strcmp(fReturn[pushed],"a"))
3673 pic16_emitcode("pop",fReturn[pushed]);
3675 pic16_emitcode("pop","acc");
3681 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3684 /* generate a jump to the return label
3685 * if the next is not the return statement */
3686 if (!(ic->next && ic->next->op == LABEL
3687 && IC_LABEL(ic->next) == returnLabel)) {
3689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3690 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3694 /*-----------------------------------------------------------------*/
3695 /* genLabel - generates a label */
3696 /*-----------------------------------------------------------------*/
3697 static void genLabel (iCode *ic)
3699 /* special case never generate */
3700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3701 if (IC_LABEL(ic) == entryLabel)
3704 pic16_emitpLabel(IC_LABEL(ic)->key);
3705 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3708 /*-----------------------------------------------------------------*/
3709 /* genGoto - generates a goto */
3710 /*-----------------------------------------------------------------*/
3712 static void genGoto (iCode *ic)
3714 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3715 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3719 /*-----------------------------------------------------------------*/
3720 /* genMultbits :- multiplication of bits */
3721 /*-----------------------------------------------------------------*/
3722 static void genMultbits (operand *left,
3726 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3728 if(!pic16_sameRegs(AOP(result),AOP(right)))
3729 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3731 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3732 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3733 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3738 /*-----------------------------------------------------------------*/
3739 /* genMultOneByte : 8 bit multiplication & division */
3740 /*-----------------------------------------------------------------*/
3741 static void genMultOneByte (operand *left,
3745 sym_link *opetype = operandType(result);
3750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3751 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3752 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3754 /* (if two literals, the value is computed before) */
3755 /* if one literal, literal on the right */
3756 if (AOP_TYPE(left) == AOP_LIT){
3762 size = AOP_SIZE(result);
3765 if (AOP_TYPE(right) == AOP_LIT){
3766 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3767 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3768 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3769 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3771 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3772 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3773 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3774 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3776 pic16_genMult8X8_8 (left, right,result);
3777 } else { // (size > 1)
3779 pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s",
3780 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3781 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3782 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3784 if (SPEC_USIGN(opetype)){
3785 pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3786 pic16_genUMult8X8_16 (left, right, result, NULL);
3789 /* for filling the MSBs */
3790 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),2));
3791 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),3));
3795 pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3797 pic16_emitcode("mov","a,b");
3799 /* adjust the MSB if left or right neg */
3801 /* if one literal */
3802 if (AOP_TYPE(right) == AOP_LIT){
3803 pic16_emitcode("multiply ","right is a lit");
3804 /* AND literal negative */
3805 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3806 /* adjust MSB (c==0 after mul) */
3807 pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3811 pic16_genSMult8X8_16 (left, right, result, NULL);
3815 pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3817 pic16_emitcode("rlc","a");
3818 pic16_emitcode("subb","a,acc");
3826 pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3827 //pic16_aopPut(AOP(result),"a",offset++);
3831 /*-----------------------------------------------------------------*/
3832 /* genMult - generates code for multiplication */
3833 /*-----------------------------------------------------------------*/
3834 static void genMult (iCode *ic)
3836 operand *left = IC_LEFT(ic);
3837 operand *right = IC_RIGHT(ic);
3838 operand *result= IC_RESULT(ic);
3840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3841 /* assign the amsops */
3842 pic16_aopOp (left,ic,FALSE);
3843 pic16_aopOp (right,ic,FALSE);
3844 pic16_aopOp (result,ic,TRUE);
3846 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3848 /* special cases first */
3850 if (AOP_TYPE(left) == AOP_CRY &&
3851 AOP_TYPE(right)== AOP_CRY) {
3852 genMultbits(left,right,result);
3856 /* if both are of size == 1 */
3857 if (AOP_SIZE(left) == 1 &&
3858 AOP_SIZE(right) == 1 ) {
3859 genMultOneByte(left,right,result);
3863 pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3865 /* should have been converted to function call */
3869 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3870 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3871 pic16_freeAsmop(result,NULL,ic,TRUE);
3874 /*-----------------------------------------------------------------*/
3875 /* genDivbits :- division of bits */
3876 /*-----------------------------------------------------------------*/
3877 static void genDivbits (operand *left,
3884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3885 /* the result must be bit */
3886 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3887 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3891 pic16_emitcode("div","ab");
3892 pic16_emitcode("rrc","a");
3893 pic16_aopPut(AOP(result),"c",0);
3896 /*-----------------------------------------------------------------*/
3897 /* genDivOneByte : 8 bit division */
3898 /*-----------------------------------------------------------------*/
3899 static void genDivOneByte (operand *left,
3903 sym_link *opetype = operandType(result);
3908 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3909 size = AOP_SIZE(result) - 1;
3911 /* signed or unsigned */
3912 if (SPEC_USIGN(opetype)) {
3913 /* unsigned is easy */
3914 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3915 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3917 pic16_emitcode("div","ab");
3918 pic16_aopPut(AOP(result),"a",0);
3920 pic16_aopPut(AOP(result),zero,offset++);
3924 /* signed is a little bit more difficult */
3926 /* save the signs of the operands */
3927 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3929 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3930 pic16_emitcode("push","acc"); /* save it on the stack */
3932 /* now sign adjust for both left & right */
3933 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
3935 lbl = newiTempLabel(NULL);
3936 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3937 pic16_emitcode("cpl","a");
3938 pic16_emitcode("inc","a");
3939 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3940 pic16_emitcode("mov","b,a");
3942 /* sign adjust left side */
3943 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3946 lbl = newiTempLabel(NULL);
3947 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3948 pic16_emitcode("cpl","a");
3949 pic16_emitcode("inc","a");
3950 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3952 /* now the division */
3953 pic16_emitcode("div","ab");
3954 /* we are interested in the lower order
3956 pic16_emitcode("mov","b,a");
3957 lbl = newiTempLabel(NULL);
3958 pic16_emitcode("pop","acc");
3959 /* if there was an over flow we don't
3960 adjust the sign of the result */
3961 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3962 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3964 pic16_emitcode("clr","a");
3965 pic16_emitcode("subb","a,b");
3966 pic16_emitcode("mov","b,a");
3967 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3969 /* now we are done */
3970 pic16_aopPut(AOP(result),"b",0);
3972 pic16_emitcode("mov","c,b.7");
3973 pic16_emitcode("subb","a,acc");
3976 pic16_aopPut(AOP(result),"a",offset++);
3980 /*-----------------------------------------------------------------*/
3981 /* genDiv - generates code for division */
3982 /*-----------------------------------------------------------------*/
3983 static void genDiv (iCode *ic)
3985 operand *left = IC_LEFT(ic);
3986 operand *right = IC_RIGHT(ic);
3987 operand *result= IC_RESULT(ic);
3989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3990 /* assign the amsops */
3991 pic16_aopOp (left,ic,FALSE);
3992 pic16_aopOp (right,ic,FALSE);
3993 pic16_aopOp (result,ic,TRUE);
3995 /* special cases first */
3997 if (AOP_TYPE(left) == AOP_CRY &&
3998 AOP_TYPE(right)== AOP_CRY) {
3999 genDivbits(left,right,result);
4003 /* if both are of size == 1 */
4004 if (AOP_SIZE(left) == 1 &&
4005 AOP_SIZE(right) == 1 ) {
4006 genDivOneByte(left,right,result);
4010 /* should have been converted to function call */
4013 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4014 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4015 pic16_freeAsmop(result,NULL,ic,TRUE);
4018 /*-----------------------------------------------------------------*/
4019 /* genModbits :- modulus of bits */
4020 /*-----------------------------------------------------------------*/
4021 static void genModbits (operand *left,
4028 /* the result must be bit */
4029 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4030 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4034 pic16_emitcode("div","ab");
4035 pic16_emitcode("mov","a,b");
4036 pic16_emitcode("rrc","a");
4037 pic16_aopPut(AOP(result),"c",0);
4040 /*-----------------------------------------------------------------*/
4041 /* genModOneByte : 8 bit modulus */
4042 /*-----------------------------------------------------------------*/
4043 static void genModOneByte (operand *left,
4047 sym_link *opetype = operandType(result);
4051 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4052 /* signed or unsigned */
4053 if (SPEC_USIGN(opetype)) {
4054 /* unsigned is easy */
4055 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4056 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4058 pic16_emitcode("div","ab");
4059 pic16_aopPut(AOP(result),"b",0);
4063 /* signed is a little bit more difficult */
4065 /* save the signs of the operands */
4066 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4069 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4070 pic16_emitcode("push","acc"); /* save it on the stack */
4072 /* now sign adjust for both left & right */
4073 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4076 lbl = newiTempLabel(NULL);
4077 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4078 pic16_emitcode("cpl","a");
4079 pic16_emitcode("inc","a");
4080 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4081 pic16_emitcode("mov","b,a");
4083 /* sign adjust left side */
4084 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4087 lbl = newiTempLabel(NULL);
4088 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4089 pic16_emitcode("cpl","a");
4090 pic16_emitcode("inc","a");
4091 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4093 /* now the multiplication */
4094 pic16_emitcode("div","ab");
4095 /* we are interested in the lower order
4097 lbl = newiTempLabel(NULL);
4098 pic16_emitcode("pop","acc");
4099 /* if there was an over flow we don't
4100 adjust the sign of the result */
4101 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4102 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4104 pic16_emitcode("clr","a");
4105 pic16_emitcode("subb","a,b");
4106 pic16_emitcode("mov","b,a");
4107 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4109 /* now we are done */
4110 pic16_aopPut(AOP(result),"b",0);
4114 /*-----------------------------------------------------------------*/
4115 /* genMod - generates code for division */
4116 /*-----------------------------------------------------------------*/
4117 static void genMod (iCode *ic)
4119 operand *left = IC_LEFT(ic);
4120 operand *right = IC_RIGHT(ic);
4121 operand *result= IC_RESULT(ic);
4123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4124 /* assign the amsops */
4125 pic16_aopOp (left,ic,FALSE);
4126 pic16_aopOp (right,ic,FALSE);
4127 pic16_aopOp (result,ic,TRUE);
4129 /* special cases first */
4131 if (AOP_TYPE(left) == AOP_CRY &&
4132 AOP_TYPE(right)== AOP_CRY) {
4133 genModbits(left,right,result);
4137 /* if both are of size == 1 */
4138 if (AOP_SIZE(left) == 1 &&
4139 AOP_SIZE(right) == 1 ) {
4140 genModOneByte(left,right,result);
4144 /* should have been converted to function call */
4148 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4149 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4150 pic16_freeAsmop(result,NULL,ic,TRUE);
4153 /*-----------------------------------------------------------------*/
4154 /* genIfxJump :- will create a jump depending on the ifx */
4155 /*-----------------------------------------------------------------*/
4157 note: May need to add parameter to indicate when a variable is in bit space.
4159 static void genIfxJump (iCode *ic, char *jval)
4162 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4163 /* if true label then we jump if condition
4165 if ( IC_TRUE(ic) ) {
4167 if(strcmp(jval,"a") == 0)
4169 else if (strcmp(jval,"c") == 0)
4172 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4173 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1));
4176 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4177 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4181 /* false label is present */
4182 if(strcmp(jval,"a") == 0)
4184 else if (strcmp(jval,"c") == 0)
4187 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4188 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1));
4191 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4192 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4197 /* mark the icode as generated */
4201 /*-----------------------------------------------------------------*/
4203 /*-----------------------------------------------------------------*/
4204 static void genSkip(iCode *ifx,int status_bit)
4206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4210 if ( IC_TRUE(ifx) ) {
4211 switch(status_bit) {
4226 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4227 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4231 switch(status_bit) {
4245 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4246 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4252 /*-----------------------------------------------------------------*/
4254 /*-----------------------------------------------------------------*/
4255 static void genSkipc(resolvedIfx *rifx)
4265 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4266 rifx->generated = 1;
4269 /*-----------------------------------------------------------------*/
4271 /*-----------------------------------------------------------------*/
4272 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4277 if( (rifx->condition ^ invert_condition) & 1)
4282 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4283 rifx->generated = 1;
4287 /*-----------------------------------------------------------------*/
4289 /*-----------------------------------------------------------------*/
4290 static void genSkipz(iCode *ifx, int condition)
4301 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4303 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4306 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4308 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4313 /*-----------------------------------------------------------------*/
4315 /*-----------------------------------------------------------------*/
4316 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4322 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4324 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4327 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4328 rifx->generated = 1;
4332 /*-----------------------------------------------------------------*/
4333 /* genChkZeroes :- greater or less than comparison */
4334 /* For each byte in a literal that is zero, inclusive or the */
4335 /* the corresponding byte in the operand with W */
4336 /* returns true if any of the bytes are zero */
4337 /*-----------------------------------------------------------------*/
4338 static int genChkZeroes(operand *op, int lit, int size)
4345 i = (lit >> (size*8)) & 0xff;
4349 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4351 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4360 /*-----------------------------------------------------------------*/
4361 /* genCmp :- greater or less than comparison */
4362 /*-----------------------------------------------------------------*/
4363 static void genCmp (operand *left,operand *right,
4364 operand *result, iCode *ifx, int sign)
4366 int size; //, offset = 0 ;
4367 unsigned long lit = 0L,i = 0;
4368 resolvedIfx rFalseIfx;
4369 // resolvedIfx rTrueIfx;
4371 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4374 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4375 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4379 resolveIfx(&rFalseIfx,ifx);
4380 truelbl = newiTempLabel(NULL);
4381 size = max(AOP_SIZE(left),AOP_SIZE(right));
4383 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4387 /* if literal is on the right then swap with left */
4388 if ((AOP_TYPE(right) == AOP_LIT)) {
4389 operand *tmp = right ;
4390 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4391 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4394 lit = (lit - 1) & mask;
4397 rFalseIfx.condition ^= 1;
4400 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4401 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4405 //if(IC_TRUE(ifx) == NULL)
4406 /* if left & right are bit variables */
4407 if (AOP_TYPE(left) == AOP_CRY &&
4408 AOP_TYPE(right) == AOP_CRY ) {
4409 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4410 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4412 /* subtract right from left if at the
4413 end the carry flag is set then we know that
4414 left is greater than right */
4418 symbol *lbl = newiTempLabel(NULL);
4421 if(AOP_TYPE(right) == AOP_LIT) {
4423 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4425 DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4432 genSkipCond(&rFalseIfx,left,size-1,7);
4434 /* no need to compare to 0...*/
4435 /* NOTE: this is a de-generate compare that most certainly
4436 * creates some dead code. */
4437 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4439 if(ifx) ifx->generated = 1;
4446 //i = (lit >> (size*8)) & 0xff;
4447 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4449 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4451 i = ((0-lit) & 0xff);
4454 /* lit is 0x7f, all signed chars are less than
4455 * this except for 0x7f itself */
4456 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4457 genSkipz2(&rFalseIfx,0);
4459 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4460 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4461 genSkipc(&rFalseIfx);
4466 genSkipz2(&rFalseIfx,1);
4468 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4469 genSkipc(&rFalseIfx);
4473 if(ifx) ifx->generated = 1;
4477 /* chars are out of the way. now do ints and longs */
4480 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4487 genSkipCond(&rFalseIfx,left,size,7);
4488 if(ifx) ifx->generated = 1;
4493 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4495 //rFalseIfx.condition ^= 1;
4496 //genSkipCond(&rFalseIfx,left,size,7);
4497 //rFalseIfx.condition ^= 1;
4499 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4500 if(rFalseIfx.condition)
4501 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4503 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4505 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4506 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4507 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4510 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4512 if(rFalseIfx.condition) {
4514 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4520 genSkipc(&rFalseIfx);
4521 pic16_emitpLabel(truelbl->key);
4522 if(ifx) ifx->generated = 1;
4529 if( (lit & 0xff) == 0) {
4530 /* lower byte is zero */
4531 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4532 i = ((lit >> 8) & 0xff) ^0x80;
4533 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4534 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4535 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4536 genSkipc(&rFalseIfx);
4539 if(ifx) ifx->generated = 1;
4544 /* Special cases for signed longs */
4545 if( (lit & 0xffffff) == 0) {
4546 /* lower byte is zero */
4547 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4548 i = ((lit >> 8*3) & 0xff) ^0x80;
4549 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4550 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4551 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4552 genSkipc(&rFalseIfx);
4555 if(ifx) ifx->generated = 1;
4563 if(lit & (0x80 << (size*8))) {
4564 /* lit is negative */
4565 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4567 //genSkipCond(&rFalseIfx,left,size,7);
4569 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4571 if(rFalseIfx.condition)
4572 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4574 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4578 /* lit is positive */
4579 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4580 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4581 if(rFalseIfx.condition)
4582 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4584 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4589 This works, but is only good for ints.
4590 It also requires a "known zero" register.
4591 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4592 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4593 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4594 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4595 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4596 genSkipc(&rFalseIfx);
4598 pic16_emitpLabel(truelbl->key);
4599 if(ifx) ifx->generated = 1;
4603 /* There are no more special cases, so perform a general compare */
4605 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4606 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4610 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4612 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4614 //rFalseIfx.condition ^= 1;
4615 genSkipc(&rFalseIfx);
4617 pic16_emitpLabel(truelbl->key);
4619 if(ifx) ifx->generated = 1;
4626 /* sign is out of the way. So now do an unsigned compare */
4627 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4630 /* General case - compare to an unsigned literal on the right.*/
4632 i = (lit >> (size*8)) & 0xff;
4633 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4634 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4636 i = (lit >> (size*8)) & 0xff;
4639 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4641 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4643 /* this byte of the lit is zero,
4644 *if it's not the last then OR in the variable */
4646 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4651 pic16_emitpLabel(lbl->key);
4652 //if(emitFinalCheck)
4653 genSkipc(&rFalseIfx);
4655 pic16_emitpLabel(truelbl->key);
4657 if(ifx) ifx->generated = 1;
4664 if(AOP_TYPE(left) == AOP_LIT) {
4665 //symbol *lbl = newiTempLabel(NULL);
4667 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4670 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4673 if((lit == 0) && (sign == 0)){
4676 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4678 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4680 genSkipz2(&rFalseIfx,0);
4681 if(ifx) ifx->generated = 1;
4688 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4689 /* degenerate compare can never be true */
4690 if(rFalseIfx.condition == 0)
4691 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4693 if(ifx) ifx->generated = 1;
4698 /* signed comparisons to a literal byte */
4700 int lp1 = (lit+1) & 0xff;
4702 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4705 rFalseIfx.condition ^= 1;
4706 genSkipCond(&rFalseIfx,right,0,7);
4709 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4710 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4711 genSkipz2(&rFalseIfx,1);
4714 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4715 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4716 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4717 rFalseIfx.condition ^= 1;
4718 genSkipc(&rFalseIfx);
4722 /* unsigned comparisons to a literal byte */
4724 switch(lit & 0xff ) {
4726 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4727 genSkipz2(&rFalseIfx,0);
4730 rFalseIfx.condition ^= 1;
4731 genSkipCond(&rFalseIfx,right,0,7);
4735 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4736 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4737 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4738 rFalseIfx.condition ^= 1;
4739 if (AOP_TYPE(result) == AOP_CRY)
4740 genSkipc(&rFalseIfx);
4742 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4743 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4749 if(ifx) ifx->generated = 1;
4755 /* Size is greater than 1 */
4763 /* this means lit = 0xffffffff, or -1 */
4766 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4767 rFalseIfx.condition ^= 1;
4768 genSkipCond(&rFalseIfx,right,size,7);
4769 if(ifx) ifx->generated = 1;
4776 if(rFalseIfx.condition) {
4777 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4778 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4781 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4783 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4787 if(rFalseIfx.condition) {
4788 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4789 pic16_emitpLabel(truelbl->key);
4791 rFalseIfx.condition ^= 1;
4792 genSkipCond(&rFalseIfx,right,s,7);
4795 if(ifx) ifx->generated = 1;
4799 if((size == 1) && (0 == (lp1&0xff))) {
4800 /* lower byte of signed word is zero */
4801 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4802 i = ((lp1 >> 8) & 0xff) ^0x80;
4803 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4804 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4805 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4806 rFalseIfx.condition ^= 1;
4807 genSkipc(&rFalseIfx);
4810 if(ifx) ifx->generated = 1;
4814 if(lit & (0x80 << (size*8))) {
4815 /* Lit is less than zero */
4816 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4817 //rFalseIfx.condition ^= 1;
4818 //genSkipCond(&rFalseIfx,left,size,7);
4819 //rFalseIfx.condition ^= 1;
4820 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4821 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4823 if(rFalseIfx.condition)
4824 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4826 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4830 /* Lit is greater than or equal to zero */
4831 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4832 //rFalseIfx.condition ^= 1;
4833 //genSkipCond(&rFalseIfx,right,size,7);
4834 //rFalseIfx.condition ^= 1;
4836 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4837 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4839 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4840 if(rFalseIfx.condition)
4841 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4843 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4848 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4849 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4853 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4855 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4857 rFalseIfx.condition ^= 1;
4858 //rFalseIfx.condition = 1;
4859 genSkipc(&rFalseIfx);
4861 pic16_emitpLabel(truelbl->key);
4863 if(ifx) ifx->generated = 1;
4868 /* compare word or long to an unsigned literal on the right.*/
4873 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4876 break; /* handled above */
4879 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4881 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4882 genSkipz2(&rFalseIfx,0);
4886 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4888 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4891 if(rFalseIfx.condition)
4892 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4894 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4897 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4898 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4900 rFalseIfx.condition ^= 1;
4901 genSkipc(&rFalseIfx);
4904 pic16_emitpLabel(truelbl->key);
4906 if(ifx) ifx->generated = 1;
4912 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4913 i = (lit >> (size*8)) & 0xff;
4915 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4916 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4919 i = (lit >> (size*8)) & 0xff;
4922 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4924 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4926 /* this byte of the lit is zero,
4927 *if it's not the last then OR in the variable */
4929 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4934 pic16_emitpLabel(lbl->key);
4936 rFalseIfx.condition ^= 1;
4937 genSkipc(&rFalseIfx);
4941 pic16_emitpLabel(truelbl->key);
4942 if(ifx) ifx->generated = 1;
4946 /* Compare two variables */
4948 DEBUGpic16_emitcode(";sign","%d",sign);
4952 /* Sigh. thus sucks... */
4954 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4955 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4956 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4957 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4958 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4959 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4961 /* Signed char comparison */
4962 /* Special thanks to Nikolai Golovchenko for this snippet */
4963 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4964 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4965 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
4966 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4967 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4968 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4970 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4971 genSkipc(&rFalseIfx);
4973 if(ifx) ifx->generated = 1;
4979 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4980 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4984 /* The rest of the bytes of a multi-byte compare */
4988 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
4991 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4992 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4997 pic16_emitpLabel(lbl->key);
4999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5000 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5001 (AOP_TYPE(result) == AOP_REG)) {
5002 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5003 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5005 genSkipc(&rFalseIfx);
5007 //genSkipc(&rFalseIfx);
5008 if(ifx) ifx->generated = 1;
5015 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5016 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5017 pic16_outBitC(result);
5019 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5020 /* if the result is used in the next
5021 ifx conditional branch then generate
5022 code a little differently */
5024 genIfxJump (ifx,"c");
5026 pic16_outBitC(result);
5027 /* leave the result in acc */
5032 /*-----------------------------------------------------------------*/
5033 /* genCmpGt :- greater than comparison */
5034 /*-----------------------------------------------------------------*/
5035 static void genCmpGt (iCode *ic, iCode *ifx)
5037 operand *left, *right, *result;
5038 sym_link *letype , *retype;
5041 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5043 right= IC_RIGHT(ic);
5044 result = IC_RESULT(ic);
5046 letype = getSpec(operandType(left));
5047 retype =getSpec(operandType(right));
5048 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5049 /* assign the amsops */
5050 pic16_aopOp (left,ic,FALSE);
5051 pic16_aopOp (right,ic,FALSE);
5052 pic16_aopOp (result,ic,TRUE);
5054 genCmp(right, left, result, ifx, sign);
5056 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5057 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5058 pic16_freeAsmop(result,NULL,ic,TRUE);
5061 /*-----------------------------------------------------------------*/
5062 /* genCmpLt - less than comparisons */
5063 /*-----------------------------------------------------------------*/
5064 static void genCmpLt (iCode *ic, iCode *ifx)
5066 operand *left, *right, *result;
5067 sym_link *letype , *retype;
5070 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5072 right= IC_RIGHT(ic);
5073 result = IC_RESULT(ic);
5075 letype = getSpec(operandType(left));
5076 retype =getSpec(operandType(right));
5077 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5079 /* assign the amsops */
5080 pic16_aopOp (left,ic,FALSE);
5081 pic16_aopOp (right,ic,FALSE);
5082 pic16_aopOp (result,ic,TRUE);
5084 genCmp(left, right, result, ifx, sign);
5086 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5087 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5088 pic16_freeAsmop(result,NULL,ic,TRUE);
5091 /*-----------------------------------------------------------------*/
5092 /* genc16bit2lit - compare a 16 bit value to a literal */
5093 /*-----------------------------------------------------------------*/
5094 static void genc16bit2lit(operand *op, int lit, int offset)
5098 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5099 if( (lit&0xff) == 0)
5104 switch( BYTEofLONG(lit,i)) {
5106 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5109 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5112 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5115 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5116 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5121 switch( BYTEofLONG(lit,i)) {
5123 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5127 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5131 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5134 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5136 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5142 /*-----------------------------------------------------------------*/
5143 /* gencjneshort - compare and jump if not equal */
5144 /*-----------------------------------------------------------------*/
5145 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5147 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5149 int res_offset = 0; /* the result may be a different size then left or right */
5150 int res_size = AOP_SIZE(result);
5154 unsigned long lit = 0L;
5155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5156 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5158 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5159 resolveIfx(&rIfx,ifx);
5160 lbl = newiTempLabel(NULL);
5163 /* if the left side is a literal or
5164 if the right is in a pointer register and left
5166 if ((AOP_TYPE(left) == AOP_LIT) ||
5167 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5172 if(AOP_TYPE(right) == AOP_LIT)
5173 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5175 /* if the right side is a literal then anything goes */
5176 if (AOP_TYPE(right) == AOP_LIT &&
5177 AOP_TYPE(left) != AOP_DIR ) {
5180 genc16bit2lit(left, lit, 0);
5182 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5185 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5188 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5189 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5191 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5195 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5197 if(res_offset < res_size-1)
5205 /* if the right side is in a register or in direct space or
5206 if the left is a pointer register & right is not */
5207 else if (AOP_TYPE(right) == AOP_REG ||
5208 AOP_TYPE(right) == AOP_DIR ||
5209 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5210 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5211 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5212 int lbl_key = lbl->key;
5215 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5216 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5218 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5219 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5220 __FUNCTION__,__LINE__);
5224 /* switch(size) { */
5226 /* genc16bit2lit(left, lit, 0); */
5228 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5233 if((AOP_TYPE(left) == AOP_DIR) &&
5234 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5236 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5237 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5239 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5241 switch (lit & 0xff) {
5243 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5246 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5247 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5248 //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5252 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5253 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5254 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5255 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5259 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5260 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5265 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5268 if(AOP_TYPE(result) == AOP_CRY) {
5269 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5274 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5276 /* fix me. probably need to check result size too */
5277 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5282 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5283 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5290 if(res_offset < res_size-1)
5295 } else if(AOP_TYPE(right) == AOP_REG &&
5296 AOP_TYPE(left) != AOP_DIR){
5299 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5300 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5301 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5306 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5308 if(res_offset < res_size-1)
5313 /* right is a pointer reg need both a & b */
5315 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5317 pic16_emitcode("mov","b,%s",l);
5318 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5319 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5324 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5326 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5328 pic16_emitpLabel(lbl->key);
5330 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5337 /*-----------------------------------------------------------------*/
5338 /* gencjne - compare and jump if not equal */
5339 /*-----------------------------------------------------------------*/
5340 static void gencjne(operand *left, operand *right, iCode *ifx)
5342 symbol *tlbl = newiTempLabel(NULL);
5344 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5345 gencjneshort(left, right, lbl);
5347 pic16_emitcode("mov","a,%s",one);
5348 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5349 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5350 pic16_emitcode("clr","a");
5351 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5353 pic16_emitpLabel(lbl->key);
5354 pic16_emitpLabel(tlbl->key);
5359 /*-----------------------------------------------------------------*/
5360 /* genCmpEq - generates code for equal to */
5361 /*-----------------------------------------------------------------*/
5362 static void genCmpEq (iCode *ic, iCode *ifx)
5364 operand *left, *right, *result;
5365 unsigned long lit = 0L;
5367 symbol *falselbl = newiTempLabel(NULL);
5370 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5373 DEBUGpic16_emitcode ("; ifx is non-null","");
5375 DEBUGpic16_emitcode ("; ifx is null","");
5377 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5378 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5379 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5381 size = max(AOP_SIZE(left),AOP_SIZE(right));
5383 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5385 /* if literal, literal on the right or
5386 if the right is in a pointer register and left
5388 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5389 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5390 operand *tmp = right ;
5396 if(ifx && !AOP_SIZE(result)){
5398 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5399 /* if they are both bit variables */
5400 if (AOP_TYPE(left) == AOP_CRY &&
5401 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5402 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5403 if(AOP_TYPE(right) == AOP_LIT){
5404 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5406 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5407 pic16_emitcode("cpl","c");
5408 } else if(lit == 1L) {
5409 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5411 pic16_emitcode("clr","c");
5413 /* AOP_TYPE(right) == AOP_CRY */
5415 symbol *lbl = newiTempLabel(NULL);
5416 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5417 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5418 pic16_emitcode("cpl","c");
5419 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5421 /* if true label then we jump if condition
5423 tlbl = newiTempLabel(NULL);
5424 if ( IC_TRUE(ifx) ) {
5425 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5426 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5428 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5429 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5431 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5434 /* left and right are both bit variables, result is carry */
5437 resolveIfx(&rIfx,ifx);
5439 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5440 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5441 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5442 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5447 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5449 /* They're not both bit variables. Is the right a literal? */
5450 if(AOP_TYPE(right) == AOP_LIT) {
5451 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5456 switch(lit & 0xff) {
5458 if ( IC_TRUE(ifx) ) {
5459 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5463 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5468 if ( IC_TRUE(ifx) ) {
5469 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5471 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5473 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5474 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5478 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5480 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5485 /* end of size == 1 */
5489 genc16bit2lit(left,lit,offset);
5492 /* end of size == 2 */
5497 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5498 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5499 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5500 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5503 /* search for patterns that can be optimized */
5505 genc16bit2lit(left,lit,0);
5509 emitSKPZ; // if hi word unequal
5511 emitSKPNZ; // if hi word equal
5513 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5514 genc16bit2lit(left,lit,2);
5517 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5518 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5522 pic16_emitpLabel(falselbl->key);
5531 } else if(AOP_TYPE(right) == AOP_CRY ) {
5532 /* we know the left is not a bit, but that the right is */
5533 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5534 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5535 pic16_popGet(AOP(right),offset));
5536 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5538 /* if the two are equal, then W will be 0 and the Z bit is set
5539 * we could test Z now, or go ahead and check the high order bytes if
5540 * the variable we're comparing is larger than a byte. */
5543 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5545 if ( IC_TRUE(ifx) ) {
5547 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5548 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5551 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5552 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5556 /* They're both variables that are larger than bits */
5559 tlbl = newiTempLabel(NULL);
5562 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5563 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5565 if ( IC_TRUE(ifx) ) {
5569 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5571 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5572 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5576 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5579 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5580 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5585 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5587 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5588 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5592 if(s>1 && IC_TRUE(ifx)) {
5593 pic16_emitpLabel(tlbl->key);
5594 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5598 /* mark the icode as generated */
5603 /* if they are both bit variables */
5604 if (AOP_TYPE(left) == AOP_CRY &&
5605 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5606 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5607 if(AOP_TYPE(right) == AOP_LIT){
5608 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5610 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5611 pic16_emitcode("cpl","c");
5612 } else if(lit == 1L) {
5613 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5615 pic16_emitcode("clr","c");
5617 /* AOP_TYPE(right) == AOP_CRY */
5619 symbol *lbl = newiTempLabel(NULL);
5620 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5621 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5622 pic16_emitcode("cpl","c");
5623 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5626 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5627 pic16_outBitC(result);
5631 genIfxJump (ifx,"c");
5634 /* if the result is used in an arithmetic operation
5635 then put the result in place */
5636 pic16_outBitC(result);
5639 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5640 gencjne(left,right,result,ifx);
5643 gencjne(left,right,newiTempLabel(NULL));
5645 if(IC_TRUE(ifx)->key)
5646 gencjne(left,right,IC_TRUE(ifx)->key);
5648 gencjne(left,right,IC_FALSE(ifx)->key);
5652 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5653 pic16_aopPut(AOP(result),"a",0);
5658 genIfxJump (ifx,"a");
5662 /* if the result is used in an arithmetic operation
5663 then put the result in place */
5665 if (AOP_TYPE(result) != AOP_CRY)
5666 pic16_outAcc(result);
5668 /* leave the result in acc */
5672 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5673 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5674 pic16_freeAsmop(result,NULL,ic,TRUE);
5677 /*-----------------------------------------------------------------*/
5678 /* ifxForOp - returns the icode containing the ifx for operand */
5679 /*-----------------------------------------------------------------*/
5680 static iCode *ifxForOp ( operand *op, iCode *ic )
5682 /* if true symbol then needs to be assigned */
5683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5684 if (IS_TRUE_SYMOP(op))
5687 /* if this has register type condition and
5688 the next instruction is ifx with the same operand
5689 and live to of the operand is upto the ifx only then */
5691 ic->next->op == IFX &&
5692 IC_COND(ic->next)->key == op->key &&
5693 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5697 ic->next->op == IFX &&
5698 IC_COND(ic->next)->key == op->key) {
5699 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5703 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5705 ic->next->op == IFX)
5706 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5709 ic->next->op == IFX &&
5710 IC_COND(ic->next)->key == op->key) {
5711 DEBUGpic16_emitcode ("; "," key is okay");
5712 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5713 OP_SYMBOL(op)->liveTo,
5720 /*-----------------------------------------------------------------*/
5721 /* genAndOp - for && operation */
5722 /*-----------------------------------------------------------------*/
5723 static void genAndOp (iCode *ic)
5725 operand *left,*right, *result;
5728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5729 /* note here that && operations that are in an
5730 if statement are taken away by backPatchLabels
5731 only those used in arthmetic operations remain */
5732 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5733 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5734 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5736 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5738 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5739 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5740 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5742 /* if both are bit variables */
5743 /* if (AOP_TYPE(left) == AOP_CRY && */
5744 /* AOP_TYPE(right) == AOP_CRY ) { */
5745 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5746 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5747 /* pic16_outBitC(result); */
5749 /* tlbl = newiTempLabel(NULL); */
5750 /* pic16_toBoolean(left); */
5751 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5752 /* pic16_toBoolean(right); */
5753 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5754 /* pic16_outBitAcc(result); */
5757 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5758 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5759 pic16_freeAsmop(result,NULL,ic,TRUE);
5763 /*-----------------------------------------------------------------*/
5764 /* genOrOp - for || operation */
5765 /*-----------------------------------------------------------------*/
5768 modified this code, but it doesn't appear to ever get called
5771 static void genOrOp (iCode *ic)
5773 operand *left,*right, *result;
5776 /* note here that || operations that are in an
5777 if statement are taken away by backPatchLabels
5778 only those used in arthmetic operations remain */
5779 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5780 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5781 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5782 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5784 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5786 /* if both are bit variables */
5787 if (AOP_TYPE(left) == AOP_CRY &&
5788 AOP_TYPE(right) == AOP_CRY ) {
5789 pic16_emitcode("clrc","");
5790 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5791 AOP(left)->aopu.aop_dir,
5792 AOP(left)->aopu.aop_dir);
5793 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5794 AOP(right)->aopu.aop_dir,
5795 AOP(right)->aopu.aop_dir);
5796 pic16_emitcode("setc","");
5799 tlbl = newiTempLabel(NULL);
5800 pic16_toBoolean(left);
5802 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5803 pic16_toBoolean(right);
5804 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5806 pic16_outBitAcc(result);
5809 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5810 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5811 pic16_freeAsmop(result,NULL,ic,TRUE);
5814 /*-----------------------------------------------------------------*/
5815 /* isLiteralBit - test if lit == 2^n */
5816 /*-----------------------------------------------------------------*/
5817 static int isLiteralBit(unsigned long lit)
5819 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5820 0x100L,0x200L,0x400L,0x800L,
5821 0x1000L,0x2000L,0x4000L,0x8000L,
5822 0x10000L,0x20000L,0x40000L,0x80000L,
5823 0x100000L,0x200000L,0x400000L,0x800000L,
5824 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5825 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5829 for(idx = 0; idx < 32; idx++)
5835 /*-----------------------------------------------------------------*/
5836 /* continueIfTrue - */
5837 /*-----------------------------------------------------------------*/
5838 static void continueIfTrue (iCode *ic)
5840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5842 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5846 /*-----------------------------------------------------------------*/
5848 /*-----------------------------------------------------------------*/
5849 static void jumpIfTrue (iCode *ic)
5851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5853 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5857 /*-----------------------------------------------------------------*/
5858 /* jmpTrueOrFalse - */
5859 /*-----------------------------------------------------------------*/
5860 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5862 // ugly but optimized by peephole
5863 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5865 symbol *nlbl = newiTempLabel(NULL);
5866 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5867 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5868 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5869 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5872 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5873 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5878 /*-----------------------------------------------------------------*/
5879 /* genAnd - code for and */
5880 /*-----------------------------------------------------------------*/
5881 static void genAnd (iCode *ic, iCode *ifx)
5883 operand *left, *right, *result;
5885 unsigned long lit = 0L;
5890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5891 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5892 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5893 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5895 resolveIfx(&rIfx,ifx);
5897 /* if left is a literal & right is not then exchange them */
5898 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5899 AOP_NEEDSACC(left)) {
5900 operand *tmp = right ;
5905 /* if result = right then exchange them */
5906 if(pic16_sameRegs(AOP(result),AOP(right))){
5907 operand *tmp = right ;
5912 /* if right is bit then exchange them */
5913 if (AOP_TYPE(right) == AOP_CRY &&
5914 AOP_TYPE(left) != AOP_CRY){
5915 operand *tmp = right ;
5919 if(AOP_TYPE(right) == AOP_LIT)
5920 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5922 size = AOP_SIZE(result);
5924 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5927 // result = bit & yy;
5928 if (AOP_TYPE(left) == AOP_CRY){
5929 // c = bit & literal;
5930 if(AOP_TYPE(right) == AOP_LIT){
5932 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5935 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5938 if(size && (AOP_TYPE(result) == AOP_CRY)){
5939 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5942 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5946 pic16_emitcode("clr","c");
5949 if (AOP_TYPE(right) == AOP_CRY){
5951 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5955 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5957 pic16_emitcode("rrc","a");
5958 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5964 pic16_outBitC(result);
5966 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5967 genIfxJump(ifx, "c");
5971 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5972 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5973 if((AOP_TYPE(right) == AOP_LIT) &&
5974 (AOP_TYPE(result) == AOP_CRY) &&
5975 (AOP_TYPE(left) != AOP_CRY)){
5976 int posbit = isLiteralBit(lit);
5980 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5983 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5989 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5990 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5992 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5993 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5996 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5997 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6005 symbol *tlbl = newiTempLabel(NULL);
6006 int sizel = AOP_SIZE(left);
6008 pic16_emitcode("setb","c");
6010 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6011 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6013 if((posbit = isLiteralBit(bytelit)) != 0)
6014 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6016 if(bytelit != 0x0FFL)
6017 pic16_emitcode("anl","a,%s",
6018 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6019 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6024 // bit = left & literal
6026 pic16_emitcode("clr","c");
6027 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6029 // if(left & literal)
6032 jmpTrueOrFalse(ifx, tlbl);
6036 pic16_outBitC(result);
6040 /* if left is same as result */
6041 if(pic16_sameRegs(AOP(result),AOP(left))){
6043 for(;size--; offset++,lit>>=8) {
6044 if(AOP_TYPE(right) == AOP_LIT){
6045 switch(lit & 0xff) {
6047 /* and'ing with 0 has clears the result */
6048 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6049 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6052 /* and'ing with 0xff is a nop when the result and left are the same */
6057 int p = my_powof2( (~lit) & 0xff );
6059 /* only one bit is set in the literal, so use a bcf instruction */
6060 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6061 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6064 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6065 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6066 if(know_W != (lit&0xff))
6067 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6069 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6074 if (AOP_TYPE(left) == AOP_ACC) {
6075 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6077 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6078 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6085 // left & result in different registers
6086 if(AOP_TYPE(result) == AOP_CRY){
6088 // if(size), result in bit
6089 // if(!size && ifx), conditional oper: if(left & right)
6090 symbol *tlbl = newiTempLabel(NULL);
6091 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6093 pic16_emitcode("setb","c");
6095 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6096 pic16_emitcode("anl","a,%s",
6097 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6098 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6103 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6104 pic16_outBitC(result);
6106 jmpTrueOrFalse(ifx, tlbl);
6108 for(;(size--);offset++) {
6110 // result = left & right
6111 if(AOP_TYPE(right) == AOP_LIT){
6112 int t = (lit >> (offset*8)) & 0x0FFL;
6115 pic16_emitcode("clrf","%s",
6116 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6117 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6120 pic16_emitcode("movf","%s,w",
6121 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6122 pic16_emitcode("movwf","%s",
6123 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6124 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6125 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6128 pic16_emitcode("movlw","0x%x",t);
6129 pic16_emitcode("andwf","%s,w",
6130 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6131 pic16_emitcode("movwf","%s",
6132 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6134 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6135 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6136 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6141 if (AOP_TYPE(left) == AOP_ACC) {
6142 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6143 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6145 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6146 pic16_emitcode("andwf","%s,w",
6147 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6148 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6149 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6151 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6152 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6158 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6159 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6160 pic16_freeAsmop(result,NULL,ic,TRUE);
6163 /*-----------------------------------------------------------------*/
6164 /* genOr - code for or */
6165 /*-----------------------------------------------------------------*/
6166 static void genOr (iCode *ic, iCode *ifx)
6168 operand *left, *right, *result;
6170 unsigned long lit = 0L;
6172 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6174 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6175 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6176 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6178 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6180 /* if left is a literal & right is not then exchange them */
6181 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6182 AOP_NEEDSACC(left)) {
6183 operand *tmp = right ;
6188 /* if result = right then exchange them */
6189 if(pic16_sameRegs(AOP(result),AOP(right))){
6190 operand *tmp = right ;
6195 /* if right is bit then exchange them */
6196 if (AOP_TYPE(right) == AOP_CRY &&
6197 AOP_TYPE(left) != AOP_CRY){
6198 operand *tmp = right ;
6203 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6205 if(AOP_TYPE(right) == AOP_LIT)
6206 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6208 size = AOP_SIZE(result);
6212 if (AOP_TYPE(left) == AOP_CRY){
6213 if(AOP_TYPE(right) == AOP_LIT){
6214 // c = bit & literal;
6216 // lit != 0 => result = 1
6217 if(AOP_TYPE(result) == AOP_CRY){
6219 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6220 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6221 // AOP(result)->aopu.aop_dir,
6222 // AOP(result)->aopu.aop_dir);
6224 continueIfTrue(ifx);
6228 // lit == 0 => result = left
6229 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6231 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6234 if (AOP_TYPE(right) == AOP_CRY){
6235 if(pic16_sameRegs(AOP(result),AOP(left))){
6237 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6238 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6239 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6241 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6242 AOP(result)->aopu.aop_dir,
6243 AOP(result)->aopu.aop_dir);
6244 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6245 AOP(right)->aopu.aop_dir,
6246 AOP(right)->aopu.aop_dir);
6247 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6248 AOP(result)->aopu.aop_dir,
6249 AOP(result)->aopu.aop_dir);
6251 if( AOP_TYPE(result) == AOP_ACC) {
6252 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6253 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6254 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6255 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6259 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6260 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6261 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6262 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6264 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6265 AOP(result)->aopu.aop_dir,
6266 AOP(result)->aopu.aop_dir);
6267 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6268 AOP(right)->aopu.aop_dir,
6269 AOP(right)->aopu.aop_dir);
6270 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6271 AOP(left)->aopu.aop_dir,
6272 AOP(left)->aopu.aop_dir);
6273 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6274 AOP(result)->aopu.aop_dir,
6275 AOP(result)->aopu.aop_dir);
6280 symbol *tlbl = newiTempLabel(NULL);
6281 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6284 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6285 if( AOP_TYPE(right) == AOP_ACC) {
6286 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6288 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6289 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6294 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6295 pic16_emitcode(";XXX setb","c");
6296 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6297 AOP(left)->aopu.aop_dir,tlbl->key+100);
6298 pic16_toBoolean(right);
6299 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6300 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6301 jmpTrueOrFalse(ifx, tlbl);
6305 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6312 pic16_outBitC(result);
6314 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6315 genIfxJump(ifx, "c");
6319 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6320 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6321 if((AOP_TYPE(right) == AOP_LIT) &&
6322 (AOP_TYPE(result) == AOP_CRY) &&
6323 (AOP_TYPE(left) != AOP_CRY)){
6325 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6328 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6330 continueIfTrue(ifx);
6333 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6334 // lit = 0, result = boolean(left)
6336 pic16_emitcode(";XXX setb","c");
6337 pic16_toBoolean(right);
6339 symbol *tlbl = newiTempLabel(NULL);
6340 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6342 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6344 genIfxJump (ifx,"a");
6348 pic16_outBitC(result);
6352 /* if left is same as result */
6353 if(pic16_sameRegs(AOP(result),AOP(left))){
6355 for(;size--; offset++,lit>>=8) {
6356 if(AOP_TYPE(right) == AOP_LIT){
6357 if((lit & 0xff) == 0)
6358 /* or'ing with 0 has no effect */
6361 int p = my_powof2(lit & 0xff);
6363 /* only one bit is set in the literal, so use a bsf instruction */
6364 pic16_emitpcode(POC_BSF,
6365 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6367 if(know_W != (lit & 0xff))
6368 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6369 know_W = lit & 0xff;
6370 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6375 if (AOP_TYPE(left) == AOP_ACC) {
6376 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6377 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6379 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6380 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6382 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6383 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6389 // left & result in different registers
6390 if(AOP_TYPE(result) == AOP_CRY){
6392 // if(size), result in bit
6393 // if(!size && ifx), conditional oper: if(left | right)
6394 symbol *tlbl = newiTempLabel(NULL);
6395 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6396 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6400 pic16_emitcode(";XXX setb","c");
6402 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6403 pic16_emitcode(";XXX orl","a,%s",
6404 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6405 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6410 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6411 pic16_outBitC(result);
6413 jmpTrueOrFalse(ifx, tlbl);
6414 } else for(;(size--);offset++){
6416 // result = left & right
6417 if(AOP_TYPE(right) == AOP_LIT){
6418 int t = (lit >> (offset*8)) & 0x0FFL;
6421 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6422 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6424 pic16_emitcode("movf","%s,w",
6425 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6426 pic16_emitcode("movwf","%s",
6427 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6430 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6431 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6432 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6434 pic16_emitcode("movlw","0x%x",t);
6435 pic16_emitcode("iorwf","%s,w",
6436 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6437 pic16_emitcode("movwf","%s",
6438 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6444 // faster than result <- left, anl result,right
6445 // and better if result is SFR
6446 if (AOP_TYPE(left) == AOP_ACC) {
6447 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6448 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6450 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6451 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6453 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6454 pic16_emitcode("iorwf","%s,w",
6455 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6457 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6458 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6463 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6464 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6465 pic16_freeAsmop(result,NULL,ic,TRUE);
6468 /*-----------------------------------------------------------------*/
6469 /* genXor - code for xclusive or */
6470 /*-----------------------------------------------------------------*/
6471 static void genXor (iCode *ic, iCode *ifx)
6473 operand *left, *right, *result;
6475 unsigned long lit = 0L;
6477 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6479 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6480 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6481 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6483 /* if left is a literal & right is not ||
6484 if left needs acc & right does not */
6485 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6486 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6487 operand *tmp = right ;
6492 /* if result = right then exchange them */
6493 if(pic16_sameRegs(AOP(result),AOP(right))){
6494 operand *tmp = right ;
6499 /* if right is bit then exchange them */
6500 if (AOP_TYPE(right) == AOP_CRY &&
6501 AOP_TYPE(left) != AOP_CRY){
6502 operand *tmp = right ;
6506 if(AOP_TYPE(right) == AOP_LIT)
6507 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6509 size = AOP_SIZE(result);
6513 if (AOP_TYPE(left) == AOP_CRY){
6514 if(AOP_TYPE(right) == AOP_LIT){
6515 // c = bit & literal;
6517 // lit>>1 != 0 => result = 1
6518 if(AOP_TYPE(result) == AOP_CRY){
6520 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6521 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6523 continueIfTrue(ifx);
6526 pic16_emitcode("setb","c");
6530 // lit == 0, result = left
6531 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6533 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6535 // lit == 1, result = not(left)
6536 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6537 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6538 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6539 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6542 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6543 pic16_emitcode("cpl","c");
6550 symbol *tlbl = newiTempLabel(NULL);
6551 if (AOP_TYPE(right) == AOP_CRY){
6553 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6556 int sizer = AOP_SIZE(right);
6558 // if val>>1 != 0, result = 1
6559 pic16_emitcode("setb","c");
6561 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6563 // test the msb of the lsb
6564 pic16_emitcode("anl","a,#0xfe");
6565 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6569 pic16_emitcode("rrc","a");
6571 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6572 pic16_emitcode("cpl","c");
6573 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6578 pic16_outBitC(result);
6580 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6581 genIfxJump(ifx, "c");
6585 if(pic16_sameRegs(AOP(result),AOP(left))){
6586 /* if left is same as result */
6587 for(;size--; offset++) {
6588 if(AOP_TYPE(right) == AOP_LIT){
6589 int t = (lit >> (offset*8)) & 0x0FFL;
6593 if (IS_AOP_PREG(left)) {
6594 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6595 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6596 pic16_aopPut(AOP(result),"a",offset);
6598 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6599 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6600 pic16_emitcode("xrl","%s,%s",
6601 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6602 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6605 if (AOP_TYPE(left) == AOP_ACC)
6606 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6608 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6609 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6611 if (IS_AOP_PREG(left)) {
6612 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6613 pic16_aopPut(AOP(result),"a",offset);
6615 pic16_emitcode("xrl","%s,a",
6616 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6622 // left & result in different registers
6623 if(AOP_TYPE(result) == AOP_CRY){
6625 // if(size), result in bit
6626 // if(!size && ifx), conditional oper: if(left ^ right)
6627 symbol *tlbl = newiTempLabel(NULL);
6628 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6630 pic16_emitcode("setb","c");
6632 if((AOP_TYPE(right) == AOP_LIT) &&
6633 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6634 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6636 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6637 pic16_emitcode("xrl","a,%s",
6638 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6640 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6645 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6646 pic16_outBitC(result);
6648 jmpTrueOrFalse(ifx, tlbl);
6649 } else for(;(size--);offset++){
6651 // result = left & right
6652 if(AOP_TYPE(right) == AOP_LIT){
6653 int t = (lit >> (offset*8)) & 0x0FFL;
6656 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6657 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6658 pic16_emitcode("movf","%s,w",
6659 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6660 pic16_emitcode("movwf","%s",
6661 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6664 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6665 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6666 pic16_emitcode("comf","%s,w",
6667 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6668 pic16_emitcode("movwf","%s",
6669 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6672 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6673 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6674 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6675 pic16_emitcode("movlw","0x%x",t);
6676 pic16_emitcode("xorwf","%s,w",
6677 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6678 pic16_emitcode("movwf","%s",
6679 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6685 // faster than result <- left, anl result,right
6686 // and better if result is SFR
6687 if (AOP_TYPE(left) == AOP_ACC) {
6688 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6689 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6691 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6692 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6693 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6694 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6696 if ( AOP_TYPE(result) != AOP_ACC){
6697 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6698 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6704 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6705 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6706 pic16_freeAsmop(result,NULL,ic,TRUE);
6709 /*-----------------------------------------------------------------*/
6710 /* genInline - write the inline code out */
6711 /*-----------------------------------------------------------------*/
6712 static void genInline (iCode *ic)
6714 char *buffer, *bp, *bp1;
6716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6718 _G.inLine += (!options.asmpeep);
6720 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6721 strcpy(buffer,IC_INLINE(ic));
6723 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6725 /* emit each line as a code */
6731 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6739 /* print label, use this special format with NULL directive
6740 * to denote that the argument should not be indented with tab */
6741 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6748 if ((bp1 != bp) && *bp1)
6749 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6754 _G.inLine -= (!options.asmpeep);
6757 /*-----------------------------------------------------------------*/
6758 /* genRRC - rotate right with carry */
6759 /*-----------------------------------------------------------------*/
6760 static void genRRC (iCode *ic)
6762 operand *left , *result ;
6763 int size, offset = 0, same;
6765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6767 /* rotate right with carry */
6769 result=IC_RESULT(ic);
6770 pic16_aopOp (left,ic,FALSE);
6771 pic16_aopOp (result,ic,FALSE);
6773 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6775 same = pic16_sameRegs(AOP(result),AOP(left));
6777 size = AOP_SIZE(result);
6779 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6781 /* get the lsb and put it into the carry */
6782 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6789 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6791 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6798 pic16_freeAsmop(left,NULL,ic,TRUE);
6799 pic16_freeAsmop(result,NULL,ic,TRUE);
6802 /*-----------------------------------------------------------------*/
6803 /* genRLC - generate code for rotate left with carry */
6804 /*-----------------------------------------------------------------*/
6805 static void genRLC (iCode *ic)
6807 operand *left , *result ;
6808 int size, offset = 0;
6811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6812 /* rotate right with carry */
6814 result=IC_RESULT(ic);
6815 pic16_aopOp (left,ic,FALSE);
6816 pic16_aopOp (result,ic,FALSE);
6818 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6820 same = pic16_sameRegs(AOP(result),AOP(left));
6822 /* move it to the result */
6823 size = AOP_SIZE(result);
6825 /* get the msb and put it into the carry */
6826 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6833 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6835 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6836 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6843 pic16_freeAsmop(left,NULL,ic,TRUE);
6844 pic16_freeAsmop(result,NULL,ic,TRUE);
6848 /* gpasm can get the highest order bit with HIGH/UPPER
6849 * so the following probably is not needed -- VR */
6851 /*-----------------------------------------------------------------*/
6852 /* genGetHbit - generates code get highest order bit */
6853 /*-----------------------------------------------------------------*/
6854 static void genGetHbit (iCode *ic)
6856 operand *left, *result;
6858 result=IC_RESULT(ic);
6859 pic16_aopOp (left,ic,FALSE);
6860 pic16_aopOp (result,ic,FALSE);
6862 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6863 /* get the highest order byte into a */
6864 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6865 if(AOP_TYPE(result) == AOP_CRY){
6866 pic16_emitcode("rlc","a");
6867 pic16_outBitC(result);
6870 pic16_emitcode("rl","a");
6871 pic16_emitcode("anl","a,#0x01");
6872 pic16_outAcc(result);
6876 pic16_freeAsmop(left,NULL,ic,TRUE);
6877 pic16_freeAsmop(result,NULL,ic,TRUE);
6881 /*-----------------------------------------------------------------*/
6882 /* AccRol - rotate left accumulator by known count */
6883 /*-----------------------------------------------------------------*/
6884 static void AccRol (int shCount)
6886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6887 shCount &= 0x0007; // shCount : 0..7
6892 pic16_emitcode("rl","a");
6895 pic16_emitcode("rl","a");
6896 pic16_emitcode("rl","a");
6899 pic16_emitcode("swap","a");
6900 pic16_emitcode("rr","a");
6903 pic16_emitcode("swap","a");
6906 pic16_emitcode("swap","a");
6907 pic16_emitcode("rl","a");
6910 pic16_emitcode("rr","a");
6911 pic16_emitcode("rr","a");
6914 pic16_emitcode("rr","a");
6920 /*-----------------------------------------------------------------*/
6921 /* AccLsh - left shift accumulator by known count */
6922 /*-----------------------------------------------------------------*/
6923 static void AccLsh (int shCount)
6925 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6931 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6934 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6935 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6938 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6939 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6942 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6945 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6946 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6949 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6950 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6953 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6957 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6960 /*-----------------------------------------------------------------*/
6961 /* AccRsh - right shift accumulator by known count */
6962 /*-----------------------------------------------------------------*/
6963 static void AccRsh (int shCount, int andmask)
6965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6970 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6971 // andmask = 0; /* no need */
6974 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6975 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6976 // andmask = 0; /* no need */
6979 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6980 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6983 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6986 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6987 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6990 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6991 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6994 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6999 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7001 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7005 /*-----------------------------------------------------------------*/
7006 /* AccSRsh - signed right shift accumulator by known count */
7007 /*-----------------------------------------------------------------*/
7008 static void AccSRsh (int shCount)
7011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7014 pic16_emitcode("mov","c,acc.7");
7015 pic16_emitcode("rrc","a");
7016 } else if(shCount == 2){
7017 pic16_emitcode("mov","c,acc.7");
7018 pic16_emitcode("rrc","a");
7019 pic16_emitcode("mov","c,acc.7");
7020 pic16_emitcode("rrc","a");
7022 tlbl = newiTempLabel(NULL);
7023 /* rotate right accumulator */
7024 AccRol(8 - shCount);
7025 /* and kill the higher order bits */
7026 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7027 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7028 pic16_emitcode("orl","a,#0x%02x",
7029 (unsigned char)~SRMask[shCount]);
7030 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7035 /*-----------------------------------------------------------------*/
7036 /* shiftR1Left2Result - shift right one byte from left to result */
7037 /*-----------------------------------------------------------------*/
7038 static void shiftR1Left2ResultSigned (operand *left, int offl,
7039 operand *result, int offr,
7044 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7046 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7050 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7052 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7054 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7061 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7063 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7065 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7068 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7069 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7075 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7077 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7081 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7082 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7083 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7085 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7086 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7092 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7093 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7094 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7095 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7096 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7100 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7102 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7103 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7105 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7106 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7107 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7108 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7109 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7115 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7116 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7117 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7118 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7119 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7121 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7122 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7123 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7124 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7125 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7132 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7133 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7134 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7136 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7137 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7138 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7146 /*-----------------------------------------------------------------*/
7147 /* shiftR1Left2Result - shift right one byte from left to result */
7148 /*-----------------------------------------------------------------*/
7149 static void shiftR1Left2Result (operand *left, int offl,
7150 operand *result, int offr,
7151 int shCount, int sign)
7155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7157 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7159 /* Copy the msb into the carry if signed. */
7161 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7171 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7173 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7174 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7180 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7182 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7183 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7186 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7191 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7193 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7197 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7198 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7199 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7200 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7204 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7205 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7206 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7210 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7211 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7212 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7214 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7219 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7220 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7221 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7222 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7223 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7228 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7229 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7230 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7239 /*-----------------------------------------------------------------*/
7240 /* shiftL1Left2Result - shift left one byte from left to result */
7241 /*-----------------------------------------------------------------*/
7242 static void shiftL1Left2Result (operand *left, int offl,
7243 operand *result, int offr, int shCount)
7248 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7250 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7251 DEBUGpic16_emitcode ("; ***","same = %d",same);
7252 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7254 /* shift left accumulator */
7255 //AccLsh(shCount); // don't comment out just yet...
7256 // pic16_aopPut(AOP(result),"a",offr);
7260 /* Shift left 1 bit position */
7261 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7263 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7265 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7266 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7270 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7271 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7272 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7273 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7276 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7277 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7278 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7279 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7280 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7283 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7284 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7285 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7288 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7289 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7290 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7291 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7294 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7295 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7296 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7297 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7298 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7301 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7302 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7303 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7307 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7312 /*-----------------------------------------------------------------*/
7313 /* movLeft2Result - move byte from left to result */
7314 /*-----------------------------------------------------------------*/
7315 static void movLeft2Result (operand *left, int offl,
7316 operand *result, int offr)
7319 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7320 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7321 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7323 if (*l == '@' && (IS_AOP_PREG(result))) {
7324 pic16_emitcode("mov","a,%s",l);
7325 pic16_aopPut(AOP(result),"a",offr);
7327 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7328 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7333 /*-----------------------------------------------------------------*/
7334 /* shiftL2Left2Result - shift left two bytes from left to result */
7335 /*-----------------------------------------------------------------*/
7336 static void shiftL2Left2Result (operand *left, int offl,
7337 operand *result, int offr, int shCount)
7339 int same = pic16_sameRegs(AOP(result), AOP(left));
7342 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7344 if (same && (offl != offr)) { // shift bytes
7347 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7348 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7350 } else { // just treat as different later on
7363 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7364 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7365 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7369 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7370 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7376 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7377 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7378 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7379 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7380 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7381 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7382 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7384 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7385 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7389 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7390 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7391 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7392 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7393 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7394 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7395 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7396 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7397 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7398 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7401 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7402 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7403 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7404 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7405 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7415 /* note, use a mov/add for the shift since the mov has a
7416 chance of getting optimized out */
7417 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7418 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7419 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7420 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7421 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7425 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7426 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7432 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7433 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7434 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7435 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7436 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7437 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7438 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7439 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7443 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7444 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7448 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7449 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7450 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7451 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7453 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7454 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7455 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7456 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7457 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7458 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7459 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7460 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7463 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7464 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7465 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7466 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7467 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7472 /*-----------------------------------------------------------------*/
7473 /* shiftR2Left2Result - shift right two bytes from left to result */
7474 /*-----------------------------------------------------------------*/
7475 static void shiftR2Left2Result (operand *left, int offl,
7476 operand *result, int offr,
7477 int shCount, int sign)
7479 int same = pic16_sameRegs(AOP(result), AOP(left));
7481 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7483 if (same && (offl != offr)) { // shift right bytes
7486 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7487 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7489 } else { // just treat as different later on
7501 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7506 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7507 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7509 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7510 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7511 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7512 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7517 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7520 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7521 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7528 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7529 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7530 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7532 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7533 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7534 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7535 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7537 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7538 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7539 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7541 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7542 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7543 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7544 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7545 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7549 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7550 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7555 pic16_emitpcode(POC_BTFSC,
7556 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7557 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7565 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7566 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7568 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7569 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7570 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7571 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7573 pic16_emitpcode(POC_BTFSC,
7574 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7575 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7577 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7578 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7579 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7580 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7582 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7583 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7584 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7585 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7586 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7587 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7588 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7589 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7591 pic16_emitpcode(POC_BTFSC,
7592 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7593 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7595 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7596 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7603 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7604 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7605 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7606 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7609 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7611 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7616 /*-----------------------------------------------------------------*/
7617 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7618 /*-----------------------------------------------------------------*/
7619 static void shiftLLeftOrResult (operand *left, int offl,
7620 operand *result, int offr, int shCount)
7622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7624 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7625 /* shift left accumulator */
7627 /* or with result */
7628 /* back to result */
7629 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7632 /*-----------------------------------------------------------------*/
7633 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7634 /*-----------------------------------------------------------------*/
7635 static void shiftRLeftOrResult (operand *left, int offl,
7636 operand *result, int offr, int shCount)
7638 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7640 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7641 /* shift right accumulator */
7643 /* or with result */
7644 /* back to result */
7645 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7648 /*-----------------------------------------------------------------*/
7649 /* genlshOne - left shift a one byte quantity by known count */
7650 /*-----------------------------------------------------------------*/
7651 static void genlshOne (operand *result, operand *left, int shCount)
7653 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7654 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7657 /*-----------------------------------------------------------------*/
7658 /* genlshTwo - left shift two bytes by known amount != 0 */
7659 /*-----------------------------------------------------------------*/
7660 static void genlshTwo (operand *result,operand *left, int shCount)
7664 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7665 size = pic16_getDataSize(result);
7667 /* if shCount >= 8 */
7673 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7675 movLeft2Result(left, LSB, result, MSB16);
7677 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7680 /* 1 <= shCount <= 7 */
7683 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7685 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7689 /*-----------------------------------------------------------------*/
7690 /* shiftLLong - shift left one long from left to result */
7691 /* offr = LSB or MSB16 */
7692 /*-----------------------------------------------------------------*/
7693 static void shiftLLong (operand *left, operand *result, int offr )
7695 int size = AOP_SIZE(result);
7696 int same = pic16_sameRegs(AOP(left),AOP(result));
7699 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7701 if (same && (offr == MSB16)) { //shift one byte
7702 for(i=size-1;i>=MSB16;i--) {
7703 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7704 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7707 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7710 if (size >= LSB+offr ){
7712 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7714 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7715 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7719 if(size >= MSB16+offr){
7721 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7723 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7724 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7728 if(size >= MSB24+offr){
7730 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7732 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7733 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7737 if(size > MSB32+offr){
7739 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7741 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7742 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7746 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7750 /*-----------------------------------------------------------------*/
7751 /* genlshFour - shift four byte by a known amount != 0 */
7752 /*-----------------------------------------------------------------*/
7753 static void genlshFour (operand *result, operand *left, int shCount)
7757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7758 size = AOP_SIZE(result);
7760 /* if shifting more that 3 bytes */
7761 if (shCount >= 24 ) {
7764 /* lowest order of left goes to the highest
7765 order of the destination */
7766 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7768 movLeft2Result(left, LSB, result, MSB32);
7770 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7771 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7772 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7777 /* more than two bytes */
7778 else if ( shCount >= 16 ) {
7779 /* lower order two bytes goes to higher order two bytes */
7781 /* if some more remaining */
7783 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7785 movLeft2Result(left, MSB16, result, MSB32);
7786 movLeft2Result(left, LSB, result, MSB24);
7788 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7789 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7793 /* if more than 1 byte */
7794 else if ( shCount >= 8 ) {
7795 /* lower order three bytes goes to higher order three bytes */
7799 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7801 movLeft2Result(left, LSB, result, MSB16);
7803 else{ /* size = 4 */
7805 movLeft2Result(left, MSB24, result, MSB32);
7806 movLeft2Result(left, MSB16, result, MSB24);
7807 movLeft2Result(left, LSB, result, MSB16);
7808 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7810 else if(shCount == 1)
7811 shiftLLong(left, result, MSB16);
7813 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7814 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7815 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7816 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7821 /* 1 <= shCount <= 7 */
7822 else if(shCount <= 3)
7824 shiftLLong(left, result, LSB);
7825 while(--shCount >= 1)
7826 shiftLLong(result, result, LSB);
7828 /* 3 <= shCount <= 7, optimize */
7830 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7831 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7832 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7836 /*-----------------------------------------------------------------*/
7837 /* genLeftShiftLiteral - left shifting by known count */
7838 /*-----------------------------------------------------------------*/
7839 static void genLeftShiftLiteral (operand *left,
7844 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7847 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7848 pic16_freeAsmop(right,NULL,ic,TRUE);
7850 pic16_aopOp(left,ic,FALSE);
7851 pic16_aopOp(result,ic,FALSE);
7853 size = getSize(operandType(result));
7856 pic16_emitcode("; shift left ","result %d, left %d",size,
7860 /* I suppose that the left size >= result size */
7863 movLeft2Result(left, size, result, size);
7867 else if(shCount >= (size * 8))
7869 pic16_aopPut(AOP(result),zero,size);
7873 genlshOne (result,left,shCount);
7878 genlshTwo (result,left,shCount);
7882 genlshFour (result,left,shCount);
7886 pic16_freeAsmop(left,NULL,ic,TRUE);
7887 pic16_freeAsmop(result,NULL,ic,TRUE);
7890 /*-----------------------------------------------------------------*
7891 * genMultiAsm - repeat assembly instruction for size of register.
7892 * if endian == 1, then the high byte (i.e base address + size of
7893 * register) is used first else the low byte is used first;
7894 *-----------------------------------------------------------------*/
7895 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7913 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7918 /*-----------------------------------------------------------------*/
7919 /* genLeftShift - generates code for left shifting */
7920 /*-----------------------------------------------------------------*/
7921 static void genLeftShift (iCode *ic)
7923 operand *left,*right, *result;
7926 symbol *tlbl , *tlbl1;
7929 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7931 right = IC_RIGHT(ic);
7933 result = IC_RESULT(ic);
7935 pic16_aopOp(right,ic,FALSE);
7937 /* if the shift count is known then do it
7938 as efficiently as possible */
7939 if (AOP_TYPE(right) == AOP_LIT) {
7940 genLeftShiftLiteral (left,right,result,ic);
7944 /* shift count is unknown then we have to form
7945 a loop get the loop count in B : Note: we take
7946 only the lower order byte since shifting
7947 more that 32 bits make no sense anyway, ( the
7948 largest size of an object can be only 32 bits ) */
7951 pic16_aopOp(left,ic,FALSE);
7952 pic16_aopOp(result,ic,FALSE);
7954 /* now move the left to the result if they are not the
7956 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
7957 AOP_SIZE(result) > 1) {
7959 size = AOP_SIZE(result);
7962 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7963 if (*l == '@' && (IS_AOP_PREG(result))) {
7965 pic16_emitcode("mov","a,%s",l);
7966 pic16_aopPut(AOP(result),"a",offset);
7968 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7969 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7970 //pic16_aopPut(AOP(result),l,offset);
7976 size = AOP_SIZE(result);
7978 /* if it is only one byte then */
7980 if(optimized_for_speed) {
7981 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7982 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7983 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7984 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7985 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
7986 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7987 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
7988 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
7989 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
7990 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
7991 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7992 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
7995 tlbl = newiTempLabel(NULL);
7996 if (!pic16_sameRegs(AOP(left),AOP(result))) {
7997 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8001 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8002 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8003 pic16_emitpLabel(tlbl->key);
8004 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8005 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8007 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8012 if (pic16_sameRegs(AOP(left),AOP(result))) {
8014 tlbl = newiTempLabel(NULL);
8015 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8016 genMultiAsm(POC_RRCF, result, size,1);
8017 pic16_emitpLabel(tlbl->key);
8018 genMultiAsm(POC_RLCF, result, size,0);
8019 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8021 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8025 //tlbl = newiTempLabel(NULL);
8027 //tlbl1 = newiTempLabel(NULL);
8029 //reAdjustPreg(AOP(result));
8031 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8032 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8033 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8035 //pic16_emitcode("add","a,acc");
8036 //pic16_aopPut(AOP(result),"a",offset++);
8038 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8040 // pic16_emitcode("rlc","a");
8041 // pic16_aopPut(AOP(result),"a",offset++);
8043 //reAdjustPreg(AOP(result));
8045 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8046 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8049 tlbl = newiTempLabel(NULL);
8050 tlbl1= newiTempLabel(NULL);
8052 size = AOP_SIZE(result);
8055 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8057 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8059 /* offset should be 0, 1 or 3 */
8061 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8063 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8065 pic16_emitpcode(POC_MOVWF, pctemp);
8068 pic16_emitpLabel(tlbl->key);
8071 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8073 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8075 pic16_emitpcode(POC_DECFSZ, pctemp);
8076 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8077 pic16_emitpLabel(tlbl1->key);
8079 pic16_popReleaseTempReg(pctemp);
8083 pic16_freeAsmop (right,NULL,ic,TRUE);
8084 pic16_freeAsmop(left,NULL,ic,TRUE);
8085 pic16_freeAsmop(result,NULL,ic,TRUE);
8088 /*-----------------------------------------------------------------*/
8089 /* genrshOne - right shift a one byte quantity by known count */
8090 /*-----------------------------------------------------------------*/
8091 static void genrshOne (operand *result, operand *left,
8092 int shCount, int sign)
8094 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8095 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8098 /*-----------------------------------------------------------------*/
8099 /* genrshTwo - right shift two bytes by known amount != 0 */
8100 /*-----------------------------------------------------------------*/
8101 static void genrshTwo (operand *result,operand *left,
8102 int shCount, int sign)
8104 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8105 /* if shCount >= 8 */
8109 shiftR1Left2Result(left, MSB16, result, LSB,
8112 movLeft2Result(left, MSB16, result, LSB);
8114 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8117 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8118 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8122 /* 1 <= shCount <= 7 */
8124 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8127 /*-----------------------------------------------------------------*/
8128 /* shiftRLong - shift right one long from left to result */
8129 /* offl = LSB or MSB16 */
8130 /*-----------------------------------------------------------------*/
8131 static void shiftRLong (operand *left, int offl,
8132 operand *result, int sign)
8134 int size = AOP_SIZE(result);
8135 int same = pic16_sameRegs(AOP(left),AOP(result));
8137 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8139 if (same && (offl == MSB16)) { //shift one byte right
8140 for(i=MSB16;i<size;i++) {
8141 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8142 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8147 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8153 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8155 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8156 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8160 /* add sign of "a" */
8161 pic16_addSign(result, MSB32, sign);
8165 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8167 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8168 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8172 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8174 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8175 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8179 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8182 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8183 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8188 /*-----------------------------------------------------------------*/
8189 /* genrshFour - shift four byte by a known amount != 0 */
8190 /*-----------------------------------------------------------------*/
8191 static void genrshFour (operand *result, operand *left,
8192 int shCount, int sign)
8194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8195 /* if shifting more that 3 bytes */
8196 if(shCount >= 24 ) {
8199 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8201 movLeft2Result(left, MSB32, result, LSB);
8203 pic16_addSign(result, MSB16, sign);
8205 else if(shCount >= 16){
8208 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8210 movLeft2Result(left, MSB24, result, LSB);
8211 movLeft2Result(left, MSB32, result, MSB16);
8213 pic16_addSign(result, MSB24, sign);
8215 else if(shCount >= 8){
8218 shiftRLong(left, MSB16, result, sign);
8219 else if(shCount == 0){
8220 movLeft2Result(left, MSB16, result, LSB);
8221 movLeft2Result(left, MSB24, result, MSB16);
8222 movLeft2Result(left, MSB32, result, MSB24);
8223 pic16_addSign(result, MSB32, sign);
8225 else{ //shcount >= 2
8226 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8227 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8228 /* the last shift is signed */
8229 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8230 pic16_addSign(result, MSB32, sign);
8233 else{ /* 1 <= shCount <= 7 */
8235 shiftRLong(left, LSB, result, sign);
8237 shiftRLong(result, LSB, result, sign);
8240 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8241 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8242 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8247 /*-----------------------------------------------------------------*/
8248 /* genRightShiftLiteral - right shifting by known count */
8249 /*-----------------------------------------------------------------*/
8250 static void genRightShiftLiteral (operand *left,
8256 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8259 pic16_freeAsmop(right,NULL,ic,TRUE);
8261 pic16_aopOp(left,ic,FALSE);
8262 pic16_aopOp(result,ic,FALSE);
8264 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8267 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8271 lsize = pic16_getDataSize(left);
8272 res_size = pic16_getDataSize(result);
8273 /* test the LEFT size !!! */
8275 /* I suppose that the left size >= result size */
8278 movLeft2Result(left, lsize, result, res_size);
8281 else if(shCount >= (lsize * 8)){
8284 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8286 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8287 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8292 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8293 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8294 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8296 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8301 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8308 genrshOne (result,left,shCount,sign);
8312 genrshTwo (result,left,shCount,sign);
8316 genrshFour (result,left,shCount,sign);
8324 pic16_freeAsmop(left,NULL,ic,TRUE);
8325 pic16_freeAsmop(result,NULL,ic,TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genSignedRightShift - right shift of signed number */
8330 /*-----------------------------------------------------------------*/
8331 static void genSignedRightShift (iCode *ic)
8333 operand *right, *left, *result;
8336 symbol *tlbl, *tlbl1 ;
8339 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8341 /* we do it the hard way put the shift count in b
8342 and loop thru preserving the sign */
8343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8345 right = IC_RIGHT(ic);
8347 result = IC_RESULT(ic);
8349 pic16_aopOp(right,ic,FALSE);
8350 pic16_aopOp(left,ic,FALSE);
8351 pic16_aopOp(result,ic,FALSE);
8354 if ( AOP_TYPE(right) == AOP_LIT) {
8355 genRightShiftLiteral (left,right,result,ic,1);
8358 /* shift count is unknown then we have to form
8359 a loop get the loop count in B : Note: we take
8360 only the lower order byte since shifting
8361 more that 32 bits make no sense anyway, ( the
8362 largest size of an object can be only 32 bits ) */
8364 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8365 //pic16_emitcode("inc","b");
8366 //pic16_freeAsmop (right,NULL,ic,TRUE);
8367 //pic16_aopOp(left,ic,FALSE);
8368 //pic16_aopOp(result,ic,FALSE);
8370 /* now move the left to the result if they are not the
8372 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8373 AOP_SIZE(result) > 1) {
8375 size = AOP_SIZE(result);
8379 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8380 if (*l == '@' && IS_AOP_PREG(result)) {
8382 pic16_emitcode("mov","a,%s",l);
8383 pic16_aopPut(AOP(result),"a",offset);
8385 pic16_aopPut(AOP(result),l,offset);
8387 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8388 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8394 /* mov the highest order bit to OVR */
8395 tlbl = newiTempLabel(NULL);
8396 tlbl1= newiTempLabel(NULL);
8398 size = AOP_SIZE(result);
8401 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8403 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8405 /* offset should be 0, 1 or 3 */
8406 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8410 pic16_emitpcode(POC_MOVWF, pctemp);
8413 pic16_emitpLabel(tlbl->key);
8415 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8416 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8419 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8422 pic16_emitpcode(POC_DECFSZ, pctemp);
8423 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8424 pic16_emitpLabel(tlbl1->key);
8426 pic16_popReleaseTempReg(pctemp);
8428 size = AOP_SIZE(result);
8430 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8431 pic16_emitcode("rlc","a");
8432 pic16_emitcode("mov","ov,c");
8433 /* if it is only one byte then */
8435 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8437 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8438 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8439 pic16_emitcode("mov","c,ov");
8440 pic16_emitcode("rrc","a");
8441 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8442 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8443 pic16_aopPut(AOP(result),"a",0);
8447 reAdjustPreg(AOP(result));
8448 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8449 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8450 pic16_emitcode("mov","c,ov");
8452 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8454 pic16_emitcode("rrc","a");
8455 pic16_aopPut(AOP(result),"a",offset--);
8457 reAdjustPreg(AOP(result));
8458 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8459 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8464 pic16_freeAsmop(left,NULL,ic,TRUE);
8465 pic16_freeAsmop(result,NULL,ic,TRUE);
8466 pic16_freeAsmop(right,NULL,ic,TRUE);
8469 /*-----------------------------------------------------------------*/
8470 /* genRightShift - generate code for right shifting */
8471 /*-----------------------------------------------------------------*/
8472 static void genRightShift (iCode *ic)
8474 operand *right, *left, *result;
8478 symbol *tlbl, *tlbl1 ;
8480 /* if signed then we do it the hard way preserve the
8481 sign bit moving it inwards */
8482 letype = getSpec(operandType(IC_LEFT(ic)));
8483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8485 if (!SPEC_USIGN(letype)) {
8486 genSignedRightShift (ic);
8490 /* signed & unsigned types are treated the same : i.e. the
8491 signed is NOT propagated inwards : quoting from the
8492 ANSI - standard : "for E1 >> E2, is equivalent to division
8493 by 2**E2 if unsigned or if it has a non-negative value,
8494 otherwise the result is implementation defined ", MY definition
8495 is that the sign does not get propagated */
8497 right = IC_RIGHT(ic);
8499 result = IC_RESULT(ic);
8501 pic16_aopOp(right,ic,FALSE);
8503 /* if the shift count is known then do it
8504 as efficiently as possible */
8505 if (AOP_TYPE(right) == AOP_LIT) {
8506 genRightShiftLiteral (left,right,result,ic, 0);
8510 /* shift count is unknown then we have to form
8511 a loop get the loop count in B : Note: we take
8512 only the lower order byte since shifting
8513 more that 32 bits make no sense anyway, ( the
8514 largest size of an object can be only 32 bits ) */
8516 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8517 pic16_emitcode("inc","b");
8518 pic16_aopOp(left,ic,FALSE);
8519 pic16_aopOp(result,ic,FALSE);
8521 /* now move the left to the result if they are not the
8523 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8524 AOP_SIZE(result) > 1) {
8526 size = AOP_SIZE(result);
8529 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8530 if (*l == '@' && IS_AOP_PREG(result)) {
8532 pic16_emitcode("mov","a,%s",l);
8533 pic16_aopPut(AOP(result),"a",offset);
8535 pic16_aopPut(AOP(result),l,offset);
8540 tlbl = newiTempLabel(NULL);
8541 tlbl1= newiTempLabel(NULL);
8542 size = AOP_SIZE(result);
8545 /* if it is only one byte then */
8548 tlbl = newiTempLabel(NULL);
8549 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8550 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8551 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8554 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8555 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8556 pic16_emitpLabel(tlbl->key);
8557 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8558 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8560 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8565 reAdjustPreg(AOP(result));
8566 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8567 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8570 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8572 pic16_emitcode("rrc","a");
8573 pic16_aopPut(AOP(result),"a",offset--);
8575 reAdjustPreg(AOP(result));
8577 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8578 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8581 pic16_freeAsmop(left,NULL,ic,TRUE);
8582 pic16_freeAsmop (right,NULL,ic,TRUE);
8583 pic16_freeAsmop(result,NULL,ic,TRUE);
8586 /*-----------------------------------------------------------------*/
8587 /* genUnpackBits - generates code for unpacking bits */
8588 /*-----------------------------------------------------------------*/
8589 static void genUnpackBits (operand *result, char *rname, int ptype)
8596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8597 etype = getSpec(operandType(result));
8599 /* read the first byte */
8606 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8609 pic16_emitcode("clr","a");
8610 pic16_emitcode("movc","a","@a+dptr");
8615 /* if we have bitdisplacement then it fits */
8616 /* into this byte completely or if length is */
8617 /* less than a byte */
8618 if ((shCnt = SPEC_BSTR(etype)) ||
8619 (SPEC_BLEN(etype) <= 8)) {
8621 /* shift right acc */
8624 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8625 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8627 /* VR -- normally I would use the following, but since we use the hack,
8628 * to avoid the masking from AccRsh, why not mask it right now? */
8631 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8634 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8640 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8641 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8644 /* bit field did not fit in a byte */
8645 rlen = SPEC_BLEN(etype) - 8;
8646 pic16_aopPut(AOP(result),"a",offset++);
8653 pic16_emitcode("inc","%s",rname);
8654 pic16_emitcode("mov","a,@%s",rname);
8658 pic16_emitcode("inc","%s",rname);
8659 pic16_emitcode("movx","a,@%s",rname);
8663 pic16_emitcode("inc","dptr");
8664 pic16_emitcode("movx","a,@dptr");
8668 pic16_emitcode("clr","a");
8669 pic16_emitcode("inc","dptr");
8670 pic16_emitcode("movc","a","@a+dptr");
8674 pic16_emitcode("inc","dptr");
8675 pic16_emitcode("lcall","__gptrget");
8680 /* if we are done */
8684 pic16_aopPut(AOP(result),"a",offset++);
8689 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8690 pic16_aopPut(AOP(result),"a",offset);
8697 static void genDataPointerGet(operand *left,
8701 int size, offset = 0, leoffset=0 ;
8703 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8704 pic16_aopOp(result, ic, FALSE);
8706 size = AOP_SIZE(result);
8707 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8711 /* The following tests may save a redudant movff instruction when
8712 * accessing unions */
8714 /* if they are the same */
8715 if (operandsEqu (left, result)) {
8716 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8720 /* if they are the same registers */
8721 if (pic16_sameRegs(AOP(left),AOP(result))) {
8722 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8728 if ( AOP_TYPE(left) == AOP_PCODE) {
8729 fprintf(stderr,"genDataPointerGet %s, %d\n",
8730 AOP(left)->aopu.pcop->name,
8731 (AOP(left)->aopu.pcop->type == PO_DIR)?
8732 PCOR(AOP(left)->aopu.pcop)->instance:
8733 PCOI(AOP(left)->aopu.pcop)->offset);
8737 if(AOP(left)->aopu.pcop->type == PO_DIR)
8738 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8740 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8743 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8745 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8746 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8747 mov2w(AOP(left), offset); // patch 8
8748 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8750 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8751 pic16_popGet(AOP(left), offset), //patch 8
8752 pic16_popGet(AOP(result), offset)));
8760 pic16_freeAsmop(result,NULL,ic,TRUE);
8763 void pic16_loadFSR0(operand *op)
8765 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8769 /*-----------------------------------------------------------------*/
8770 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8771 /*-----------------------------------------------------------------*/
8772 static void genNearPointerGet (operand *left,
8777 //regs *preg = NULL ;
8778 sym_link *rtype, *retype;
8779 sym_link *ltype = operandType(left);
8781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8782 rtype = operandType(result);
8783 retype= getSpec(rtype);
8785 pic16_aopOp(left,ic,FALSE);
8787 pic16_DumpOp("(left)",left);
8788 pic16_DumpOp("(result)",result);
8790 /* if left is rematerialisable and
8791 * result is not bit variable type and
8792 * the left is pointer to data space i.e
8793 * lower 128 bytes of space */
8794 if (AOP_TYPE(left) == AOP_PCODE
8795 && !IS_BITFIELD(retype)
8796 && DCL_TYPE(ltype) == POINTER) {
8798 genDataPointerGet (left,result,ic);
8799 pic16_freeAsmop(left, NULL, ic, TRUE);
8803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8805 /* if the value is already in a pointer register
8806 * then don't need anything more */
8807 if (!AOP_INPREG(AOP(left))) {
8808 /* otherwise get a free pointer register */
8809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8811 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8812 if( (AOP_TYPE(left) == AOP_PCODE)
8813 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8814 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
8816 pic16_loadFSR0( left ); // patch 10
8818 // set up FSR0 with address from left
8819 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
8820 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
8824 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8826 pic16_aopOp (result,ic,FALSE);
8828 /* if bitfield then unpack the bits */
8829 if (IS_BITFIELD(retype))
8830 genUnpackBits (result, NULL, POINTER);
8832 /* we have can just get the values */
8833 int size = AOP_SIZE(result);
8836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8839 /* fsr0 is loaded already -- VR */
8840 // pic16_loadFSR0( left );
8842 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8843 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8847 pic16_emitpcode(POC_MOVFF,
8848 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8849 pic16_popGet(AOP(result), offset++)));
8851 pic16_emitpcode(POC_MOVFF,
8852 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8853 pic16_popGet(AOP(result), offset++)));
8857 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8858 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8860 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8864 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8866 pic16_emitcode("mov","a,@%s",rname);
8867 pic16_aopPut(AOP(result),"a",offset);
8869 sprintf(buffer,"@%s",rname);
8870 pic16_aopPut(AOP(result),buffer,offset);
8874 pic16_emitcode("inc","%s",rname);
8879 /* now some housekeeping stuff */
8881 /* we had to allocate for this iCode */
8882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8883 pic16_freeAsmop(NULL,aop,ic,TRUE);
8885 /* we did not allocate which means left
8886 already in a pointer register, then
8887 if size > 0 && this could be used again
8888 we have to point it back to where it
8890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8891 if (AOP_SIZE(result) > 1 &&
8892 !OP_SYMBOL(left)->remat &&
8893 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8895 // int size = AOP_SIZE(result) - 1;
8897 // pic16_emitcode("dec","%s",rname);
8902 pic16_freeAsmop(left,NULL,ic,TRUE);
8903 pic16_freeAsmop(result,NULL,ic,TRUE);
8907 /*-----------------------------------------------------------------*/
8908 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
8909 /*-----------------------------------------------------------------*/
8910 static void genPagedPointerGet (operand *left,
8917 sym_link *rtype, *retype;
8919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8921 rtype = operandType(result);
8922 retype= getSpec(rtype);
8924 pic16_aopOp(left,ic,FALSE);
8926 /* if the value is already in a pointer register
8927 then don't need anything more */
8928 if (!AOP_INPREG(AOP(left))) {
8929 /* otherwise get a free pointer register */
8931 preg = getFreePtr(ic,&aop,FALSE);
8932 pic16_emitcode("mov","%s,%s",
8934 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8935 rname = preg->name ;
8937 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8939 pic16_freeAsmop(left,NULL,ic,TRUE);
8940 pic16_aopOp (result,ic,FALSE);
8942 /* if bitfield then unpack the bits */
8943 if (IS_BITFIELD(retype))
8944 genUnpackBits (result,rname,PPOINTER);
8946 /* we have can just get the values */
8947 int size = AOP_SIZE(result);
8952 pic16_emitcode("movx","a,@%s",rname);
8953 pic16_aopPut(AOP(result),"a",offset);
8958 pic16_emitcode("inc","%s",rname);
8962 /* now some housekeeping stuff */
8964 /* we had to allocate for this iCode */
8965 pic16_freeAsmop(NULL,aop,ic,TRUE);
8967 /* we did not allocate which means left
8968 already in a pointer register, then
8969 if size > 0 && this could be used again
8970 we have to point it back to where it
8972 if (AOP_SIZE(result) > 1 &&
8973 !OP_SYMBOL(left)->remat &&
8974 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8976 int size = AOP_SIZE(result) - 1;
8978 pic16_emitcode("dec","%s",rname);
8983 pic16_freeAsmop(result,NULL,ic,TRUE);
8988 /*-----------------------------------------------------------------*/
8989 /* genFarPointerGet - gget value from far space */
8990 /*-----------------------------------------------------------------*/
8991 static void genFarPointerGet (operand *left,
8992 operand *result, iCode *ic)
8995 sym_link *retype = getSpec(operandType(result));
8997 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8999 pic16_aopOp(left,ic,FALSE);
9001 /* if the operand is already in dptr
9002 then we do nothing else we move the value to dptr */
9003 if (AOP_TYPE(left) != AOP_STR) {
9004 /* if this is remateriazable */
9005 if (AOP_TYPE(left) == AOP_IMMD)
9006 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9007 else { /* we need to get it byte by byte */
9008 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9009 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9010 if (options.model == MODEL_FLAT24)
9012 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9016 /* so dptr know contains the address */
9017 pic16_freeAsmop(left,NULL,ic,TRUE);
9018 pic16_aopOp(result,ic,FALSE);
9020 /* if bit then unpack */
9021 if (IS_BITFIELD(retype))
9022 genUnpackBits(result,"dptr",FPOINTER);
9024 size = AOP_SIZE(result);
9028 pic16_emitcode("movx","a,@dptr");
9029 pic16_aopPut(AOP(result),"a",offset++);
9031 pic16_emitcode("inc","dptr");
9035 pic16_freeAsmop(result,NULL,ic,TRUE);
9038 /*-----------------------------------------------------------------*/
9039 /* genCodePointerGet - get value from code space */
9040 /*-----------------------------------------------------------------*/
9041 static void genCodePointerGet (operand *left,
9042 operand *result, iCode *ic)
9045 sym_link *retype = getSpec(operandType(result));
9047 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9049 pic16_aopOp(left,ic,FALSE);
9051 /* if the operand is already in dptr
9052 then we do nothing else we move the value to dptr */
9053 if (AOP_TYPE(left) != AOP_STR) {
9054 /* if this is remateriazable */
9055 if (AOP_TYPE(left) == AOP_IMMD)
9056 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9057 else { /* we need to get it byte by byte */
9058 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9059 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9060 if (options.model == MODEL_FLAT24)
9062 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9066 /* so dptr know contains the address */
9067 pic16_freeAsmop(left,NULL,ic,TRUE);
9068 pic16_aopOp(result,ic,FALSE);
9070 /* if bit then unpack */
9071 if (IS_BITFIELD(retype))
9072 genUnpackBits(result,"dptr",CPOINTER);
9074 size = AOP_SIZE(result);
9078 pic16_emitcode("clr","a");
9079 pic16_emitcode("movc","a,@a+dptr");
9080 pic16_aopPut(AOP(result),"a",offset++);
9082 pic16_emitcode("inc","dptr");
9086 pic16_freeAsmop(result,NULL,ic,TRUE);
9089 /*-----------------------------------------------------------------*/
9090 /* genGenPointerGet - gget value from generic pointer space */
9091 /*-----------------------------------------------------------------*/
9092 static void genGenPointerGet (operand *left,
9093 operand *result, iCode *ic)
9095 int size, offset, lit;
9096 sym_link *retype = getSpec(operandType(result));
9098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9099 pic16_aopOp(left,ic,FALSE);
9100 pic16_aopOp(result,ic,FALSE);
9101 size = AOP_SIZE(result);
9103 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9105 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9107 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9108 // load FSR0 from immediate
9109 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9111 // pic16_loadFSR0( left );
9116 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9118 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9125 else { /* we need to get it byte by byte */
9126 // set up FSR0 with address from left
9127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9128 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9134 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9136 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9143 /* if bit then unpack */
9144 if (IS_BITFIELD(retype))
9145 genUnpackBits(result,"BAD",GPOINTER);
9148 pic16_freeAsmop(left,NULL,ic,TRUE);
9149 pic16_freeAsmop(result,NULL,ic,TRUE);
9153 /*-----------------------------------------------------------------*/
9154 /* genConstPointerGet - get value from const generic pointer space */
9155 /*-----------------------------------------------------------------*/
9156 static void genConstPointerGet (operand *left,
9157 operand *result, iCode *ic)
9159 //sym_link *retype = getSpec(operandType(result));
9160 // symbol *albl = newiTempLabel(NULL); // patch 15
9161 // symbol *blbl = newiTempLabel(NULL); //
9162 // PIC_OPCODE poc; // patch 15
9166 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9167 pic16_aopOp(left,ic,FALSE);
9168 pic16_aopOp(result,ic,TRUE);
9169 size = AOP_SIZE(result);
9171 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9173 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9175 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9176 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9177 pic16_emitpLabel(albl->key);
9179 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9181 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9182 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9183 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9184 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9185 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9187 pic16_emitpLabel(blbl->key);
9189 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9193 // set up table pointer
9194 if( (AOP_TYPE(left) == AOP_PCODE)
9195 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9196 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9198 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9199 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9200 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9201 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9202 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9203 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9208 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9209 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9215 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9216 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9220 pic16_freeAsmop(left,NULL,ic,TRUE);
9221 pic16_freeAsmop(result,NULL,ic,TRUE);
9224 /*-----------------------------------------------------------------*/
9225 /* genPointerGet - generate code for pointer get */
9226 /*-----------------------------------------------------------------*/
9227 static void genPointerGet (iCode *ic)
9229 operand *left, *result ;
9230 sym_link *type, *etype;
9233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9236 result = IC_RESULT(ic) ;
9238 /* depending on the type of pointer we need to
9239 move it to the correct pointer register */
9240 type = operandType(left);
9241 etype = getSpec(type);
9244 if (IS_PTR_CONST(type))
9246 if (IS_CODEPTR(type))
9248 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9250 /* if left is of type of pointer then it is simple */
9251 if (IS_PTR(type) && !IS_FUNC(type->next))
9252 p_type = DCL_TYPE(type);
9254 /* we have to go by the storage class */
9255 p_type = PTR_TYPE(SPEC_OCLS(etype));
9257 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9259 if (SPEC_OCLS(etype)->codesp ) {
9260 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9261 //p_type = CPOINTER ;
9264 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9265 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9266 /*p_type = FPOINTER ;*/
9268 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9269 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9270 /* p_type = PPOINTER; */
9272 if (SPEC_OCLS(etype) == idata )
9273 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9274 /* p_type = IPOINTER; */
9276 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9277 /* p_type = POINTER ; */
9280 /* now that we have the pointer type we assign
9281 the pointer values */
9286 genNearPointerGet (left,result,ic);
9290 genPagedPointerGet(left,result,ic);
9294 genFarPointerGet (left,result,ic);
9298 genConstPointerGet (left,result,ic);
9299 //pic16_emitcodePointerGet (left,result,ic);
9304 if (IS_PTR_CONST(type))
9305 genConstPointerGet (left,result,ic);
9308 genGenPointerGet (left,result,ic);
9314 /*-----------------------------------------------------------------*/
9315 /* genPackBits - generates code for packed bit storage */
9316 /*-----------------------------------------------------------------*/
9317 static void genPackBits (sym_link *etype ,
9319 char *rname, int p_type)
9327 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9328 blen = SPEC_BLEN(etype);
9329 bstr = SPEC_BSTR(etype);
9331 if(AOP_TYPE(right) == AOP_LIT) {
9332 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9337 /* l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9340 /* if the bit lenth is less than or */
9341 /* it exactly fits a byte then */
9342 if((shCnt=SPEC_BSTR(etype))
9343 || SPEC_BLEN(etype) <= 8 ) {
9345 /* shift left acc */
9348 /* using PRODL as a temporary register here */
9349 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9355 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9356 // pic16_emitcode ("mov","b,a");
9357 // pic16_emitcode("mov","a,@%s",rname);
9361 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9362 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9363 (unsigned char)(0xff >> (8-bstr))) ));
9364 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9365 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9369 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9370 ((unsigned char)(0xFF << (blen+bstr)) |
9371 (unsigned char)(0xFF >> (8-bstr)) ) );
9372 pic16_emitcode ("orl","a,b");
9373 if (p_type == GPOINTER)
9374 pic16_emitcode("pop","b");
9379 pic16_emitcode("mov","@%s,a",rname);
9382 pic16_emitcode("movx","@dptr,a");
9385 DEBUGpic16_emitcode(";lcall","__gptrput");
9394 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9395 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9400 if ( SPEC_BLEN(etype) <= 8 )
9403 pic16_emitcode("inc","%s",rname);
9404 rLen = SPEC_BLEN(etype) ;
9408 /* now generate for lengths greater than one byte */
9411 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9421 pic16_emitcode("mov","@%s,a",rname);
9423 pic16_emitcode("mov","@%s,%s",rname,l);
9428 pic16_emitcode("movx","@dptr,a");
9433 DEBUGpic16_emitcode(";lcall","__gptrput");
9436 pic16_emitcode ("inc","%s",rname);
9441 /* last last was not complete */
9443 /* save the byte & read byte */
9446 pic16_emitcode ("mov","b,a");
9447 pic16_emitcode("mov","a,@%s",rname);
9451 pic16_emitcode ("mov","b,a");
9452 pic16_emitcode("movx","a,@dptr");
9456 pic16_emitcode ("push","b");
9457 pic16_emitcode ("push","acc");
9458 pic16_emitcode ("lcall","__gptrget");
9459 pic16_emitcode ("pop","b");
9463 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9464 pic16_emitcode ("orl","a,b");
9467 if (p_type == GPOINTER)
9468 pic16_emitcode("pop","b");
9473 pic16_emitcode("mov","@%s,a",rname);
9477 pic16_emitcode("movx","@dptr,a");
9481 DEBUGpic16_emitcode(";lcall","__gptrput");
9485 /*-----------------------------------------------------------------*/
9486 /* genDataPointerSet - remat pointer to data space */
9487 /*-----------------------------------------------------------------*/
9488 static void genDataPointerSet(operand *right,
9492 int size, offset = 0, resoffset=0 ;
9494 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9495 pic16_aopOp(right,ic,FALSE);
9497 size = AOP_SIZE(right);
9499 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9502 if ( AOP_TYPE(result) == AOP_PCODE) {
9503 fprintf(stderr,"genDataPointerSet %s, %d\n",
9504 AOP(result)->aopu.pcop->name,
9505 (AOP(result)->aopu.pcop->type == PO_DIR)?
9506 PCOR(AOP(result)->aopu.pcop)->instance:
9507 PCOI(AOP(result)->aopu.pcop)->offset);
9511 if(AOP(result)->aopu.pcop->type == PO_DIR)
9512 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9515 if (AOP_TYPE(right) == AOP_LIT) {
9516 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9518 lit = lit >> (8*offset);
9520 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9523 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9526 mov2w(AOP(right), offset);
9527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9533 pic16_freeAsmop(right,NULL,ic,TRUE);
9538 /*-----------------------------------------------------------------*/
9539 /* genNearPointerSet - pic16_emitcode for near pointer put */
9540 /*-----------------------------------------------------------------*/
9541 static void genNearPointerSet (operand *right,
9548 sym_link *ptype = operandType(result);
9551 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9552 retype= getSpec(operandType(right));
9553 resetype = getSpec(operandType(result));
9555 pic16_aopOp(result,ic,FALSE);
9557 /* if the result is rematerializable &
9558 * in data space & not a bit variable */
9560 /* and result is not a bit variable */
9561 if (AOP_TYPE(result) == AOP_PCODE
9562 // && AOP_TYPE(result) == AOP_IMMD
9563 && DCL_TYPE(ptype) == POINTER
9564 && !IS_BITFIELD(retype)
9565 && !IS_BITFIELD(resetype)) {
9567 genDataPointerSet (right,result,ic);
9568 pic16_freeAsmop(result,NULL,ic,TRUE);
9572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9573 pic16_aopOp(right,ic,FALSE);
9574 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9576 /* if the value is already in a pointer register
9577 * then don't need anything more */
9578 if (!AOP_INPREG(AOP(result))) {
9579 /* otherwise get a free pointer register */
9580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9582 if( (AOP_TYPE(result) == AOP_PCODE)
9583 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9584 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9586 pic16_loadFSR0( result ); // patch 10
9588 // set up FSR0 with address of result
9589 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9590 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9595 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9599 /* if bitfield then unpack the bits */
9600 if (IS_BITFIELD(resetype)) {
9601 genPackBits (resetype, right, NULL, POINTER);
9603 /* we have can just get the values */
9604 int size = AOP_SIZE(right);
9607 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9609 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9612 //pic16_emitcode("mov","@%s,a",rname);
9613 pic16_emitcode("movf","indf0,w ;1");
9616 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
9617 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
9619 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
9621 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
9623 } else { // no literal //
9625 pic16_emitpcode(POC_MOVFF, //
9626 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
9627 pic16_popCopyReg(&pic16_pc_postinc0))); //
9629 pic16_emitpcode(POC_MOVFF, //
9630 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
9631 pic16_popCopyReg(&pic16_pc_indf0))); //
9639 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9640 /* now some housekeeping stuff */
9642 /* we had to allocate for this iCode */
9643 pic16_freeAsmop(NULL,aop,ic,TRUE);
9645 /* we did not allocate which means left
9646 * already in a pointer register, then
9647 * if size > 0 && this could be used again
9648 * we have to point it back to where it
9650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9651 if (AOP_SIZE(right) > 1
9652 && !OP_SYMBOL(result)->remat
9653 && ( OP_SYMBOL(result)->liveTo > ic->seq
9656 int size = AOP_SIZE(right) - 1;
9659 pic16_emitcode("decf","fsr0,f");
9660 //pic16_emitcode("dec","%s",rname);
9664 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9667 pic16_freeAsmop(right,NULL,ic,TRUE);
9668 pic16_freeAsmop(result,NULL,ic,TRUE);
9671 /*-----------------------------------------------------------------*/
9672 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
9673 /*-----------------------------------------------------------------*/
9674 static void genPagedPointerSet (operand *right,
9683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9685 retype= getSpec(operandType(right));
9687 pic16_aopOp(result,ic,FALSE);
9689 /* if the value is already in a pointer register
9690 then don't need anything more */
9691 if (!AOP_INPREG(AOP(result))) {
9692 /* otherwise get a free pointer register */
9694 preg = getFreePtr(ic,&aop,FALSE);
9695 pic16_emitcode("mov","%s,%s",
9697 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9698 rname = preg->name ;
9700 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9702 pic16_freeAsmop(result,NULL,ic,TRUE);
9703 pic16_aopOp (right,ic,FALSE);
9705 /* if bitfield then unpack the bits */
9706 if (IS_BITFIELD(retype))
9707 genPackBits (retype,right,rname,PPOINTER);
9709 /* we have can just get the values */
9710 int size = AOP_SIZE(right);
9714 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9717 pic16_emitcode("movx","@%s,a",rname);
9720 pic16_emitcode("inc","%s",rname);
9726 /* now some housekeeping stuff */
9728 /* we had to allocate for this iCode */
9729 pic16_freeAsmop(NULL,aop,ic,TRUE);
9731 /* we did not allocate which means left
9732 already in a pointer register, then
9733 if size > 0 && this could be used again
9734 we have to point it back to where it
9736 if (AOP_SIZE(right) > 1 &&
9737 !OP_SYMBOL(result)->remat &&
9738 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9740 int size = AOP_SIZE(right) - 1;
9742 pic16_emitcode("dec","%s",rname);
9747 pic16_freeAsmop(right,NULL,ic,TRUE);
9752 /*-----------------------------------------------------------------*/
9753 /* genFarPointerSet - set value from far space */
9754 /*-----------------------------------------------------------------*/
9755 static void genFarPointerSet (operand *right,
9756 operand *result, iCode *ic)
9759 sym_link *retype = getSpec(operandType(right));
9761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9762 pic16_aopOp(result,ic,FALSE);
9764 /* if the operand is already in dptr
9765 then we do nothing else we move the value to dptr */
9766 if (AOP_TYPE(result) != AOP_STR) {
9767 /* if this is remateriazable */
9768 if (AOP_TYPE(result) == AOP_IMMD)
9769 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9770 else { /* we need to get it byte by byte */
9771 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9772 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9773 if (options.model == MODEL_FLAT24)
9775 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9779 /* so dptr know contains the address */
9780 pic16_freeAsmop(result,NULL,ic,TRUE);
9781 pic16_aopOp(right,ic,FALSE);
9783 /* if bit then unpack */
9784 if (IS_BITFIELD(retype))
9785 genPackBits(retype,right,"dptr",FPOINTER);
9787 size = AOP_SIZE(right);
9791 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9793 pic16_emitcode("movx","@dptr,a");
9795 pic16_emitcode("inc","dptr");
9799 pic16_freeAsmop(right,NULL,ic,TRUE);
9802 /*-----------------------------------------------------------------*/
9803 /* genGenPointerSet - set value from generic pointer space */
9804 /*-----------------------------------------------------------------*/
9805 static void genGenPointerSet (operand *right,
9806 operand *result, iCode *ic)
9808 int i, size, offset, lit;
9809 sym_link *retype = getSpec(operandType(right));
9811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9813 pic16_aopOp(result,ic,FALSE);
9814 pic16_aopOp(right,ic,FALSE);
9815 size = AOP_SIZE(right);
9818 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9820 /* if the operand is already in dptr
9821 then we do nothing else we move the value to dptr */
9822 if (AOP_TYPE(result) != AOP_STR) {
9823 /* if this is remateriazable */
9824 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9825 // WARNING: anythig until "else" is untested!
9826 if (AOP_TYPE(result) == AOP_IMMD) {
9827 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9828 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9829 // load FSR0 from immediate
9830 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9834 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9836 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9842 else { /* we need to get it byte by byte */
9843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9844 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9846 // set up FSR0 with address of result
9847 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9848 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9850 /* hack hack! see if this the FSR. If so don't load W */
9851 if(AOP_TYPE(right) != AOP_ACC) {
9853 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9855 if(AOP_TYPE(right) == AOP_LIT)
9858 // note: pic16_popGet handles sign extension
9859 for(i=0;i<size;i++) {
9860 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
9862 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
9864 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9869 for(i=0;i<size;i++) {
9871 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9872 pic16_popCopyReg(&pic16_pc_postinc0)));
9874 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9875 pic16_popCopyReg(&pic16_pc_indf0)));
9881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9882 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9884 } // if (AOP_TYPE(result) != AOP_IMMD)
9886 } // if (AOP_TYPE(result) != AOP_STR)
9887 /* so dptr know contains the address */
9890 /* if bit then unpack */
9891 if (IS_BITFIELD(retype))
9892 genPackBits(retype,right,"dptr",GPOINTER);
9894 size = AOP_SIZE(right);
9897 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
9899 // set up FSR0 with address of result
9900 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9901 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9904 if (AOP_TYPE(right) == AOP_LIT) {
9905 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9907 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9909 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9911 } else { // no literal
9913 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9915 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9923 pic16_freeAsmop(right,NULL,ic,TRUE);
9924 pic16_freeAsmop(result,NULL,ic,TRUE);
9927 /*-----------------------------------------------------------------*/
9928 /* genPointerSet - stores the value into a pointer location */
9929 /*-----------------------------------------------------------------*/
9930 static void genPointerSet (iCode *ic)
9932 operand *right, *result ;
9933 sym_link *type, *etype;
9936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9938 right = IC_RIGHT(ic);
9939 result = IC_RESULT(ic) ;
9941 /* depending on the type of pointer we need to
9942 move it to the correct pointer register */
9943 type = operandType(result);
9944 etype = getSpec(type);
9945 /* if left is of type of pointer then it is simple */
9946 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9947 p_type = DCL_TYPE(type);
9950 /* we have to go by the storage class */
9951 p_type = PTR_TYPE(SPEC_OCLS(etype));
9953 /* if (SPEC_OCLS(etype)->codesp ) { */
9954 /* p_type = CPOINTER ; */
9957 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9958 /* p_type = FPOINTER ; */
9960 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9961 /* p_type = PPOINTER ; */
9963 /* if (SPEC_OCLS(etype) == idata ) */
9964 /* p_type = IPOINTER ; */
9966 /* p_type = POINTER ; */
9969 /* now that we have the pointer type we assign
9970 the pointer values */
9975 genNearPointerSet (right,result,ic);
9979 genPagedPointerSet (right,result,ic);
9983 genFarPointerSet (right,result,ic);
9987 genGenPointerSet (right,result,ic);
9991 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9992 "genPointerSet: illegal pointer type");
9996 /*-----------------------------------------------------------------*/
9997 /* genIfx - generate code for Ifx statement */
9998 /*-----------------------------------------------------------------*/
9999 static void genIfx (iCode *ic, iCode *popIc)
10001 operand *cond = IC_COND(ic);
10004 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10006 pic16_aopOp(cond,ic,FALSE);
10008 /* get the value into acc */
10009 if (AOP_TYPE(cond) != AOP_CRY)
10010 pic16_toBoolean(cond);
10013 /* the result is now in the accumulator */
10014 pic16_freeAsmop(cond,NULL,ic,TRUE);
10016 /* if there was something to be popped then do it */
10020 /* if the condition is a bit variable */
10021 if (isbit && IS_ITEMP(cond) &&
10023 genIfxJump(ic,SPIL_LOC(cond)->rname);
10024 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10027 if (isbit && !IS_ITEMP(cond))
10028 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10030 genIfxJump(ic,"a");
10036 /*-----------------------------------------------------------------*/
10037 /* genAddrOf - generates code for address of */
10038 /*-----------------------------------------------------------------*/
10039 static void genAddrOf (iCode *ic)
10041 operand *result, *left;
10043 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10044 pCodeOp *pcop0, *pcop1, *pcop2;
10046 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10048 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10049 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10051 sym = OP_SYMBOL( left );
10053 size = AOP_SIZE(IC_RESULT(ic));
10055 if(pic16_debug_verbose) {
10056 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10057 __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10060 /* Assume that what we want the address of is in data space
10061 * since there is no stack on the PIC, yet! -- VR */
10063 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10066 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10069 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10073 pic16_emitpcode(POC_MOVLW, pcop0);
10074 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10075 pic16_emitpcode(POC_MOVLW, pcop1);
10076 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10077 pic16_emitpcode(POC_MOVLW, pcop2);
10078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10081 pic16_emitpcode(POC_MOVLW, pcop0);
10082 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10083 pic16_emitpcode(POC_MOVLW, pcop1);
10084 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10086 pic16_emitpcode(POC_MOVLW, pcop0);
10087 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10090 pic16_freeAsmop(result,NULL,ic,TRUE);
10091 pic16_freeAsmop(left, NULL, ic, FALSE);
10096 /*-----------------------------------------------------------------*/
10097 /* genFarFarAssign - assignment when both are in far space */
10098 /*-----------------------------------------------------------------*/
10099 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10101 int size = AOP_SIZE(right);
10104 /* first push the right side on to the stack */
10106 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10108 pic16_emitcode ("push","acc");
10111 pic16_freeAsmop(right,NULL,ic,FALSE);
10112 /* now assign DPTR to result */
10113 pic16_aopOp(result,ic,FALSE);
10114 size = AOP_SIZE(result);
10116 pic16_emitcode ("pop","acc");
10117 pic16_aopPut(AOP(result),"a",--offset);
10119 pic16_freeAsmop(result,NULL,ic,FALSE);
10124 /*-----------------------------------------------------------------*/
10125 /* genAssign - generate code for assignment */
10126 /*-----------------------------------------------------------------*/
10127 static void genAssign (iCode *ic)
10129 operand *result, *right;
10130 int size, offset,know_W;
10131 unsigned long lit = 0L;
10133 result = IC_RESULT(ic);
10134 right = IC_RIGHT(ic) ;
10136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10138 /* if they are the same */
10139 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10142 pic16_aopOp(right,ic,FALSE);
10143 pic16_aopOp(result,ic,TRUE);
10145 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10147 /* if they are the same registers */
10148 if (pic16_sameRegs(AOP(right),AOP(result)))
10151 /* if the result is a bit */
10152 if (AOP_TYPE(result) == AOP_CRY) {
10153 /* if the right size is a literal then
10154 we know what the value is */
10155 if (AOP_TYPE(right) == AOP_LIT) {
10157 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10158 pic16_popGet(AOP(result),0));
10160 if (((int) operandLitValue(right)))
10161 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10162 AOP(result)->aopu.aop_dir,
10163 AOP(result)->aopu.aop_dir);
10165 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10166 AOP(result)->aopu.aop_dir,
10167 AOP(result)->aopu.aop_dir);
10171 /* the right is also a bit variable */
10172 if (AOP_TYPE(right) == AOP_CRY) {
10173 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10174 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10175 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10177 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10178 AOP(result)->aopu.aop_dir,
10179 AOP(result)->aopu.aop_dir);
10180 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10181 AOP(right)->aopu.aop_dir,
10182 AOP(right)->aopu.aop_dir);
10183 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10184 AOP(result)->aopu.aop_dir,
10185 AOP(result)->aopu.aop_dir);
10189 /* we need to or */
10190 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10191 pic16_toBoolean(right);
10193 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10194 //pic16_aopPut(AOP(result),"a",0);
10198 /* bit variables done */
10200 size = AOP_SIZE(result);
10202 if(AOP_TYPE(right) == AOP_LIT)
10203 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10205 /* VR - What is this?! */
10206 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10207 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10208 if(aopIdx(AOP(result),0) == 4) {
10209 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10211 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10214 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10220 if(AOP_TYPE(right) == AOP_LIT) {
10222 if(know_W != (lit&0xff))
10223 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10225 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10227 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10231 } else if (AOP_TYPE(right) == AOP_CRY) {
10232 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10234 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10235 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10237 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10238 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10239 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10244 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10245 normally should work, but mind that the W register live range
10246 is not checked, so if the code generator assumes that the W
10247 is already loaded after such a pair, wrong code will be generated.
10249 Checking the live range is the next step.
10250 This is experimental code yet and has not been fully tested yet.
10251 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10252 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10254 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10256 /* This is the old code, which is assumed(?!) that works fine(!?) */
10258 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10268 pic16_freeAsmop (right,NULL,ic,FALSE);
10269 pic16_freeAsmop (result,NULL,ic,TRUE);
10272 /*-----------------------------------------------------------------*/
10273 /* genJumpTab - generates code for jump table */
10274 /*-----------------------------------------------------------------*/
10275 static void genJumpTab (iCode *ic)
10280 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10282 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10283 /* get the condition into accumulator */
10284 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10286 /* multiply by three */
10287 pic16_emitcode("add","a,acc");
10288 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10290 jtab = newiTempLabel(NULL);
10291 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10292 pic16_emitcode("jmp","@a+dptr");
10293 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10295 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10296 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10298 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10299 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10300 pic16_emitpLabel(jtab->key);
10302 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10304 /* now generate the jump labels */
10305 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10306 jtab = setNextItem(IC_JTLABELS(ic))) {
10307 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10308 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10314 /*-----------------------------------------------------------------*/
10315 /* genMixedOperation - gen code for operators between mixed types */
10316 /*-----------------------------------------------------------------*/
10318 TSD - Written for the PIC port - but this unfortunately is buggy.
10319 This routine is good in that it is able to efficiently promote
10320 types to different (larger) sizes. Unfortunately, the temporary
10321 variables that are optimized out by this routine are sometimes
10322 used in other places. So until I know how to really parse the
10323 iCode tree, I'm going to not be using this routine :(.
10325 static int genMixedOperation (iCode *ic)
10328 operand *result = IC_RESULT(ic);
10329 sym_link *ctype = operandType(IC_LEFT(ic));
10330 operand *right = IC_RIGHT(ic);
10336 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10338 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10344 nextright = IC_RIGHT(nextic);
10345 nextleft = IC_LEFT(nextic);
10346 nextresult = IC_RESULT(nextic);
10348 pic16_aopOp(right,ic,FALSE);
10349 pic16_aopOp(result,ic,FALSE);
10350 pic16_aopOp(nextright, nextic, FALSE);
10351 pic16_aopOp(nextleft, nextic, FALSE);
10352 pic16_aopOp(nextresult, nextic, FALSE);
10354 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10356 operand *t = right;
10360 pic16_emitcode(";remove right +","");
10362 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10364 operand *t = right;
10368 pic16_emitcode(";remove left +","");
10372 big = AOP_SIZE(nextleft);
10373 small = AOP_SIZE(nextright);
10375 switch(nextic->op) {
10378 pic16_emitcode(";optimize a +","");
10379 /* if unsigned or not an integral type */
10380 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10381 pic16_emitcode(";add a bit to something","");
10384 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10386 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10387 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10388 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10390 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10398 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10399 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10400 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10403 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10405 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10406 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10407 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10408 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10409 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10412 pic16_emitcode("rlf","known_zero,w");
10419 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10420 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10421 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10423 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10433 pic16_freeAsmop(right,NULL,ic,TRUE);
10434 pic16_freeAsmop(result,NULL,ic,TRUE);
10435 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10436 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10438 nextic->generated = 1;
10445 /*-----------------------------------------------------------------*/
10446 /* genCast - gen code for casting */
10447 /*-----------------------------------------------------------------*/
10448 static void genCast (iCode *ic)
10450 operand *result = IC_RESULT(ic);
10451 sym_link *ctype = operandType(IC_LEFT(ic));
10452 sym_link *rtype = operandType(IC_RIGHT(ic));
10453 operand *right = IC_RIGHT(ic);
10456 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10457 /* if they are equivalent then do nothing */
10458 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10461 pic16_aopOp(right,ic,FALSE) ;
10462 pic16_aopOp(result,ic,FALSE);
10464 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10466 /* if the result is a bit */
10467 if (AOP_TYPE(result) == AOP_CRY) {
10469 /* if the right size is a literal then
10470 * we know what the value is */
10471 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10473 if (AOP_TYPE(right) == AOP_LIT) {
10474 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10475 pic16_popGet(AOP(result),0));
10477 if (((int) operandLitValue(right)))
10478 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10479 AOP(result)->aopu.aop_dir,
10480 AOP(result)->aopu.aop_dir);
10482 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10483 AOP(result)->aopu.aop_dir,
10484 AOP(result)->aopu.aop_dir);
10488 /* the right is also a bit variable */
10489 if (AOP_TYPE(right) == AOP_CRY) {
10491 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10493 pic16_emitcode("clrc","");
10494 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10495 AOP(right)->aopu.aop_dir,
10496 AOP(right)->aopu.aop_dir);
10497 pic16_aopPut(AOP(result),"c",0);
10501 /* we need to or */
10502 if (AOP_TYPE(right) == AOP_REG) {
10503 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10504 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10505 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10507 pic16_toBoolean(right);
10508 pic16_aopPut(AOP(result),"a",0);
10512 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10515 size = AOP_SIZE(result);
10517 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10519 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
10520 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10521 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10524 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10529 /* if they are the same size : or less */
10530 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10532 /* if they are in the same place */
10533 if (pic16_sameRegs(AOP(right),AOP(result)))
10536 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10538 if (IS_PTR_CONST(rtype))
10540 if (IS_CODEPTR(rtype))
10542 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10545 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10547 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10549 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10552 if(AOP_TYPE(right) == AOP_IMMD) {
10553 pCodeOp *pcop0, *pcop1, *pcop2;
10554 symbol *sym = OP_SYMBOL( right );
10556 size = AOP_SIZE(result);
10558 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10560 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10562 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10565 pic16_emitpcode(POC_MOVLW, pcop0);
10566 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10567 pic16_emitpcode(POC_MOVLW, pcop1);
10568 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10569 pic16_emitpcode(POC_MOVLW, pcop2);
10570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10573 pic16_emitpcode(POC_MOVLW, pcop0);
10574 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10575 pic16_emitpcode(POC_MOVLW, pcop1);
10576 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10578 pic16_emitpcode(POC_MOVLW, pcop0);
10579 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10583 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10584 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10586 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10587 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10588 if(AOP_SIZE(result) <2)
10589 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10591 /* if they in different places then copy */
10592 size = AOP_SIZE(result);
10595 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10596 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10603 /* if the result is of type pointer */
10604 if (IS_PTR(ctype)) {
10606 sym_link *type = operandType(right);
10607 sym_link *etype = getSpec(type);
10609 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10611 /* pointer to generic pointer */
10612 if (IS_GENPTR(ctype)) {
10616 p_type = DCL_TYPE(type);
10618 /* we have to go by the storage class */
10619 p_type = PTR_TYPE(SPEC_OCLS(etype));
10621 /* if (SPEC_OCLS(etype)->codesp ) */
10622 /* p_type = CPOINTER ; */
10624 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10625 /* p_type = FPOINTER ; */
10627 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10628 /* p_type = PPOINTER; */
10630 /* if (SPEC_OCLS(etype) == idata ) */
10631 /* p_type = IPOINTER ; */
10633 /* p_type = POINTER ; */
10636 /* the first two bytes are known */
10637 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10638 size = GPTRSIZE - 1;
10641 if(offset < AOP_SIZE(right)) {
10642 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10643 if ((AOP_TYPE(right) == AOP_PCODE) &&
10644 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10645 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10646 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10648 pic16_aopPut(AOP(result),
10649 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10653 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10656 /* the last byte depending on type */
10660 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10663 pic16_emitcode(";BUG!? ","%d",__LINE__);
10667 pic16_emitcode(";BUG!? ","%d",__LINE__);
10671 pic16_emitcode(";BUG!? ","%d",__LINE__);
10676 /* this should never happen */
10677 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10678 "got unknown pointer type");
10681 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
10685 /* just copy the pointers */
10686 size = AOP_SIZE(result);
10689 pic16_aopPut(AOP(result),
10690 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10699 /* so we now know that the size of destination is greater
10700 than the size of the source.
10701 Now, if the next iCode is an operator then we might be
10702 able to optimize the operation without performing a cast.
10704 if(genMixedOperation(ic))
10707 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10709 /* we move to result for the size of source */
10710 size = AOP_SIZE(right);
10713 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10718 /* now depending on the sign of the destination */
10719 size = AOP_SIZE(result) - AOP_SIZE(right);
10720 /* if unsigned or not an integral type */
10721 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10723 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10725 /* we need to extend the sign :( */
10728 /* Save one instruction of casting char to int */
10729 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10730 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10731 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
10733 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10736 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10738 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10740 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
10748 pic16_freeAsmop(right,NULL,ic,TRUE);
10749 pic16_freeAsmop(result,NULL,ic,TRUE);
10753 /*-----------------------------------------------------------------*/
10754 /* genDjnz - generate decrement & jump if not zero instrucion */
10755 /*-----------------------------------------------------------------*/
10756 static int genDjnz (iCode *ic, iCode *ifx)
10758 symbol *lbl, *lbl1;
10759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10764 /* if the if condition has a false label
10765 then we cannot save */
10769 /* if the minus is not of the form
10771 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10772 !IS_OP_LITERAL(IC_RIGHT(ic)))
10775 if (operandLitValue(IC_RIGHT(ic)) != 1)
10778 /* if the size of this greater than one then no
10780 if (getSize(operandType(IC_RESULT(ic))) > 1)
10783 /* otherwise we can save BIG */
10784 lbl = newiTempLabel(NULL);
10785 lbl1= newiTempLabel(NULL);
10787 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10789 if (IS_AOP_PREG(IC_RESULT(ic))) {
10790 pic16_emitcode("dec","%s",
10791 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10792 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10793 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10797 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10798 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10800 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10801 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10804 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10805 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10806 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10807 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10810 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10811 ifx->generated = 1;
10815 /*-----------------------------------------------------------------*/
10816 /* genReceive - generate code for a receive iCode */
10817 /*-----------------------------------------------------------------*/
10818 static void genReceive (iCode *ic)
10820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10822 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10823 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10824 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10826 int size = getSize(operandType(IC_RESULT(ic)));
10827 int offset = pic16_fReturnSizePic - size;
10830 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10831 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10835 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10837 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10838 size = AOP_SIZE(IC_RESULT(ic));
10841 pic16_emitcode ("pop","acc");
10842 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10845 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
10848 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10850 assignResultValue(IC_RESULT(ic), 0);
10853 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10856 /*-----------------------------------------------------------------*/
10857 /* genDummyRead - generate code for dummy read of volatiles */
10858 /*-----------------------------------------------------------------*/
10860 genDummyRead (iCode * ic)
10862 pic16_emitcode ("; genDummyRead","");
10863 pic16_emitcode ("; not implemented","");
10868 /*-----------------------------------------------------------------*/
10869 /* genpic16Code - generate code for pic16 based controllers */
10870 /*-----------------------------------------------------------------*/
10872 * At this point, ralloc.c has gone through the iCode and attempted
10873 * to optimize in a way suitable for a PIC. Now we've got to generate
10874 * PIC instructions that correspond to the iCode.
10876 * Once the instructions are generated, we'll pass through both the
10877 * peep hole optimizer and the pCode optimizer.
10878 *-----------------------------------------------------------------*/
10880 void genpic16Code (iCode *lic)
10885 lineHead = lineCurr = NULL;
10887 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10888 pic16_addpBlock(pb);
10891 /* if debug information required */
10892 if (options.debug && currFunc) {
10894 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10896 if (IS_STATIC(currFunc->etype)) {
10897 pic16_emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
10898 //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10900 pic16_emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
10901 //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10908 for (ic = lic ; ic ; ic = ic->next ) {
10910 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10911 if ( cln != ic->lineno ) {
10912 if ( options.debug ) {
10914 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10915 FileBaseName(ic->filename),ic->lineno,
10916 ic->level,ic->block);
10920 if(!options.noCcodeInAsm) {
10921 pic16_addpCode2pBlock(pb,
10922 pic16_newpCodeCSource(ic->lineno, ic->filename,
10923 printCLine(ic->filename, ic->lineno)));
10929 if(options.iCodeInAsm) {
10930 /* insert here code to print iCode as comment */
10931 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10934 /* if the result is marked as
10935 spilt and rematerializable or code for
10936 this has already been generated then
10938 if (resultRemat(ic) || ic->generated )
10941 /* depending on the operation */
10960 /* IPOP happens only when trying to restore a
10961 spilt live range, if there is an ifx statement
10962 following this pop then the if statement might
10963 be using some of the registers being popped which
10964 would destroy the contents of the register so
10965 we need to check for this condition and handle it */
10967 ic->next->op == IFX &&
10968 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10969 genIfx (ic->next,ic);
10987 genEndFunction (ic);
11003 pic16_genPlus (ic) ;
11007 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11008 pic16_genMinus (ic);
11024 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11028 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11035 /* note these two are xlated by algebraic equivalence
11036 during parsing SDCC.y */
11037 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11038 "got '>=' or '<=' shouldn't have come here");
11042 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11054 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11058 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11062 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11086 genRightShift (ic);
11089 case GET_VALUE_AT_ADDRESS:
11094 if (POINTER_SET(ic))
11121 addSet(&_G.sendSet,ic);
11124 case DUMMY_READ_VOLATILE:
11134 /* now we are ready to call the
11135 peep hole optimizer */
11136 if (!options.nopeep) {
11137 peepHole (&lineHead);
11139 /* now do the actual printing */
11140 printLine (lineHead,codeOutFile);
11143 DFPRINTF((stderr,"printing pBlock\n\n"));
11144 pic16_printpBlock(stdout,pb);