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);
5152 symbol *lbl, *lbl_done;
5154 unsigned long lit = 0L;
5155 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5157 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5158 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5160 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5161 resolveIfx(&rIfx,ifx);
5162 lbl = newiTempLabel(NULL);
5163 lbl_done = newiTempLabel(NULL);
5166 /* if the left side is a literal or
5167 if the right is in a pointer register and left
5169 if ((AOP_TYPE(left) == AOP_LIT) ||
5170 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5175 if(AOP_TYPE(right) == AOP_LIT)
5176 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5178 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5179 preserve_result = 1;
5181 if(result && !preserve_result)
5184 for(i = 0; i < AOP_SIZE(result); i++)
5185 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5189 /* if the right side is a literal then anything goes */
5190 if (AOP_TYPE(right) == AOP_LIT &&
5191 AOP_TYPE(left) != AOP_DIR ) {
5194 genc16bit2lit(left, lit, 0);
5196 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5202 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5203 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5205 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5209 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5211 if(res_offset < res_size-1)
5219 /* if the right side is in a register or in direct space or
5220 if the left is a pointer register & right is not */
5221 else if (AOP_TYPE(right) == AOP_REG ||
5222 AOP_TYPE(right) == AOP_DIR ||
5223 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5224 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5225 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5226 int lbl_key = lbl->key;
5229 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5230 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5232 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5233 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5234 __FUNCTION__,__LINE__);
5238 /* switch(size) { */
5240 /* genc16bit2lit(left, lit, 0); */
5242 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5247 if((AOP_TYPE(left) == AOP_DIR) &&
5248 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5250 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5251 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5253 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5255 switch (lit & 0xff) {
5257 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5260 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5261 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5262 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5266 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5267 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5268 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5269 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5273 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5274 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5279 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5282 if(AOP_TYPE(result) == AOP_CRY) {
5283 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5288 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5290 /* fix me. probably need to check result size too */
5291 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5296 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5297 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5304 if(res_offset < res_size-1)
5309 } else if(AOP_TYPE(right) == AOP_REG &&
5310 AOP_TYPE(left) != AOP_DIR){
5313 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5314 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5315 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5320 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5322 if(res_offset < res_size-1)
5327 /* right is a pointer reg need both a & b */
5329 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5331 pic16_emitcode("mov","b,%s",l);
5332 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5333 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5338 if(result && preserve_result)
5341 for(i = 0; i < AOP_SIZE(result); i++)
5342 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5345 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5347 if(result && preserve_result)
5348 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5351 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5353 pic16_emitpLabel(lbl->key);
5355 if(result && preserve_result)
5358 for(i = 0; i < AOP_SIZE(result); i++)
5359 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5361 pic16_emitpLabel(lbl_done->key);
5364 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5371 /*-----------------------------------------------------------------*/
5372 /* gencjne - compare and jump if not equal */
5373 /*-----------------------------------------------------------------*/
5374 static void gencjne(operand *left, operand *right, iCode *ifx)
5376 symbol *tlbl = newiTempLabel(NULL);
5378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5379 gencjneshort(left, right, lbl);
5381 pic16_emitcode("mov","a,%s",one);
5382 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5383 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5384 pic16_emitcode("clr","a");
5385 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5387 pic16_emitpLabel(lbl->key);
5388 pic16_emitpLabel(tlbl->key);
5393 /*-----------------------------------------------------------------*/
5394 /* genCmpEq - generates code for equal to */
5395 /*-----------------------------------------------------------------*/
5396 static void genCmpEq (iCode *ic, iCode *ifx)
5398 operand *left, *right, *result;
5399 unsigned long lit = 0L;
5401 symbol *falselbl = newiTempLabel(NULL);
5404 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5407 DEBUGpic16_emitcode ("; ifx is non-null","");
5409 DEBUGpic16_emitcode ("; ifx is null","");
5411 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5412 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5413 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5415 size = max(AOP_SIZE(left),AOP_SIZE(right));
5417 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5419 /* if literal, literal on the right or
5420 if the right is in a pointer register and left
5422 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5423 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5424 operand *tmp = right ;
5430 if(ifx && !AOP_SIZE(result)){
5432 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5433 /* if they are both bit variables */
5434 if (AOP_TYPE(left) == AOP_CRY &&
5435 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5436 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5437 if(AOP_TYPE(right) == AOP_LIT){
5438 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5440 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5441 pic16_emitcode("cpl","c");
5442 } else if(lit == 1L) {
5443 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5445 pic16_emitcode("clr","c");
5447 /* AOP_TYPE(right) == AOP_CRY */
5449 symbol *lbl = newiTempLabel(NULL);
5450 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5451 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5452 pic16_emitcode("cpl","c");
5453 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5455 /* if true label then we jump if condition
5457 tlbl = newiTempLabel(NULL);
5458 if ( IC_TRUE(ifx) ) {
5459 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5460 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5462 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5463 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5465 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5468 /* left and right are both bit variables, result is carry */
5471 resolveIfx(&rIfx,ifx);
5473 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5474 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5475 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5476 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5481 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5483 /* They're not both bit variables. Is the right a literal? */
5484 if(AOP_TYPE(right) == AOP_LIT) {
5485 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5490 switch(lit & 0xff) {
5492 if ( IC_TRUE(ifx) ) {
5493 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5495 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5497 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5498 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5502 if ( IC_TRUE(ifx) ) {
5503 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5505 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5507 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5508 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5512 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5514 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5519 /* end of size == 1 */
5523 genc16bit2lit(left,lit,offset);
5526 /* end of size == 2 */
5531 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5532 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5533 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5534 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5537 /* search for patterns that can be optimized */
5539 genc16bit2lit(left,lit,0);
5543 emitSKPZ; // if hi word unequal
5545 emitSKPNZ; // if hi word equal
5547 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5548 genc16bit2lit(left,lit,2);
5551 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5552 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5556 pic16_emitpLabel(falselbl->key);
5565 } else if(AOP_TYPE(right) == AOP_CRY ) {
5566 /* we know the left is not a bit, but that the right is */
5567 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5568 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5569 pic16_popGet(AOP(right),offset));
5570 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5572 /* if the two are equal, then W will be 0 and the Z bit is set
5573 * we could test Z now, or go ahead and check the high order bytes if
5574 * the variable we're comparing is larger than a byte. */
5577 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5579 if ( IC_TRUE(ifx) ) {
5581 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5582 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5585 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5586 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5590 /* They're both variables that are larger than bits */
5593 tlbl = newiTempLabel(NULL);
5596 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5597 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5599 if ( IC_TRUE(ifx) ) {
5603 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5605 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5606 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5610 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5613 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5614 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5619 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5621 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5622 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5626 if(s>1 && IC_TRUE(ifx)) {
5627 pic16_emitpLabel(tlbl->key);
5628 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5632 /* mark the icode as generated */
5637 /* if they are both bit variables */
5638 if (AOP_TYPE(left) == AOP_CRY &&
5639 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5640 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5641 if(AOP_TYPE(right) == AOP_LIT){
5642 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5644 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5645 pic16_emitcode("cpl","c");
5646 } else if(lit == 1L) {
5647 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5649 pic16_emitcode("clr","c");
5651 /* AOP_TYPE(right) == AOP_CRY */
5653 symbol *lbl = newiTempLabel(NULL);
5654 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5655 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5656 pic16_emitcode("cpl","c");
5657 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5660 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5661 pic16_outBitC(result);
5665 genIfxJump (ifx,"c");
5668 /* if the result is used in an arithmetic operation
5669 then put the result in place */
5670 pic16_outBitC(result);
5673 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5674 gencjne(left,right,result,ifx);
5677 gencjne(left,right,newiTempLabel(NULL));
5679 if(IC_TRUE(ifx)->key)
5680 gencjne(left,right,IC_TRUE(ifx)->key);
5682 gencjne(left,right,IC_FALSE(ifx)->key);
5686 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5687 pic16_aopPut(AOP(result),"a",0);
5692 genIfxJump (ifx,"a");
5696 /* if the result is used in an arithmetic operation
5697 then put the result in place */
5699 if (AOP_TYPE(result) != AOP_CRY)
5700 pic16_outAcc(result);
5702 /* leave the result in acc */
5706 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5707 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5708 pic16_freeAsmop(result,NULL,ic,TRUE);
5711 /*-----------------------------------------------------------------*/
5712 /* ifxForOp - returns the icode containing the ifx for operand */
5713 /*-----------------------------------------------------------------*/
5714 static iCode *ifxForOp ( operand *op, iCode *ic )
5716 /* if true symbol then needs to be assigned */
5717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5718 if (IS_TRUE_SYMOP(op))
5721 /* if this has register type condition and
5722 the next instruction is ifx with the same operand
5723 and live to of the operand is upto the ifx only then */
5725 ic->next->op == IFX &&
5726 IC_COND(ic->next)->key == op->key &&
5727 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5731 ic->next->op == IFX &&
5732 IC_COND(ic->next)->key == op->key) {
5733 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5737 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5739 ic->next->op == IFX)
5740 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5743 ic->next->op == IFX &&
5744 IC_COND(ic->next)->key == op->key) {
5745 DEBUGpic16_emitcode ("; "," key is okay");
5746 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5747 OP_SYMBOL(op)->liveTo,
5754 /*-----------------------------------------------------------------*/
5755 /* genAndOp - for && operation */
5756 /*-----------------------------------------------------------------*/
5757 static void genAndOp (iCode *ic)
5759 operand *left,*right, *result;
5762 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5763 /* note here that && operations that are in an
5764 if statement are taken away by backPatchLabels
5765 only those used in arthmetic operations remain */
5766 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5767 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5768 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5770 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5772 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5773 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5774 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5776 /* if both are bit variables */
5777 /* if (AOP_TYPE(left) == AOP_CRY && */
5778 /* AOP_TYPE(right) == AOP_CRY ) { */
5779 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5780 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5781 /* pic16_outBitC(result); */
5783 /* tlbl = newiTempLabel(NULL); */
5784 /* pic16_toBoolean(left); */
5785 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5786 /* pic16_toBoolean(right); */
5787 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5788 /* pic16_outBitAcc(result); */
5791 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5792 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5793 pic16_freeAsmop(result,NULL,ic,TRUE);
5797 /*-----------------------------------------------------------------*/
5798 /* genOrOp - for || operation */
5799 /*-----------------------------------------------------------------*/
5802 modified this code, but it doesn't appear to ever get called
5805 static void genOrOp (iCode *ic)
5807 operand *left,*right, *result;
5810 /* note here that || operations that are in an
5811 if statement are taken away by backPatchLabels
5812 only those used in arthmetic operations remain */
5813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5814 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5815 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5816 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5818 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5820 /* if both are bit variables */
5821 if (AOP_TYPE(left) == AOP_CRY &&
5822 AOP_TYPE(right) == AOP_CRY ) {
5823 pic16_emitcode("clrc","");
5824 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5825 AOP(left)->aopu.aop_dir,
5826 AOP(left)->aopu.aop_dir);
5827 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5828 AOP(right)->aopu.aop_dir,
5829 AOP(right)->aopu.aop_dir);
5830 pic16_emitcode("setc","");
5833 tlbl = newiTempLabel(NULL);
5834 pic16_toBoolean(left);
5836 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5837 pic16_toBoolean(right);
5838 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5840 pic16_outBitAcc(result);
5843 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5844 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5845 pic16_freeAsmop(result,NULL,ic,TRUE);
5848 /*-----------------------------------------------------------------*/
5849 /* isLiteralBit - test if lit == 2^n */
5850 /*-----------------------------------------------------------------*/
5851 static int isLiteralBit(unsigned long lit)
5853 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5854 0x100L,0x200L,0x400L,0x800L,
5855 0x1000L,0x2000L,0x4000L,0x8000L,
5856 0x10000L,0x20000L,0x40000L,0x80000L,
5857 0x100000L,0x200000L,0x400000L,0x800000L,
5858 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5859 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5862 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5863 for(idx = 0; idx < 32; idx++)
5869 /*-----------------------------------------------------------------*/
5870 /* continueIfTrue - */
5871 /*-----------------------------------------------------------------*/
5872 static void continueIfTrue (iCode *ic)
5874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5876 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5880 /*-----------------------------------------------------------------*/
5882 /*-----------------------------------------------------------------*/
5883 static void jumpIfTrue (iCode *ic)
5885 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5887 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5891 /*-----------------------------------------------------------------*/
5892 /* jmpTrueOrFalse - */
5893 /*-----------------------------------------------------------------*/
5894 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5896 // ugly but optimized by peephole
5897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5899 symbol *nlbl = newiTempLabel(NULL);
5900 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5901 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5902 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5903 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5906 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5907 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5912 /*-----------------------------------------------------------------*/
5913 /* genAnd - code for and */
5914 /*-----------------------------------------------------------------*/
5915 static void genAnd (iCode *ic, iCode *ifx)
5917 operand *left, *right, *result;
5919 unsigned long lit = 0L;
5924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5925 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5926 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5927 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5929 resolveIfx(&rIfx,ifx);
5931 /* if left is a literal & right is not then exchange them */
5932 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5933 AOP_NEEDSACC(left)) {
5934 operand *tmp = right ;
5939 /* if result = right then exchange them */
5940 if(pic16_sameRegs(AOP(result),AOP(right))){
5941 operand *tmp = right ;
5946 /* if right is bit then exchange them */
5947 if (AOP_TYPE(right) == AOP_CRY &&
5948 AOP_TYPE(left) != AOP_CRY){
5949 operand *tmp = right ;
5953 if(AOP_TYPE(right) == AOP_LIT)
5954 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5956 size = AOP_SIZE(result);
5958 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5961 // result = bit & yy;
5962 if (AOP_TYPE(left) == AOP_CRY){
5963 // c = bit & literal;
5964 if(AOP_TYPE(right) == AOP_LIT){
5966 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5969 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5972 if(size && (AOP_TYPE(result) == AOP_CRY)){
5973 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5976 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5980 pic16_emitcode("clr","c");
5983 if (AOP_TYPE(right) == AOP_CRY){
5985 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5986 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5989 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5991 pic16_emitcode("rrc","a");
5992 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5998 pic16_outBitC(result);
6000 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6001 genIfxJump(ifx, "c");
6005 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6006 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6007 if((AOP_TYPE(right) == AOP_LIT) &&
6008 (AOP_TYPE(result) == AOP_CRY) &&
6009 (AOP_TYPE(left) != AOP_CRY)){
6010 int posbit = isLiteralBit(lit);
6014 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6017 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6023 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6024 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6026 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6027 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6030 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6031 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6032 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6039 symbol *tlbl = newiTempLabel(NULL);
6040 int sizel = AOP_SIZE(left);
6042 pic16_emitcode("setb","c");
6044 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6045 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6047 if((posbit = isLiteralBit(bytelit)) != 0)
6048 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6050 if(bytelit != 0x0FFL)
6051 pic16_emitcode("anl","a,%s",
6052 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6053 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6058 // bit = left & literal
6060 pic16_emitcode("clr","c");
6061 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6063 // if(left & literal)
6066 jmpTrueOrFalse(ifx, tlbl);
6070 pic16_outBitC(result);
6074 /* if left is same as result */
6075 if(pic16_sameRegs(AOP(result),AOP(left))){
6077 for(;size--; offset++,lit>>=8) {
6078 if(AOP_TYPE(right) == AOP_LIT){
6079 switch(lit & 0xff) {
6081 /* and'ing with 0 has clears the result */
6082 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6083 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6086 /* and'ing with 0xff is a nop when the result and left are the same */
6091 int p = my_powof2( (~lit) & 0xff );
6093 /* only one bit is set in the literal, so use a bcf instruction */
6094 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6095 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6098 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6099 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6100 if(know_W != (lit&0xff))
6101 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6103 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6108 if (AOP_TYPE(left) == AOP_ACC) {
6109 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6111 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6112 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6119 // left & result in different registers
6120 if(AOP_TYPE(result) == AOP_CRY){
6122 // if(size), result in bit
6123 // if(!size && ifx), conditional oper: if(left & right)
6124 symbol *tlbl = newiTempLabel(NULL);
6125 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6127 pic16_emitcode("setb","c");
6129 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6130 pic16_emitcode("anl","a,%s",
6131 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6132 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6137 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6138 pic16_outBitC(result);
6140 jmpTrueOrFalse(ifx, tlbl);
6142 for(;(size--);offset++) {
6144 // result = left & right
6145 if(AOP_TYPE(right) == AOP_LIT){
6146 int t = (lit >> (offset*8)) & 0x0FFL;
6149 pic16_emitcode("clrf","%s",
6150 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6151 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6154 pic16_emitcode("movf","%s,w",
6155 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6156 pic16_emitcode("movwf","%s",
6157 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6158 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6159 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6162 pic16_emitcode("movlw","0x%x",t);
6163 pic16_emitcode("andwf","%s,w",
6164 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6165 pic16_emitcode("movwf","%s",
6166 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6168 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6169 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6170 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6175 if (AOP_TYPE(left) == AOP_ACC) {
6176 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6177 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6179 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6180 pic16_emitcode("andwf","%s,w",
6181 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6182 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6183 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6185 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6192 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6193 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6194 pic16_freeAsmop(result,NULL,ic,TRUE);
6197 /*-----------------------------------------------------------------*/
6198 /* genOr - code for or */
6199 /*-----------------------------------------------------------------*/
6200 static void genOr (iCode *ic, iCode *ifx)
6202 operand *left, *right, *result;
6204 unsigned long lit = 0L;
6206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6208 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6209 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6210 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6212 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6214 /* if left is a literal & right is not then exchange them */
6215 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6216 AOP_NEEDSACC(left)) {
6217 operand *tmp = right ;
6222 /* if result = right then exchange them */
6223 if(pic16_sameRegs(AOP(result),AOP(right))){
6224 operand *tmp = right ;
6229 /* if right is bit then exchange them */
6230 if (AOP_TYPE(right) == AOP_CRY &&
6231 AOP_TYPE(left) != AOP_CRY){
6232 operand *tmp = right ;
6237 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6239 if(AOP_TYPE(right) == AOP_LIT)
6240 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6242 size = AOP_SIZE(result);
6246 if (AOP_TYPE(left) == AOP_CRY){
6247 if(AOP_TYPE(right) == AOP_LIT){
6248 // c = bit & literal;
6250 // lit != 0 => result = 1
6251 if(AOP_TYPE(result) == AOP_CRY){
6253 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6254 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6255 // AOP(result)->aopu.aop_dir,
6256 // AOP(result)->aopu.aop_dir);
6258 continueIfTrue(ifx);
6262 // lit == 0 => result = left
6263 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6265 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6268 if (AOP_TYPE(right) == AOP_CRY){
6269 if(pic16_sameRegs(AOP(result),AOP(left))){
6271 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6272 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6273 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6275 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6276 AOP(result)->aopu.aop_dir,
6277 AOP(result)->aopu.aop_dir);
6278 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6279 AOP(right)->aopu.aop_dir,
6280 AOP(right)->aopu.aop_dir);
6281 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6282 AOP(result)->aopu.aop_dir,
6283 AOP(result)->aopu.aop_dir);
6285 if( AOP_TYPE(result) == AOP_ACC) {
6286 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6287 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6288 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6289 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6293 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6294 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6295 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6296 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6298 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6299 AOP(result)->aopu.aop_dir,
6300 AOP(result)->aopu.aop_dir);
6301 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6302 AOP(right)->aopu.aop_dir,
6303 AOP(right)->aopu.aop_dir);
6304 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6305 AOP(left)->aopu.aop_dir,
6306 AOP(left)->aopu.aop_dir);
6307 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6308 AOP(result)->aopu.aop_dir,
6309 AOP(result)->aopu.aop_dir);
6314 symbol *tlbl = newiTempLabel(NULL);
6315 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6318 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6319 if( AOP_TYPE(right) == AOP_ACC) {
6320 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6322 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6323 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6328 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6329 pic16_emitcode(";XXX setb","c");
6330 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6331 AOP(left)->aopu.aop_dir,tlbl->key+100);
6332 pic16_toBoolean(right);
6333 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6334 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6335 jmpTrueOrFalse(ifx, tlbl);
6339 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6346 pic16_outBitC(result);
6348 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6349 genIfxJump(ifx, "c");
6353 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6354 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6355 if((AOP_TYPE(right) == AOP_LIT) &&
6356 (AOP_TYPE(result) == AOP_CRY) &&
6357 (AOP_TYPE(left) != AOP_CRY)){
6359 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6362 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6364 continueIfTrue(ifx);
6367 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6368 // lit = 0, result = boolean(left)
6370 pic16_emitcode(";XXX setb","c");
6371 pic16_toBoolean(right);
6373 symbol *tlbl = newiTempLabel(NULL);
6374 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6376 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6378 genIfxJump (ifx,"a");
6382 pic16_outBitC(result);
6386 /* if left is same as result */
6387 if(pic16_sameRegs(AOP(result),AOP(left))){
6389 for(;size--; offset++,lit>>=8) {
6390 if(AOP_TYPE(right) == AOP_LIT){
6391 if((lit & 0xff) == 0)
6392 /* or'ing with 0 has no effect */
6395 int p = my_powof2(lit & 0xff);
6397 /* only one bit is set in the literal, so use a bsf instruction */
6398 pic16_emitpcode(POC_BSF,
6399 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6401 if(know_W != (lit & 0xff))
6402 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6403 know_W = lit & 0xff;
6404 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6409 if (AOP_TYPE(left) == AOP_ACC) {
6410 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6411 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6413 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6414 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6416 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6417 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6423 // left & result in different registers
6424 if(AOP_TYPE(result) == AOP_CRY){
6426 // if(size), result in bit
6427 // if(!size && ifx), conditional oper: if(left | right)
6428 symbol *tlbl = newiTempLabel(NULL);
6429 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6430 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6434 pic16_emitcode(";XXX setb","c");
6436 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6437 pic16_emitcode(";XXX orl","a,%s",
6438 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6439 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6444 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6445 pic16_outBitC(result);
6447 jmpTrueOrFalse(ifx, tlbl);
6448 } else for(;(size--);offset++){
6450 // result = left & right
6451 if(AOP_TYPE(right) == AOP_LIT){
6452 int t = (lit >> (offset*8)) & 0x0FFL;
6455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6456 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6458 pic16_emitcode("movf","%s,w",
6459 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6460 pic16_emitcode("movwf","%s",
6461 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6464 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6465 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6466 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6468 pic16_emitcode("movlw","0x%x",t);
6469 pic16_emitcode("iorwf","%s,w",
6470 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6471 pic16_emitcode("movwf","%s",
6472 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6478 // faster than result <- left, anl result,right
6479 // and better if result is SFR
6480 if (AOP_TYPE(left) == AOP_ACC) {
6481 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6482 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6484 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6485 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6487 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6488 pic16_emitcode("iorwf","%s,w",
6489 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6491 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6492 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6497 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6498 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6499 pic16_freeAsmop(result,NULL,ic,TRUE);
6502 /*-----------------------------------------------------------------*/
6503 /* genXor - code for xclusive or */
6504 /*-----------------------------------------------------------------*/
6505 static void genXor (iCode *ic, iCode *ifx)
6507 operand *left, *right, *result;
6509 unsigned long lit = 0L;
6511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6513 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6514 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6515 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6517 /* if left is a literal & right is not ||
6518 if left needs acc & right does not */
6519 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6520 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6521 operand *tmp = right ;
6526 /* if result = right then exchange them */
6527 if(pic16_sameRegs(AOP(result),AOP(right))){
6528 operand *tmp = right ;
6533 /* if right is bit then exchange them */
6534 if (AOP_TYPE(right) == AOP_CRY &&
6535 AOP_TYPE(left) != AOP_CRY){
6536 operand *tmp = right ;
6540 if(AOP_TYPE(right) == AOP_LIT)
6541 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6543 size = AOP_SIZE(result);
6547 if (AOP_TYPE(left) == AOP_CRY){
6548 if(AOP_TYPE(right) == AOP_LIT){
6549 // c = bit & literal;
6551 // lit>>1 != 0 => result = 1
6552 if(AOP_TYPE(result) == AOP_CRY){
6554 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6555 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6557 continueIfTrue(ifx);
6560 pic16_emitcode("setb","c");
6564 // lit == 0, result = left
6565 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6567 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6569 // lit == 1, result = not(left)
6570 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6571 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6572 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6573 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6576 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6577 pic16_emitcode("cpl","c");
6584 symbol *tlbl = newiTempLabel(NULL);
6585 if (AOP_TYPE(right) == AOP_CRY){
6587 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6590 int sizer = AOP_SIZE(right);
6592 // if val>>1 != 0, result = 1
6593 pic16_emitcode("setb","c");
6595 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6597 // test the msb of the lsb
6598 pic16_emitcode("anl","a,#0xfe");
6599 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6603 pic16_emitcode("rrc","a");
6605 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6606 pic16_emitcode("cpl","c");
6607 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6612 pic16_outBitC(result);
6614 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6615 genIfxJump(ifx, "c");
6619 if(pic16_sameRegs(AOP(result),AOP(left))){
6620 /* if left is same as result */
6621 for(;size--; offset++) {
6622 if(AOP_TYPE(right) == AOP_LIT){
6623 int t = (lit >> (offset*8)) & 0x0FFL;
6627 if (IS_AOP_PREG(left)) {
6628 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6629 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6630 pic16_aopPut(AOP(result),"a",offset);
6632 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6633 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6634 pic16_emitcode("xrl","%s,%s",
6635 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6636 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6639 if (AOP_TYPE(left) == AOP_ACC)
6640 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6642 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6643 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6645 if (IS_AOP_PREG(left)) {
6646 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6647 pic16_aopPut(AOP(result),"a",offset);
6649 pic16_emitcode("xrl","%s,a",
6650 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6656 // left & result in different registers
6657 if(AOP_TYPE(result) == AOP_CRY){
6659 // if(size), result in bit
6660 // if(!size && ifx), conditional oper: if(left ^ right)
6661 symbol *tlbl = newiTempLabel(NULL);
6662 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6664 pic16_emitcode("setb","c");
6666 if((AOP_TYPE(right) == AOP_LIT) &&
6667 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6668 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6670 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6671 pic16_emitcode("xrl","a,%s",
6672 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6674 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6679 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6680 pic16_outBitC(result);
6682 jmpTrueOrFalse(ifx, tlbl);
6683 } else for(;(size--);offset++){
6685 // result = left & right
6686 if(AOP_TYPE(right) == AOP_LIT){
6687 int t = (lit >> (offset*8)) & 0x0FFL;
6690 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6691 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6692 pic16_emitcode("movf","%s,w",
6693 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6694 pic16_emitcode("movwf","%s",
6695 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6698 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6699 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6700 pic16_emitcode("comf","%s,w",
6701 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6702 pic16_emitcode("movwf","%s",
6703 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6707 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6708 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6709 pic16_emitcode("movlw","0x%x",t);
6710 pic16_emitcode("xorwf","%s,w",
6711 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6712 pic16_emitcode("movwf","%s",
6713 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6719 // faster than result <- left, anl result,right
6720 // and better if result is SFR
6721 if (AOP_TYPE(left) == AOP_ACC) {
6722 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6723 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6725 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6726 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6727 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6728 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6730 if ( AOP_TYPE(result) != AOP_ACC){
6731 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6732 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6738 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6739 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6740 pic16_freeAsmop(result,NULL,ic,TRUE);
6743 /*-----------------------------------------------------------------*/
6744 /* genInline - write the inline code out */
6745 /*-----------------------------------------------------------------*/
6746 static void genInline (iCode *ic)
6748 char *buffer, *bp, *bp1;
6750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6752 _G.inLine += (!options.asmpeep);
6754 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6755 strcpy(buffer,IC_INLINE(ic));
6757 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6759 /* emit each line as a code */
6765 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6773 /* print label, use this special format with NULL directive
6774 * to denote that the argument should not be indented with tab */
6775 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6782 if ((bp1 != bp) && *bp1)
6783 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6788 _G.inLine -= (!options.asmpeep);
6791 /*-----------------------------------------------------------------*/
6792 /* genRRC - rotate right with carry */
6793 /*-----------------------------------------------------------------*/
6794 static void genRRC (iCode *ic)
6796 operand *left , *result ;
6797 int size, offset = 0, same;
6799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6801 /* rotate right with carry */
6803 result=IC_RESULT(ic);
6804 pic16_aopOp (left,ic,FALSE);
6805 pic16_aopOp (result,ic,FALSE);
6807 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6809 same = pic16_sameRegs(AOP(result),AOP(left));
6811 size = AOP_SIZE(result);
6813 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6815 /* get the lsb and put it into the carry */
6816 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6823 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6825 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6826 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6832 pic16_freeAsmop(left,NULL,ic,TRUE);
6833 pic16_freeAsmop(result,NULL,ic,TRUE);
6836 /*-----------------------------------------------------------------*/
6837 /* genRLC - generate code for rotate left with carry */
6838 /*-----------------------------------------------------------------*/
6839 static void genRLC (iCode *ic)
6841 operand *left , *result ;
6842 int size, offset = 0;
6845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6846 /* rotate right with carry */
6848 result=IC_RESULT(ic);
6849 pic16_aopOp (left,ic,FALSE);
6850 pic16_aopOp (result,ic,FALSE);
6852 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6854 same = pic16_sameRegs(AOP(result),AOP(left));
6856 /* move it to the result */
6857 size = AOP_SIZE(result);
6859 /* get the msb and put it into the carry */
6860 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6869 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6870 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6877 pic16_freeAsmop(left,NULL,ic,TRUE);
6878 pic16_freeAsmop(result,NULL,ic,TRUE);
6882 /* gpasm can get the highest order bit with HIGH/UPPER
6883 * so the following probably is not needed -- VR */
6885 /*-----------------------------------------------------------------*/
6886 /* genGetHbit - generates code get highest order bit */
6887 /*-----------------------------------------------------------------*/
6888 static void genGetHbit (iCode *ic)
6890 operand *left, *result;
6892 result=IC_RESULT(ic);
6893 pic16_aopOp (left,ic,FALSE);
6894 pic16_aopOp (result,ic,FALSE);
6896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6897 /* get the highest order byte into a */
6898 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6899 if(AOP_TYPE(result) == AOP_CRY){
6900 pic16_emitcode("rlc","a");
6901 pic16_outBitC(result);
6904 pic16_emitcode("rl","a");
6905 pic16_emitcode("anl","a,#0x01");
6906 pic16_outAcc(result);
6910 pic16_freeAsmop(left,NULL,ic,TRUE);
6911 pic16_freeAsmop(result,NULL,ic,TRUE);
6915 /*-----------------------------------------------------------------*/
6916 /* AccRol - rotate left accumulator by known count */
6917 /*-----------------------------------------------------------------*/
6918 static void AccRol (int shCount)
6920 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6921 shCount &= 0x0007; // shCount : 0..7
6926 pic16_emitcode("rl","a");
6929 pic16_emitcode("rl","a");
6930 pic16_emitcode("rl","a");
6933 pic16_emitcode("swap","a");
6934 pic16_emitcode("rr","a");
6937 pic16_emitcode("swap","a");
6940 pic16_emitcode("swap","a");
6941 pic16_emitcode("rl","a");
6944 pic16_emitcode("rr","a");
6945 pic16_emitcode("rr","a");
6948 pic16_emitcode("rr","a");
6954 /*-----------------------------------------------------------------*/
6955 /* AccLsh - left shift accumulator by known count */
6956 /*-----------------------------------------------------------------*/
6957 static void AccLsh (int shCount)
6959 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6965 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6968 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6969 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6972 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6973 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6976 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6979 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6980 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6983 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6984 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6987 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6991 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6994 /*-----------------------------------------------------------------*/
6995 /* AccRsh - right shift accumulator by known count */
6996 /*-----------------------------------------------------------------*/
6997 static void AccRsh (int shCount, int andmask)
6999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7004 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7005 // andmask = 0; /* no need */
7008 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7009 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7010 // andmask = 0; /* no need */
7013 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7014 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7017 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7020 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7021 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7024 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7025 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7028 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7033 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7035 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7039 /*-----------------------------------------------------------------*/
7040 /* AccSRsh - signed right shift accumulator by known count */
7041 /*-----------------------------------------------------------------*/
7042 static void AccSRsh (int shCount)
7045 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7048 pic16_emitcode("mov","c,acc.7");
7049 pic16_emitcode("rrc","a");
7050 } else if(shCount == 2){
7051 pic16_emitcode("mov","c,acc.7");
7052 pic16_emitcode("rrc","a");
7053 pic16_emitcode("mov","c,acc.7");
7054 pic16_emitcode("rrc","a");
7056 tlbl = newiTempLabel(NULL);
7057 /* rotate right accumulator */
7058 AccRol(8 - shCount);
7059 /* and kill the higher order bits */
7060 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7061 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7062 pic16_emitcode("orl","a,#0x%02x",
7063 (unsigned char)~SRMask[shCount]);
7064 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7069 /*-----------------------------------------------------------------*/
7070 /* shiftR1Left2Result - shift right one byte from left to result */
7071 /*-----------------------------------------------------------------*/
7072 static void shiftR1Left2ResultSigned (operand *left, int offl,
7073 operand *result, int offr,
7078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7080 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7084 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7086 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7088 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7089 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7095 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7097 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7099 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7100 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7102 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7103 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7109 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7111 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7112 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7115 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7116 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7117 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7119 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7120 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7122 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7126 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7127 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7128 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7129 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7130 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7134 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7136 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7137 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7139 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7140 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7141 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7142 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7143 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7148 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7149 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7150 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7151 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7152 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7153 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7155 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7156 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7157 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7158 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7159 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7165 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7166 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7167 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7168 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7170 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7171 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7172 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7180 /*-----------------------------------------------------------------*/
7181 /* shiftR1Left2Result - shift right one byte from left to result */
7182 /*-----------------------------------------------------------------*/
7183 static void shiftR1Left2Result (operand *left, int offl,
7184 operand *result, int offr,
7185 int shCount, int sign)
7189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7191 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7193 /* Copy the msb into the carry if signed. */
7195 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7205 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7207 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7208 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7214 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7216 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7217 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7220 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7225 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7227 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7228 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7231 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7232 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7233 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7234 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7238 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7239 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7240 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7244 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7245 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7246 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7248 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7253 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7254 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7256 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7257 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7262 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7263 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7264 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7273 /*-----------------------------------------------------------------*/
7274 /* shiftL1Left2Result - shift left one byte from left to result */
7275 /*-----------------------------------------------------------------*/
7276 static void shiftL1Left2Result (operand *left, int offl,
7277 operand *result, int offr, int shCount)
7282 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7284 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7285 DEBUGpic16_emitcode ("; ***","same = %d",same);
7286 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7288 /* shift left accumulator */
7289 //AccLsh(shCount); // don't comment out just yet...
7290 // pic16_aopPut(AOP(result),"a",offr);
7294 /* Shift left 1 bit position */
7295 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7297 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7299 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7300 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7304 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7305 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7306 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7307 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7310 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7311 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7312 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7313 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7314 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7317 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7318 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7319 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7322 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7323 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7324 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7325 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7328 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7329 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7330 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7331 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7332 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7335 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7336 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7337 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7341 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7346 /*-----------------------------------------------------------------*/
7347 /* movLeft2Result - move byte from left to result */
7348 /*-----------------------------------------------------------------*/
7349 static void movLeft2Result (operand *left, int offl,
7350 operand *result, int offr)
7353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7354 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7355 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7357 if (*l == '@' && (IS_AOP_PREG(result))) {
7358 pic16_emitcode("mov","a,%s",l);
7359 pic16_aopPut(AOP(result),"a",offr);
7361 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7362 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7367 /*-----------------------------------------------------------------*/
7368 /* shiftL2Left2Result - shift left two bytes from left to result */
7369 /*-----------------------------------------------------------------*/
7370 static void shiftL2Left2Result (operand *left, int offl,
7371 operand *result, int offr, int shCount)
7373 int same = pic16_sameRegs(AOP(result), AOP(left));
7376 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7378 if (same && (offl != offr)) { // shift bytes
7381 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7382 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7384 } else { // just treat as different later on
7397 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7398 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7399 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7403 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7404 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7410 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7411 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7412 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7413 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7414 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7415 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7416 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7418 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7419 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7423 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7424 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7425 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7426 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7427 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7428 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7429 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7430 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7431 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7432 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7435 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7436 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7437 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7438 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7439 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7449 /* note, use a mov/add for the shift since the mov has a
7450 chance of getting optimized out */
7451 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7452 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7453 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7454 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7455 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7459 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7460 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7466 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7467 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7468 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7469 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7470 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7471 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7472 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7473 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7477 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7478 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7482 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7483 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7484 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7485 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7487 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7488 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7489 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7490 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7491 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7492 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7493 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7494 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7497 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7498 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7499 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7500 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7501 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7506 /*-----------------------------------------------------------------*/
7507 /* shiftR2Left2Result - shift right two bytes from left to result */
7508 /*-----------------------------------------------------------------*/
7509 static void shiftR2Left2Result (operand *left, int offl,
7510 operand *result, int offr,
7511 int shCount, int sign)
7513 int same = pic16_sameRegs(AOP(result), AOP(left));
7515 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7517 if (same && (offl != offr)) { // shift right bytes
7520 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7521 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7523 } else { // just treat as different later on
7535 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7540 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7541 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7543 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7544 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7545 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7546 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7551 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7554 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7555 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7562 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7563 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7564 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7566 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7567 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7568 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7569 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7571 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7572 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7573 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7575 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7576 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7577 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7578 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7579 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7583 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7584 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7588 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7589 pic16_emitpcode(POC_BTFSC,
7590 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7591 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7599 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7600 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7602 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7603 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7604 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7605 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7607 pic16_emitpcode(POC_BTFSC,
7608 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7609 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7611 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7612 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7613 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7614 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7616 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7617 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7618 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7619 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7620 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7621 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7622 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7623 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7625 pic16_emitpcode(POC_BTFSC,
7626 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7627 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7629 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7630 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7637 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7638 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7639 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7640 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7643 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7645 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7650 /*-----------------------------------------------------------------*/
7651 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7652 /*-----------------------------------------------------------------*/
7653 static void shiftLLeftOrResult (operand *left, int offl,
7654 operand *result, int offr, int shCount)
7656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7658 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7659 /* shift left accumulator */
7661 /* or with result */
7662 /* back to result */
7663 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7666 /*-----------------------------------------------------------------*/
7667 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7668 /*-----------------------------------------------------------------*/
7669 static void shiftRLeftOrResult (operand *left, int offl,
7670 operand *result, int offr, int shCount)
7672 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7675 /* shift right accumulator */
7677 /* or with result */
7678 /* back to result */
7679 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7682 /*-----------------------------------------------------------------*/
7683 /* genlshOne - left shift a one byte quantity by known count */
7684 /*-----------------------------------------------------------------*/
7685 static void genlshOne (operand *result, operand *left, int shCount)
7687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7688 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7691 /*-----------------------------------------------------------------*/
7692 /* genlshTwo - left shift two bytes by known amount != 0 */
7693 /*-----------------------------------------------------------------*/
7694 static void genlshTwo (operand *result,operand *left, int shCount)
7698 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7699 size = pic16_getDataSize(result);
7701 /* if shCount >= 8 */
7707 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7709 movLeft2Result(left, LSB, result, MSB16);
7711 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7714 /* 1 <= shCount <= 7 */
7717 shiftL1Left2Result(left, LSB, result, LSB, shCount);
7719 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7723 /*-----------------------------------------------------------------*/
7724 /* shiftLLong - shift left one long from left to result */
7725 /* offr = LSB or MSB16 */
7726 /*-----------------------------------------------------------------*/
7727 static void shiftLLong (operand *left, operand *result, int offr )
7729 int size = AOP_SIZE(result);
7730 int same = pic16_sameRegs(AOP(left),AOP(result));
7733 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7735 if (same && (offr == MSB16)) { //shift one byte
7736 for(i=size-1;i>=MSB16;i--) {
7737 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7738 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7741 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7744 if (size >= LSB+offr ){
7746 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7748 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7749 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7753 if(size >= MSB16+offr){
7755 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7757 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7758 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7762 if(size >= MSB24+offr){
7764 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7766 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7767 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7771 if(size > MSB32+offr){
7773 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7775 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7776 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7780 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7784 /*-----------------------------------------------------------------*/
7785 /* genlshFour - shift four byte by a known amount != 0 */
7786 /*-----------------------------------------------------------------*/
7787 static void genlshFour (operand *result, operand *left, int shCount)
7791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7792 size = AOP_SIZE(result);
7794 /* if shifting more that 3 bytes */
7795 if (shCount >= 24 ) {
7798 /* lowest order of left goes to the highest
7799 order of the destination */
7800 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7802 movLeft2Result(left, LSB, result, MSB32);
7804 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7805 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7806 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7811 /* more than two bytes */
7812 else if ( shCount >= 16 ) {
7813 /* lower order two bytes goes to higher order two bytes */
7815 /* if some more remaining */
7817 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7819 movLeft2Result(left, MSB16, result, MSB32);
7820 movLeft2Result(left, LSB, result, MSB24);
7822 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7823 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7827 /* if more than 1 byte */
7828 else if ( shCount >= 8 ) {
7829 /* lower order three bytes goes to higher order three bytes */
7833 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7835 movLeft2Result(left, LSB, result, MSB16);
7837 else{ /* size = 4 */
7839 movLeft2Result(left, MSB24, result, MSB32);
7840 movLeft2Result(left, MSB16, result, MSB24);
7841 movLeft2Result(left, LSB, result, MSB16);
7842 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7844 else if(shCount == 1)
7845 shiftLLong(left, result, MSB16);
7847 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7848 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7849 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7850 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7855 /* 1 <= shCount <= 7 */
7856 else if(shCount <= 3)
7858 shiftLLong(left, result, LSB);
7859 while(--shCount >= 1)
7860 shiftLLong(result, result, LSB);
7862 /* 3 <= shCount <= 7, optimize */
7864 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7865 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7866 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7870 /*-----------------------------------------------------------------*/
7871 /* genLeftShiftLiteral - left shifting by known count */
7872 /*-----------------------------------------------------------------*/
7873 static void genLeftShiftLiteral (operand *left,
7878 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7881 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7882 pic16_freeAsmop(right,NULL,ic,TRUE);
7884 pic16_aopOp(left,ic,FALSE);
7885 pic16_aopOp(result,ic,FALSE);
7887 size = getSize(operandType(result));
7890 pic16_emitcode("; shift left ","result %d, left %d",size,
7894 /* I suppose that the left size >= result size */
7897 movLeft2Result(left, size, result, size);
7901 else if(shCount >= (size * 8))
7903 pic16_aopPut(AOP(result),zero,size);
7907 genlshOne (result,left,shCount);
7912 genlshTwo (result,left,shCount);
7916 genlshFour (result,left,shCount);
7920 pic16_freeAsmop(left,NULL,ic,TRUE);
7921 pic16_freeAsmop(result,NULL,ic,TRUE);
7924 /*-----------------------------------------------------------------*
7925 * genMultiAsm - repeat assembly instruction for size of register.
7926 * if endian == 1, then the high byte (i.e base address + size of
7927 * register) is used first else the low byte is used first;
7928 *-----------------------------------------------------------------*/
7929 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7947 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
7952 /*-----------------------------------------------------------------*/
7953 /* genLeftShift - generates code for left shifting */
7954 /*-----------------------------------------------------------------*/
7955 static void genLeftShift (iCode *ic)
7957 operand *left,*right, *result;
7960 symbol *tlbl , *tlbl1;
7963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7965 right = IC_RIGHT(ic);
7967 result = IC_RESULT(ic);
7969 pic16_aopOp(right,ic,FALSE);
7971 /* if the shift count is known then do it
7972 as efficiently as possible */
7973 if (AOP_TYPE(right) == AOP_LIT) {
7974 genLeftShiftLiteral (left,right,result,ic);
7978 /* shift count is unknown then we have to form
7979 a loop get the loop count in B : Note: we take
7980 only the lower order byte since shifting
7981 more that 32 bits make no sense anyway, ( the
7982 largest size of an object can be only 32 bits ) */
7985 pic16_aopOp(left,ic,FALSE);
7986 pic16_aopOp(result,ic,FALSE);
7988 /* now move the left to the result if they are not the
7990 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
7991 AOP_SIZE(result) > 1) {
7993 size = AOP_SIZE(result);
7996 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7997 if (*l == '@' && (IS_AOP_PREG(result))) {
7999 pic16_emitcode("mov","a,%s",l);
8000 pic16_aopPut(AOP(result),"a",offset);
8002 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8004 //pic16_aopPut(AOP(result),l,offset);
8010 size = AOP_SIZE(result);
8012 /* if it is only one byte then */
8014 if(optimized_for_speed) {
8015 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8016 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8017 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8018 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8020 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8021 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8022 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8023 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8024 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8025 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8026 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8029 tlbl = newiTempLabel(NULL);
8030 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8031 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8032 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8035 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8036 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8037 pic16_emitpLabel(tlbl->key);
8038 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8039 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8041 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8046 if (pic16_sameRegs(AOP(left),AOP(result))) {
8048 tlbl = newiTempLabel(NULL);
8049 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8050 genMultiAsm(POC_RRCF, result, size,1);
8051 pic16_emitpLabel(tlbl->key);
8052 genMultiAsm(POC_RLCF, result, size,0);
8053 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8055 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8059 //tlbl = newiTempLabel(NULL);
8061 //tlbl1 = newiTempLabel(NULL);
8063 //reAdjustPreg(AOP(result));
8065 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8066 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8067 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8069 //pic16_emitcode("add","a,acc");
8070 //pic16_aopPut(AOP(result),"a",offset++);
8072 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8074 // pic16_emitcode("rlc","a");
8075 // pic16_aopPut(AOP(result),"a",offset++);
8077 //reAdjustPreg(AOP(result));
8079 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8080 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8083 tlbl = newiTempLabel(NULL);
8084 tlbl1= newiTempLabel(NULL);
8086 size = AOP_SIZE(result);
8089 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8091 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8093 /* offset should be 0, 1 or 3 */
8095 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8097 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8099 pic16_emitpcode(POC_MOVWF, pctemp);
8102 pic16_emitpLabel(tlbl->key);
8105 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8107 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8109 pic16_emitpcode(POC_DECFSZ, pctemp);
8110 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8111 pic16_emitpLabel(tlbl1->key);
8113 pic16_popReleaseTempReg(pctemp);
8117 pic16_freeAsmop (right,NULL,ic,TRUE);
8118 pic16_freeAsmop(left,NULL,ic,TRUE);
8119 pic16_freeAsmop(result,NULL,ic,TRUE);
8122 /*-----------------------------------------------------------------*/
8123 /* genrshOne - right shift a one byte quantity by known count */
8124 /*-----------------------------------------------------------------*/
8125 static void genrshOne (operand *result, operand *left,
8126 int shCount, int sign)
8128 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8129 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8132 /*-----------------------------------------------------------------*/
8133 /* genrshTwo - right shift two bytes by known amount != 0 */
8134 /*-----------------------------------------------------------------*/
8135 static void genrshTwo (operand *result,operand *left,
8136 int shCount, int sign)
8138 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8139 /* if shCount >= 8 */
8143 shiftR1Left2Result(left, MSB16, result, LSB,
8146 movLeft2Result(left, MSB16, result, LSB);
8148 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8151 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8152 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8156 /* 1 <= shCount <= 7 */
8158 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8161 /*-----------------------------------------------------------------*/
8162 /* shiftRLong - shift right one long from left to result */
8163 /* offl = LSB or MSB16 */
8164 /*-----------------------------------------------------------------*/
8165 static void shiftRLong (operand *left, int offl,
8166 operand *result, int sign)
8168 int size = AOP_SIZE(result);
8169 int same = pic16_sameRegs(AOP(left),AOP(result));
8171 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8173 if (same && (offl == MSB16)) { //shift one byte right
8174 for(i=MSB16;i<size;i++) {
8175 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8181 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8187 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8189 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8190 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8194 /* add sign of "a" */
8195 pic16_addSign(result, MSB32, sign);
8199 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8201 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8202 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8206 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8208 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8209 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8213 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8216 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8217 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8222 /*-----------------------------------------------------------------*/
8223 /* genrshFour - shift four byte by a known amount != 0 */
8224 /*-----------------------------------------------------------------*/
8225 static void genrshFour (operand *result, operand *left,
8226 int shCount, int sign)
8228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8229 /* if shifting more that 3 bytes */
8230 if(shCount >= 24 ) {
8233 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8235 movLeft2Result(left, MSB32, result, LSB);
8237 pic16_addSign(result, MSB16, sign);
8239 else if(shCount >= 16){
8242 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8244 movLeft2Result(left, MSB24, result, LSB);
8245 movLeft2Result(left, MSB32, result, MSB16);
8247 pic16_addSign(result, MSB24, sign);
8249 else if(shCount >= 8){
8252 shiftRLong(left, MSB16, result, sign);
8253 else if(shCount == 0){
8254 movLeft2Result(left, MSB16, result, LSB);
8255 movLeft2Result(left, MSB24, result, MSB16);
8256 movLeft2Result(left, MSB32, result, MSB24);
8257 pic16_addSign(result, MSB32, sign);
8259 else{ //shcount >= 2
8260 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8261 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8262 /* the last shift is signed */
8263 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8264 pic16_addSign(result, MSB32, sign);
8267 else{ /* 1 <= shCount <= 7 */
8269 shiftRLong(left, LSB, result, sign);
8271 shiftRLong(result, LSB, result, sign);
8274 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8275 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8276 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8281 /*-----------------------------------------------------------------*/
8282 /* genRightShiftLiteral - right shifting by known count */
8283 /*-----------------------------------------------------------------*/
8284 static void genRightShiftLiteral (operand *left,
8290 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8293 pic16_freeAsmop(right,NULL,ic,TRUE);
8295 pic16_aopOp(left,ic,FALSE);
8296 pic16_aopOp(result,ic,FALSE);
8298 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8301 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8305 lsize = pic16_getDataSize(left);
8306 res_size = pic16_getDataSize(result);
8307 /* test the LEFT size !!! */
8309 /* I suppose that the left size >= result size */
8312 movLeft2Result(left, lsize, result, res_size);
8315 else if(shCount >= (lsize * 8)){
8318 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8320 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8321 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8326 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8327 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8328 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8335 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8342 genrshOne (result,left,shCount,sign);
8346 genrshTwo (result,left,shCount,sign);
8350 genrshFour (result,left,shCount,sign);
8358 pic16_freeAsmop(left,NULL,ic,TRUE);
8359 pic16_freeAsmop(result,NULL,ic,TRUE);
8362 /*-----------------------------------------------------------------*/
8363 /* genSignedRightShift - right shift of signed number */
8364 /*-----------------------------------------------------------------*/
8365 static void genSignedRightShift (iCode *ic)
8367 operand *right, *left, *result;
8370 symbol *tlbl, *tlbl1 ;
8373 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8375 /* we do it the hard way put the shift count in b
8376 and loop thru preserving the sign */
8377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8379 right = IC_RIGHT(ic);
8381 result = IC_RESULT(ic);
8383 pic16_aopOp(right,ic,FALSE);
8384 pic16_aopOp(left,ic,FALSE);
8385 pic16_aopOp(result,ic,FALSE);
8388 if ( AOP_TYPE(right) == AOP_LIT) {
8389 genRightShiftLiteral (left,right,result,ic,1);
8392 /* shift count is unknown then we have to form
8393 a loop get the loop count in B : Note: we take
8394 only the lower order byte since shifting
8395 more that 32 bits make no sense anyway, ( the
8396 largest size of an object can be only 32 bits ) */
8398 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8399 //pic16_emitcode("inc","b");
8400 //pic16_freeAsmop (right,NULL,ic,TRUE);
8401 //pic16_aopOp(left,ic,FALSE);
8402 //pic16_aopOp(result,ic,FALSE);
8404 /* now move the left to the result if they are not the
8406 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8407 AOP_SIZE(result) > 1) {
8409 size = AOP_SIZE(result);
8413 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8414 if (*l == '@' && IS_AOP_PREG(result)) {
8416 pic16_emitcode("mov","a,%s",l);
8417 pic16_aopPut(AOP(result),"a",offset);
8419 pic16_aopPut(AOP(result),l,offset);
8421 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8422 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8428 /* mov the highest order bit to OVR */
8429 tlbl = newiTempLabel(NULL);
8430 tlbl1= newiTempLabel(NULL);
8432 size = AOP_SIZE(result);
8435 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8439 /* offset should be 0, 1 or 3 */
8440 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8442 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8444 pic16_emitpcode(POC_MOVWF, pctemp);
8447 pic16_emitpLabel(tlbl->key);
8449 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8450 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8453 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8456 pic16_emitpcode(POC_DECFSZ, pctemp);
8457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8458 pic16_emitpLabel(tlbl1->key);
8460 pic16_popReleaseTempReg(pctemp);
8462 size = AOP_SIZE(result);
8464 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8465 pic16_emitcode("rlc","a");
8466 pic16_emitcode("mov","ov,c");
8467 /* if it is only one byte then */
8469 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8471 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8472 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8473 pic16_emitcode("mov","c,ov");
8474 pic16_emitcode("rrc","a");
8475 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8476 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8477 pic16_aopPut(AOP(result),"a",0);
8481 reAdjustPreg(AOP(result));
8482 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8483 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8484 pic16_emitcode("mov","c,ov");
8486 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8488 pic16_emitcode("rrc","a");
8489 pic16_aopPut(AOP(result),"a",offset--);
8491 reAdjustPreg(AOP(result));
8492 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8493 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8498 pic16_freeAsmop(left,NULL,ic,TRUE);
8499 pic16_freeAsmop(result,NULL,ic,TRUE);
8500 pic16_freeAsmop(right,NULL,ic,TRUE);
8503 /*-----------------------------------------------------------------*/
8504 /* genRightShift - generate code for right shifting */
8505 /*-----------------------------------------------------------------*/
8506 static void genRightShift (iCode *ic)
8508 operand *right, *left, *result;
8512 symbol *tlbl, *tlbl1 ;
8514 /* if signed then we do it the hard way preserve the
8515 sign bit moving it inwards */
8516 letype = getSpec(operandType(IC_LEFT(ic)));
8517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8519 if (!SPEC_USIGN(letype)) {
8520 genSignedRightShift (ic);
8524 /* signed & unsigned types are treated the same : i.e. the
8525 signed is NOT propagated inwards : quoting from the
8526 ANSI - standard : "for E1 >> E2, is equivalent to division
8527 by 2**E2 if unsigned or if it has a non-negative value,
8528 otherwise the result is implementation defined ", MY definition
8529 is that the sign does not get propagated */
8531 right = IC_RIGHT(ic);
8533 result = IC_RESULT(ic);
8535 pic16_aopOp(right,ic,FALSE);
8537 /* if the shift count is known then do it
8538 as efficiently as possible */
8539 if (AOP_TYPE(right) == AOP_LIT) {
8540 genRightShiftLiteral (left,right,result,ic, 0);
8544 /* shift count is unknown then we have to form
8545 a loop get the loop count in B : Note: we take
8546 only the lower order byte since shifting
8547 more that 32 bits make no sense anyway, ( the
8548 largest size of an object can be only 32 bits ) */
8550 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8551 pic16_emitcode("inc","b");
8552 pic16_aopOp(left,ic,FALSE);
8553 pic16_aopOp(result,ic,FALSE);
8555 /* now move the left to the result if they are not the
8557 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8558 AOP_SIZE(result) > 1) {
8560 size = AOP_SIZE(result);
8563 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8564 if (*l == '@' && IS_AOP_PREG(result)) {
8566 pic16_emitcode("mov","a,%s",l);
8567 pic16_aopPut(AOP(result),"a",offset);
8569 pic16_aopPut(AOP(result),l,offset);
8574 tlbl = newiTempLabel(NULL);
8575 tlbl1= newiTempLabel(NULL);
8576 size = AOP_SIZE(result);
8579 /* if it is only one byte then */
8582 tlbl = newiTempLabel(NULL);
8583 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8588 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8589 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8590 pic16_emitpLabel(tlbl->key);
8591 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8592 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8599 reAdjustPreg(AOP(result));
8600 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8601 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8604 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8606 pic16_emitcode("rrc","a");
8607 pic16_aopPut(AOP(result),"a",offset--);
8609 reAdjustPreg(AOP(result));
8611 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8612 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8615 pic16_freeAsmop(left,NULL,ic,TRUE);
8616 pic16_freeAsmop (right,NULL,ic,TRUE);
8617 pic16_freeAsmop(result,NULL,ic,TRUE);
8620 /*-----------------------------------------------------------------*/
8621 /* genUnpackBits - generates code for unpacking bits */
8622 /*-----------------------------------------------------------------*/
8623 static void genUnpackBits (operand *result, char *rname, int ptype)
8630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8631 etype = getSpec(operandType(result));
8633 /* read the first byte */
8640 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8643 pic16_emitcode("clr","a");
8644 pic16_emitcode("movc","a","@a+dptr");
8649 /* if we have bitdisplacement then it fits */
8650 /* into this byte completely or if length is */
8651 /* less than a byte */
8652 if ((shCnt = SPEC_BSTR(etype)) ||
8653 (SPEC_BLEN(etype) <= 8)) {
8655 /* shift right acc */
8658 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8659 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8661 /* VR -- normally I would use the following, but since we use the hack,
8662 * to avoid the masking from AccRsh, why not mask it right now? */
8665 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8674 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8675 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8678 /* bit field did not fit in a byte */
8679 rlen = SPEC_BLEN(etype) - 8;
8680 pic16_aopPut(AOP(result),"a",offset++);
8687 pic16_emitcode("inc","%s",rname);
8688 pic16_emitcode("mov","a,@%s",rname);
8692 pic16_emitcode("inc","%s",rname);
8693 pic16_emitcode("movx","a,@%s",rname);
8697 pic16_emitcode("inc","dptr");
8698 pic16_emitcode("movx","a,@dptr");
8702 pic16_emitcode("clr","a");
8703 pic16_emitcode("inc","dptr");
8704 pic16_emitcode("movc","a","@a+dptr");
8708 pic16_emitcode("inc","dptr");
8709 pic16_emitcode("lcall","__gptrget");
8714 /* if we are done */
8718 pic16_aopPut(AOP(result),"a",offset++);
8723 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8724 pic16_aopPut(AOP(result),"a",offset);
8731 static void genDataPointerGet(operand *left,
8735 int size, offset = 0, leoffset=0 ;
8737 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8738 pic16_aopOp(result, ic, FALSE);
8740 size = AOP_SIZE(result);
8741 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8745 /* The following tests may save a redudant movff instruction when
8746 * accessing unions */
8748 /* if they are the same */
8749 if (operandsEqu (left, result)) {
8750 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8754 /* if they are the same registers */
8755 if (pic16_sameRegs(AOP(left),AOP(result))) {
8756 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8762 if ( AOP_TYPE(left) == AOP_PCODE) {
8763 fprintf(stderr,"genDataPointerGet %s, %d\n",
8764 AOP(left)->aopu.pcop->name,
8765 (AOP(left)->aopu.pcop->type == PO_DIR)?
8766 PCOR(AOP(left)->aopu.pcop)->instance:
8767 PCOI(AOP(left)->aopu.pcop)->offset);
8771 if(AOP(left)->aopu.pcop->type == PO_DIR)
8772 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8774 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8777 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8779 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8780 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8781 mov2w(AOP(left), offset); // patch 8
8782 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8784 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8785 pic16_popGet(AOP(left), offset), //patch 8
8786 pic16_popGet(AOP(result), offset)));
8794 pic16_freeAsmop(result,NULL,ic,TRUE);
8797 void pic16_loadFSR0(operand *op)
8799 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8803 /*-----------------------------------------------------------------*/
8804 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
8805 /*-----------------------------------------------------------------*/
8806 static void genNearPointerGet (operand *left,
8811 //regs *preg = NULL ;
8812 sym_link *rtype, *retype;
8813 sym_link *ltype = operandType(left);
8815 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8816 rtype = operandType(result);
8817 retype= getSpec(rtype);
8819 pic16_aopOp(left,ic,FALSE);
8821 pic16_DumpOp("(left)",left);
8822 pic16_DumpOp("(result)",result);
8824 /* if left is rematerialisable and
8825 * result is not bit variable type and
8826 * the left is pointer to data space i.e
8827 * lower 128 bytes of space */
8828 if (AOP_TYPE(left) == AOP_PCODE
8829 && !IS_BITFIELD(retype)
8830 && DCL_TYPE(ltype) == POINTER) {
8832 genDataPointerGet (left,result,ic);
8833 pic16_freeAsmop(left, NULL, ic, TRUE);
8837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8839 /* if the value is already in a pointer register
8840 * then don't need anything more */
8841 if (!AOP_INPREG(AOP(left))) {
8842 /* otherwise get a free pointer register */
8843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8845 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8846 if( (AOP_TYPE(left) == AOP_PCODE)
8847 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8848 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
8850 pic16_loadFSR0( left ); // patch 10
8852 // set up FSR0 with address from left
8853 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
8854 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
8858 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8860 pic16_aopOp (result,ic,FALSE);
8862 /* if bitfield then unpack the bits */
8863 if (IS_BITFIELD(retype))
8864 genUnpackBits (result, NULL, POINTER);
8866 /* we have can just get the values */
8867 int size = AOP_SIZE(result);
8870 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8873 /* fsr0 is loaded already -- VR */
8874 // pic16_loadFSR0( left );
8876 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8877 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8881 pic16_emitpcode(POC_MOVFF,
8882 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8883 pic16_popGet(AOP(result), offset++)));
8885 pic16_emitpcode(POC_MOVFF,
8886 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8887 pic16_popGet(AOP(result), offset++)));
8891 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8892 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8894 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8898 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8900 pic16_emitcode("mov","a,@%s",rname);
8901 pic16_aopPut(AOP(result),"a",offset);
8903 sprintf(buffer,"@%s",rname);
8904 pic16_aopPut(AOP(result),buffer,offset);
8908 pic16_emitcode("inc","%s",rname);
8913 /* now some housekeeping stuff */
8915 /* we had to allocate for this iCode */
8916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8917 pic16_freeAsmop(NULL,aop,ic,TRUE);
8919 /* we did not allocate which means left
8920 already in a pointer register, then
8921 if size > 0 && this could be used again
8922 we have to point it back to where it
8924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8925 if (AOP_SIZE(result) > 1 &&
8926 !OP_SYMBOL(left)->remat &&
8927 ( OP_SYMBOL(left)->liveTo > ic->seq ||
8929 // int size = AOP_SIZE(result) - 1;
8931 // pic16_emitcode("dec","%s",rname);
8936 pic16_freeAsmop(left,NULL,ic,TRUE);
8937 pic16_freeAsmop(result,NULL,ic,TRUE);
8941 /*-----------------------------------------------------------------*/
8942 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
8943 /*-----------------------------------------------------------------*/
8944 static void genPagedPointerGet (operand *left,
8951 sym_link *rtype, *retype;
8953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8955 rtype = operandType(result);
8956 retype= getSpec(rtype);
8958 pic16_aopOp(left,ic,FALSE);
8960 /* if the value is already in a pointer register
8961 then don't need anything more */
8962 if (!AOP_INPREG(AOP(left))) {
8963 /* otherwise get a free pointer register */
8965 preg = getFreePtr(ic,&aop,FALSE);
8966 pic16_emitcode("mov","%s,%s",
8968 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8969 rname = preg->name ;
8971 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8973 pic16_freeAsmop(left,NULL,ic,TRUE);
8974 pic16_aopOp (result,ic,FALSE);
8976 /* if bitfield then unpack the bits */
8977 if (IS_BITFIELD(retype))
8978 genUnpackBits (result,rname,PPOINTER);
8980 /* we have can just get the values */
8981 int size = AOP_SIZE(result);
8986 pic16_emitcode("movx","a,@%s",rname);
8987 pic16_aopPut(AOP(result),"a",offset);
8992 pic16_emitcode("inc","%s",rname);
8996 /* now some housekeeping stuff */
8998 /* we had to allocate for this iCode */
8999 pic16_freeAsmop(NULL,aop,ic,TRUE);
9001 /* we did not allocate which means left
9002 already in a pointer register, then
9003 if size > 0 && this could be used again
9004 we have to point it back to where it
9006 if (AOP_SIZE(result) > 1 &&
9007 !OP_SYMBOL(left)->remat &&
9008 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9010 int size = AOP_SIZE(result) - 1;
9012 pic16_emitcode("dec","%s",rname);
9017 pic16_freeAsmop(result,NULL,ic,TRUE);
9022 /*-----------------------------------------------------------------*/
9023 /* genFarPointerGet - gget value from far space */
9024 /*-----------------------------------------------------------------*/
9025 static void genFarPointerGet (operand *left,
9026 operand *result, iCode *ic)
9029 sym_link *retype = getSpec(operandType(result));
9031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9033 pic16_aopOp(left,ic,FALSE);
9035 /* if the operand is already in dptr
9036 then we do nothing else we move the value to dptr */
9037 if (AOP_TYPE(left) != AOP_STR) {
9038 /* if this is remateriazable */
9039 if (AOP_TYPE(left) == AOP_IMMD)
9040 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9041 else { /* we need to get it byte by byte */
9042 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9043 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9044 if (options.model == MODEL_FLAT24)
9046 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9050 /* so dptr know contains the address */
9051 pic16_freeAsmop(left,NULL,ic,TRUE);
9052 pic16_aopOp(result,ic,FALSE);
9054 /* if bit then unpack */
9055 if (IS_BITFIELD(retype))
9056 genUnpackBits(result,"dptr",FPOINTER);
9058 size = AOP_SIZE(result);
9062 pic16_emitcode("movx","a,@dptr");
9063 pic16_aopPut(AOP(result),"a",offset++);
9065 pic16_emitcode("inc","dptr");
9069 pic16_freeAsmop(result,NULL,ic,TRUE);
9072 /*-----------------------------------------------------------------*/
9073 /* genCodePointerGet - get value from code space */
9074 /*-----------------------------------------------------------------*/
9075 static void genCodePointerGet (operand *left,
9076 operand *result, iCode *ic)
9079 sym_link *retype = getSpec(operandType(result));
9081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9083 pic16_aopOp(left,ic,FALSE);
9085 /* if the operand is already in dptr
9086 then we do nothing else we move the value to dptr */
9087 if (AOP_TYPE(left) != AOP_STR) {
9088 /* if this is remateriazable */
9089 if (AOP_TYPE(left) == AOP_IMMD)
9090 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9091 else { /* we need to get it byte by byte */
9092 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9093 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9094 if (options.model == MODEL_FLAT24)
9096 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9100 /* so dptr know contains the address */
9101 pic16_freeAsmop(left,NULL,ic,TRUE);
9102 pic16_aopOp(result,ic,FALSE);
9104 /* if bit then unpack */
9105 if (IS_BITFIELD(retype))
9106 genUnpackBits(result,"dptr",CPOINTER);
9108 size = AOP_SIZE(result);
9112 pic16_emitcode("clr","a");
9113 pic16_emitcode("movc","a,@a+dptr");
9114 pic16_aopPut(AOP(result),"a",offset++);
9116 pic16_emitcode("inc","dptr");
9120 pic16_freeAsmop(result,NULL,ic,TRUE);
9123 /*-----------------------------------------------------------------*/
9124 /* genGenPointerGet - gget value from generic pointer space */
9125 /*-----------------------------------------------------------------*/
9126 static void genGenPointerGet (operand *left,
9127 operand *result, iCode *ic)
9129 int size, offset, lit;
9130 sym_link *retype = getSpec(operandType(result));
9132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9133 pic16_aopOp(left,ic,FALSE);
9134 pic16_aopOp(result,ic,FALSE);
9135 size = AOP_SIZE(result);
9137 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9139 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9141 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9142 // load FSR0 from immediate
9143 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9145 // pic16_loadFSR0( left );
9150 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9152 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9159 else { /* we need to get it byte by byte */
9160 // set up FSR0 with address from left
9161 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9162 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9168 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9170 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9177 /* if bit then unpack */
9178 if (IS_BITFIELD(retype))
9179 genUnpackBits(result,"BAD",GPOINTER);
9182 pic16_freeAsmop(left,NULL,ic,TRUE);
9183 pic16_freeAsmop(result,NULL,ic,TRUE);
9187 /*-----------------------------------------------------------------*/
9188 /* genConstPointerGet - get value from const generic pointer space */
9189 /*-----------------------------------------------------------------*/
9190 static void genConstPointerGet (operand *left,
9191 operand *result, iCode *ic)
9193 //sym_link *retype = getSpec(operandType(result));
9194 // symbol *albl = newiTempLabel(NULL); // patch 15
9195 // symbol *blbl = newiTempLabel(NULL); //
9196 // PIC_OPCODE poc; // patch 15
9200 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9201 pic16_aopOp(left,ic,FALSE);
9202 pic16_aopOp(result,ic,TRUE);
9203 size = AOP_SIZE(result);
9205 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9207 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9209 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9210 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9211 pic16_emitpLabel(albl->key);
9213 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9215 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9216 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9217 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9218 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9219 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9221 pic16_emitpLabel(blbl->key);
9223 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9227 // set up table pointer
9228 if( (AOP_TYPE(left) == AOP_PCODE)
9229 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9230 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9232 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9233 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9234 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9235 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9236 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9237 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9241 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9242 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9243 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9249 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9250 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9254 pic16_freeAsmop(left,NULL,ic,TRUE);
9255 pic16_freeAsmop(result,NULL,ic,TRUE);
9258 /*-----------------------------------------------------------------*/
9259 /* genPointerGet - generate code for pointer get */
9260 /*-----------------------------------------------------------------*/
9261 static void genPointerGet (iCode *ic)
9263 operand *left, *result ;
9264 sym_link *type, *etype;
9267 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9270 result = IC_RESULT(ic) ;
9272 /* depending on the type of pointer we need to
9273 move it to the correct pointer register */
9274 type = operandType(left);
9275 etype = getSpec(type);
9278 if (IS_PTR_CONST(type))
9280 if (IS_CODEPTR(type))
9282 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9284 /* if left is of type of pointer then it is simple */
9285 if (IS_PTR(type) && !IS_FUNC(type->next))
9286 p_type = DCL_TYPE(type);
9288 /* we have to go by the storage class */
9289 p_type = PTR_TYPE(SPEC_OCLS(etype));
9291 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9293 if (SPEC_OCLS(etype)->codesp ) {
9294 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9295 //p_type = CPOINTER ;
9298 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9299 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9300 /*p_type = FPOINTER ;*/
9302 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9303 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9304 /* p_type = PPOINTER; */
9306 if (SPEC_OCLS(etype) == idata )
9307 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9308 /* p_type = IPOINTER; */
9310 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9311 /* p_type = POINTER ; */
9314 /* now that we have the pointer type we assign
9315 the pointer values */
9320 genNearPointerGet (left,result,ic);
9324 genPagedPointerGet(left,result,ic);
9328 genFarPointerGet (left,result,ic);
9332 genConstPointerGet (left,result,ic);
9333 //pic16_emitcodePointerGet (left,result,ic);
9338 if (IS_PTR_CONST(type))
9339 genConstPointerGet (left,result,ic);
9342 genGenPointerGet (left,result,ic);
9348 /*-----------------------------------------------------------------*/
9349 /* genPackBits - generates code for packed bit storage */
9350 /*-----------------------------------------------------------------*/
9351 static void genPackBits (sym_link *etype ,
9353 char *rname, int p_type)
9361 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9362 blen = SPEC_BLEN(etype);
9363 bstr = SPEC_BSTR(etype);
9365 if(AOP_TYPE(right) == AOP_LIT) {
9366 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9369 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9371 /* l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9374 /* if the bit lenth is less than or */
9375 /* it exactly fits a byte then */
9376 if((shCnt=SPEC_BSTR(etype))
9377 || SPEC_BLEN(etype) <= 8 ) {
9379 /* shift left acc */
9382 /* using PRODL as a temporary register here */
9383 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9389 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9390 // pic16_emitcode ("mov","b,a");
9391 // pic16_emitcode("mov","a,@%s",rname);
9395 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9396 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9397 (unsigned char)(0xff >> (8-bstr))) ));
9398 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9399 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9403 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9404 ((unsigned char)(0xFF << (blen+bstr)) |
9405 (unsigned char)(0xFF >> (8-bstr)) ) );
9406 pic16_emitcode ("orl","a,b");
9407 if (p_type == GPOINTER)
9408 pic16_emitcode("pop","b");
9413 pic16_emitcode("mov","@%s,a",rname);
9416 pic16_emitcode("movx","@dptr,a");
9419 DEBUGpic16_emitcode(";lcall","__gptrput");
9428 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9429 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9434 if ( SPEC_BLEN(etype) <= 8 )
9437 pic16_emitcode("inc","%s",rname);
9438 rLen = SPEC_BLEN(etype) ;
9442 /* now generate for lengths greater than one byte */
9445 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9455 pic16_emitcode("mov","@%s,a",rname);
9457 pic16_emitcode("mov","@%s,%s",rname,l);
9462 pic16_emitcode("movx","@dptr,a");
9467 DEBUGpic16_emitcode(";lcall","__gptrput");
9470 pic16_emitcode ("inc","%s",rname);
9475 /* last last was not complete */
9477 /* save the byte & read byte */
9480 pic16_emitcode ("mov","b,a");
9481 pic16_emitcode("mov","a,@%s",rname);
9485 pic16_emitcode ("mov","b,a");
9486 pic16_emitcode("movx","a,@dptr");
9490 pic16_emitcode ("push","b");
9491 pic16_emitcode ("push","acc");
9492 pic16_emitcode ("lcall","__gptrget");
9493 pic16_emitcode ("pop","b");
9497 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9498 pic16_emitcode ("orl","a,b");
9501 if (p_type == GPOINTER)
9502 pic16_emitcode("pop","b");
9507 pic16_emitcode("mov","@%s,a",rname);
9511 pic16_emitcode("movx","@dptr,a");
9515 DEBUGpic16_emitcode(";lcall","__gptrput");
9519 /*-----------------------------------------------------------------*/
9520 /* genDataPointerSet - remat pointer to data space */
9521 /*-----------------------------------------------------------------*/
9522 static void genDataPointerSet(operand *right,
9526 int size, offset = 0, resoffset=0 ;
9528 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9529 pic16_aopOp(right,ic,FALSE);
9531 size = AOP_SIZE(right);
9533 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9536 if ( AOP_TYPE(result) == AOP_PCODE) {
9537 fprintf(stderr,"genDataPointerSet %s, %d\n",
9538 AOP(result)->aopu.pcop->name,
9539 (AOP(result)->aopu.pcop->type == PO_DIR)?
9540 PCOR(AOP(result)->aopu.pcop)->instance:
9541 PCOI(AOP(result)->aopu.pcop)->offset);
9545 if(AOP(result)->aopu.pcop->type == PO_DIR)
9546 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9549 if (AOP_TYPE(right) == AOP_LIT) {
9550 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9552 lit = lit >> (8*offset);
9554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9555 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9557 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9560 mov2w(AOP(right), offset);
9561 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9567 pic16_freeAsmop(right,NULL,ic,TRUE);
9572 /*-----------------------------------------------------------------*/
9573 /* genNearPointerSet - pic16_emitcode for near pointer put */
9574 /*-----------------------------------------------------------------*/
9575 static void genNearPointerSet (operand *right,
9582 sym_link *ptype = operandType(result);
9585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9586 retype= getSpec(operandType(right));
9587 resetype = getSpec(operandType(result));
9589 pic16_aopOp(result,ic,FALSE);
9591 /* if the result is rematerializable &
9592 * in data space & not a bit variable */
9594 /* and result is not a bit variable */
9595 if (AOP_TYPE(result) == AOP_PCODE
9596 // && AOP_TYPE(result) == AOP_IMMD
9597 && DCL_TYPE(ptype) == POINTER
9598 && !IS_BITFIELD(retype)
9599 && !IS_BITFIELD(resetype)) {
9601 genDataPointerSet (right,result,ic);
9602 pic16_freeAsmop(result,NULL,ic,TRUE);
9606 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9607 pic16_aopOp(right,ic,FALSE);
9608 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9610 /* if the value is already in a pointer register
9611 * then don't need anything more */
9612 if (!AOP_INPREG(AOP(result))) {
9613 /* otherwise get a free pointer register */
9614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9616 if( (AOP_TYPE(result) == AOP_PCODE)
9617 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9618 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9620 pic16_loadFSR0( result ); // patch 10
9622 // set up FSR0 with address of result
9623 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9624 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9629 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9633 /* if bitfield then unpack the bits */
9634 if (IS_BITFIELD(resetype)) {
9635 genPackBits (resetype, right, NULL, POINTER);
9637 /* we have can just get the values */
9638 int size = AOP_SIZE(right);
9641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9643 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9646 //pic16_emitcode("mov","@%s,a",rname);
9647 pic16_emitcode("movf","indf0,w ;1");
9650 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
9651 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
9653 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
9655 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
9657 } else { // no literal //
9659 pic16_emitpcode(POC_MOVFF, //
9660 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
9661 pic16_popCopyReg(&pic16_pc_postinc0))); //
9663 pic16_emitpcode(POC_MOVFF, //
9664 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
9665 pic16_popCopyReg(&pic16_pc_indf0))); //
9673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9674 /* now some housekeeping stuff */
9676 /* we had to allocate for this iCode */
9677 pic16_freeAsmop(NULL,aop,ic,TRUE);
9679 /* we did not allocate which means left
9680 * already in a pointer register, then
9681 * if size > 0 && this could be used again
9682 * we have to point it back to where it
9684 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9685 if (AOP_SIZE(right) > 1
9686 && !OP_SYMBOL(result)->remat
9687 && ( OP_SYMBOL(result)->liveTo > ic->seq
9690 int size = AOP_SIZE(right) - 1;
9693 pic16_emitcode("decf","fsr0,f");
9694 //pic16_emitcode("dec","%s",rname);
9698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9701 pic16_freeAsmop(right,NULL,ic,TRUE);
9702 pic16_freeAsmop(result,NULL,ic,TRUE);
9705 /*-----------------------------------------------------------------*/
9706 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
9707 /*-----------------------------------------------------------------*/
9708 static void genPagedPointerSet (operand *right,
9717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9719 retype= getSpec(operandType(right));
9721 pic16_aopOp(result,ic,FALSE);
9723 /* if the value is already in a pointer register
9724 then don't need anything more */
9725 if (!AOP_INPREG(AOP(result))) {
9726 /* otherwise get a free pointer register */
9728 preg = getFreePtr(ic,&aop,FALSE);
9729 pic16_emitcode("mov","%s,%s",
9731 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9732 rname = preg->name ;
9734 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9736 pic16_freeAsmop(result,NULL,ic,TRUE);
9737 pic16_aopOp (right,ic,FALSE);
9739 /* if bitfield then unpack the bits */
9740 if (IS_BITFIELD(retype))
9741 genPackBits (retype,right,rname,PPOINTER);
9743 /* we have can just get the values */
9744 int size = AOP_SIZE(right);
9748 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9751 pic16_emitcode("movx","@%s,a",rname);
9754 pic16_emitcode("inc","%s",rname);
9760 /* now some housekeeping stuff */
9762 /* we had to allocate for this iCode */
9763 pic16_freeAsmop(NULL,aop,ic,TRUE);
9765 /* we did not allocate which means left
9766 already in a pointer register, then
9767 if size > 0 && this could be used again
9768 we have to point it back to where it
9770 if (AOP_SIZE(right) > 1 &&
9771 !OP_SYMBOL(result)->remat &&
9772 ( OP_SYMBOL(result)->liveTo > ic->seq ||
9774 int size = AOP_SIZE(right) - 1;
9776 pic16_emitcode("dec","%s",rname);
9781 pic16_freeAsmop(right,NULL,ic,TRUE);
9786 /*-----------------------------------------------------------------*/
9787 /* genFarPointerSet - set value from far space */
9788 /*-----------------------------------------------------------------*/
9789 static void genFarPointerSet (operand *right,
9790 operand *result, iCode *ic)
9793 sym_link *retype = getSpec(operandType(right));
9795 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9796 pic16_aopOp(result,ic,FALSE);
9798 /* if the operand is already in dptr
9799 then we do nothing else we move the value to dptr */
9800 if (AOP_TYPE(result) != AOP_STR) {
9801 /* if this is remateriazable */
9802 if (AOP_TYPE(result) == AOP_IMMD)
9803 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9804 else { /* we need to get it byte by byte */
9805 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9806 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9807 if (options.model == MODEL_FLAT24)
9809 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9813 /* so dptr know contains the address */
9814 pic16_freeAsmop(result,NULL,ic,TRUE);
9815 pic16_aopOp(right,ic,FALSE);
9817 /* if bit then unpack */
9818 if (IS_BITFIELD(retype))
9819 genPackBits(retype,right,"dptr",FPOINTER);
9821 size = AOP_SIZE(right);
9825 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9827 pic16_emitcode("movx","@dptr,a");
9829 pic16_emitcode("inc","dptr");
9833 pic16_freeAsmop(right,NULL,ic,TRUE);
9836 /*-----------------------------------------------------------------*/
9837 /* genGenPointerSet - set value from generic pointer space */
9838 /*-----------------------------------------------------------------*/
9839 static void genGenPointerSet (operand *right,
9840 operand *result, iCode *ic)
9842 int i, size, offset, lit;
9843 sym_link *retype = getSpec(operandType(right));
9845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9847 pic16_aopOp(result,ic,FALSE);
9848 pic16_aopOp(right,ic,FALSE);
9849 size = AOP_SIZE(right);
9852 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9854 /* if the operand is already in dptr
9855 then we do nothing else we move the value to dptr */
9856 if (AOP_TYPE(result) != AOP_STR) {
9857 /* if this is remateriazable */
9858 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9859 // WARNING: anythig until "else" is untested!
9860 if (AOP_TYPE(result) == AOP_IMMD) {
9861 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9862 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9863 // load FSR0 from immediate
9864 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9876 else { /* we need to get it byte by byte */
9877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9878 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9880 // set up FSR0 with address of result
9881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9884 /* hack hack! see if this the FSR. If so don't load W */
9885 if(AOP_TYPE(right) != AOP_ACC) {
9887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9889 if(AOP_TYPE(right) == AOP_LIT)
9892 // note: pic16_popGet handles sign extension
9893 for(i=0;i<size;i++) {
9894 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
9896 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
9898 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9903 for(i=0;i<size;i++) {
9905 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9906 pic16_popCopyReg(&pic16_pc_postinc0)));
9908 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
9909 pic16_popCopyReg(&pic16_pc_indf0)));
9915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9916 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9918 } // if (AOP_TYPE(result) != AOP_IMMD)
9920 } // if (AOP_TYPE(result) != AOP_STR)
9921 /* so dptr know contains the address */
9924 /* if bit then unpack */
9925 if (IS_BITFIELD(retype))
9926 genPackBits(retype,right,"dptr",GPOINTER);
9928 size = AOP_SIZE(right);
9931 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
9933 // set up FSR0 with address of result
9934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9935 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9938 if (AOP_TYPE(right) == AOP_LIT) {
9939 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9941 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9943 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9945 } else { // no literal
9947 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9949 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9957 pic16_freeAsmop(right,NULL,ic,TRUE);
9958 pic16_freeAsmop(result,NULL,ic,TRUE);
9961 /*-----------------------------------------------------------------*/
9962 /* genPointerSet - stores the value into a pointer location */
9963 /*-----------------------------------------------------------------*/
9964 static void genPointerSet (iCode *ic)
9966 operand *right, *result ;
9967 sym_link *type, *etype;
9970 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9972 right = IC_RIGHT(ic);
9973 result = IC_RESULT(ic) ;
9975 /* depending on the type of pointer we need to
9976 move it to the correct pointer register */
9977 type = operandType(result);
9978 etype = getSpec(type);
9979 /* if left is of type of pointer then it is simple */
9980 if (IS_PTR(type) && !IS_FUNC(type->next)) {
9981 p_type = DCL_TYPE(type);
9984 /* we have to go by the storage class */
9985 p_type = PTR_TYPE(SPEC_OCLS(etype));
9987 /* if (SPEC_OCLS(etype)->codesp ) { */
9988 /* p_type = CPOINTER ; */
9991 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9992 /* p_type = FPOINTER ; */
9994 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9995 /* p_type = PPOINTER ; */
9997 /* if (SPEC_OCLS(etype) == idata ) */
9998 /* p_type = IPOINTER ; */
10000 /* p_type = POINTER ; */
10003 /* now that we have the pointer type we assign
10004 the pointer values */
10009 genNearPointerSet (right,result,ic);
10013 genPagedPointerSet (right,result,ic);
10017 genFarPointerSet (right,result,ic);
10021 genGenPointerSet (right,result,ic);
10025 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10026 "genPointerSet: illegal pointer type");
10030 /*-----------------------------------------------------------------*/
10031 /* genIfx - generate code for Ifx statement */
10032 /*-----------------------------------------------------------------*/
10033 static void genIfx (iCode *ic, iCode *popIc)
10035 operand *cond = IC_COND(ic);
10038 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10040 pic16_aopOp(cond,ic,FALSE);
10042 /* get the value into acc */
10043 if (AOP_TYPE(cond) != AOP_CRY)
10044 pic16_toBoolean(cond);
10047 /* the result is now in the accumulator */
10048 pic16_freeAsmop(cond,NULL,ic,TRUE);
10050 /* if there was something to be popped then do it */
10054 /* if the condition is a bit variable */
10055 if (isbit && IS_ITEMP(cond) &&
10057 genIfxJump(ic,SPIL_LOC(cond)->rname);
10058 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10061 if (isbit && !IS_ITEMP(cond))
10062 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10064 genIfxJump(ic,"a");
10070 /*-----------------------------------------------------------------*/
10071 /* genAddrOf - generates code for address of */
10072 /*-----------------------------------------------------------------*/
10073 static void genAddrOf (iCode *ic)
10075 operand *result, *left;
10077 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10078 pCodeOp *pcop0, *pcop1, *pcop2;
10080 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10082 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10083 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10085 sym = OP_SYMBOL( left );
10087 size = AOP_SIZE(IC_RESULT(ic));
10089 if(pic16_debug_verbose) {
10090 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10091 __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10094 /* Assume that what we want the address of is in data space
10095 * since there is no stack on the PIC, yet! -- VR */
10097 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10100 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10103 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10107 pic16_emitpcode(POC_MOVLW, pcop0);
10108 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10109 pic16_emitpcode(POC_MOVLW, pcop1);
10110 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10111 pic16_emitpcode(POC_MOVLW, pcop2);
10112 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10115 pic16_emitpcode(POC_MOVLW, pcop0);
10116 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10117 pic16_emitpcode(POC_MOVLW, pcop1);
10118 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10120 pic16_emitpcode(POC_MOVLW, pcop0);
10121 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10124 pic16_freeAsmop(result,NULL,ic,TRUE);
10125 pic16_freeAsmop(left, NULL, ic, FALSE);
10130 /*-----------------------------------------------------------------*/
10131 /* genFarFarAssign - assignment when both are in far space */
10132 /*-----------------------------------------------------------------*/
10133 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10135 int size = AOP_SIZE(right);
10138 /* first push the right side on to the stack */
10140 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10142 pic16_emitcode ("push","acc");
10145 pic16_freeAsmop(right,NULL,ic,FALSE);
10146 /* now assign DPTR to result */
10147 pic16_aopOp(result,ic,FALSE);
10148 size = AOP_SIZE(result);
10150 pic16_emitcode ("pop","acc");
10151 pic16_aopPut(AOP(result),"a",--offset);
10153 pic16_freeAsmop(result,NULL,ic,FALSE);
10158 /*-----------------------------------------------------------------*/
10159 /* genAssign - generate code for assignment */
10160 /*-----------------------------------------------------------------*/
10161 static void genAssign (iCode *ic)
10163 operand *result, *right;
10164 int size, offset,know_W;
10165 unsigned long lit = 0L;
10167 result = IC_RESULT(ic);
10168 right = IC_RIGHT(ic) ;
10170 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10172 /* if they are the same */
10173 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10176 pic16_aopOp(right,ic,FALSE);
10177 pic16_aopOp(result,ic,TRUE);
10179 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10181 /* if they are the same registers */
10182 if (pic16_sameRegs(AOP(right),AOP(result)))
10185 /* if the result is a bit */
10186 if (AOP_TYPE(result) == AOP_CRY) {
10187 /* if the right size is a literal then
10188 we know what the value is */
10189 if (AOP_TYPE(right) == AOP_LIT) {
10191 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10192 pic16_popGet(AOP(result),0));
10194 if (((int) operandLitValue(right)))
10195 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10196 AOP(result)->aopu.aop_dir,
10197 AOP(result)->aopu.aop_dir);
10199 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10200 AOP(result)->aopu.aop_dir,
10201 AOP(result)->aopu.aop_dir);
10205 /* the right is also a bit variable */
10206 if (AOP_TYPE(right) == AOP_CRY) {
10207 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10208 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10209 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10211 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10212 AOP(result)->aopu.aop_dir,
10213 AOP(result)->aopu.aop_dir);
10214 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10215 AOP(right)->aopu.aop_dir,
10216 AOP(right)->aopu.aop_dir);
10217 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10218 AOP(result)->aopu.aop_dir,
10219 AOP(result)->aopu.aop_dir);
10223 /* we need to or */
10224 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10225 pic16_toBoolean(right);
10227 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10228 //pic16_aopPut(AOP(result),"a",0);
10232 /* bit variables done */
10234 size = AOP_SIZE(result);
10236 if(AOP_TYPE(right) == AOP_LIT)
10237 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10239 /* VR - What is this?! */
10240 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10242 if(aopIdx(AOP(result),0) == 4) {
10243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10244 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10248 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10254 if(AOP_TYPE(right) == AOP_LIT) {
10256 if(know_W != (lit&0xff))
10257 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10259 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10261 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10265 } else if (AOP_TYPE(right) == AOP_CRY) {
10266 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10268 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10269 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10271 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10272 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10273 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10278 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10279 normally should work, but mind that the W register live range
10280 is not checked, so if the code generator assumes that the W
10281 is already loaded after such a pair, wrong code will be generated.
10283 Checking the live range is the next step.
10284 This is experimental code yet and has not been fully tested yet.
10285 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10286 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10288 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10290 /* This is the old code, which is assumed(?!) that works fine(!?) */
10292 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10293 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10302 pic16_freeAsmop (right,NULL,ic,FALSE);
10303 pic16_freeAsmop (result,NULL,ic,TRUE);
10306 /*-----------------------------------------------------------------*/
10307 /* genJumpTab - generates code for jump table */
10308 /*-----------------------------------------------------------------*/
10309 static void genJumpTab (iCode *ic)
10314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10316 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10317 /* get the condition into accumulator */
10318 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10320 /* multiply by three */
10321 pic16_emitcode("add","a,acc");
10322 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10324 jtab = newiTempLabel(NULL);
10325 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10326 pic16_emitcode("jmp","@a+dptr");
10327 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10329 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10330 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10332 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10333 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10334 pic16_emitpLabel(jtab->key);
10336 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10338 /* now generate the jump labels */
10339 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10340 jtab = setNextItem(IC_JTLABELS(ic))) {
10341 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10342 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10348 /*-----------------------------------------------------------------*/
10349 /* genMixedOperation - gen code for operators between mixed types */
10350 /*-----------------------------------------------------------------*/
10352 TSD - Written for the PIC port - but this unfortunately is buggy.
10353 This routine is good in that it is able to efficiently promote
10354 types to different (larger) sizes. Unfortunately, the temporary
10355 variables that are optimized out by this routine are sometimes
10356 used in other places. So until I know how to really parse the
10357 iCode tree, I'm going to not be using this routine :(.
10359 static int genMixedOperation (iCode *ic)
10362 operand *result = IC_RESULT(ic);
10363 sym_link *ctype = operandType(IC_LEFT(ic));
10364 operand *right = IC_RIGHT(ic);
10370 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10372 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10378 nextright = IC_RIGHT(nextic);
10379 nextleft = IC_LEFT(nextic);
10380 nextresult = IC_RESULT(nextic);
10382 pic16_aopOp(right,ic,FALSE);
10383 pic16_aopOp(result,ic,FALSE);
10384 pic16_aopOp(nextright, nextic, FALSE);
10385 pic16_aopOp(nextleft, nextic, FALSE);
10386 pic16_aopOp(nextresult, nextic, FALSE);
10388 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10390 operand *t = right;
10394 pic16_emitcode(";remove right +","");
10396 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10398 operand *t = right;
10402 pic16_emitcode(";remove left +","");
10406 big = AOP_SIZE(nextleft);
10407 small = AOP_SIZE(nextright);
10409 switch(nextic->op) {
10412 pic16_emitcode(";optimize a +","");
10413 /* if unsigned or not an integral type */
10414 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10415 pic16_emitcode(";add a bit to something","");
10418 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10420 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10421 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10422 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10424 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10432 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10433 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10434 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10437 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10439 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10440 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10441 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10442 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10443 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10446 pic16_emitcode("rlf","known_zero,w");
10453 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10454 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10455 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10457 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10467 pic16_freeAsmop(right,NULL,ic,TRUE);
10468 pic16_freeAsmop(result,NULL,ic,TRUE);
10469 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10470 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10472 nextic->generated = 1;
10479 /*-----------------------------------------------------------------*/
10480 /* genCast - gen code for casting */
10481 /*-----------------------------------------------------------------*/
10482 static void genCast (iCode *ic)
10484 operand *result = IC_RESULT(ic);
10485 sym_link *ctype = operandType(IC_LEFT(ic));
10486 sym_link *rtype = operandType(IC_RIGHT(ic));
10487 operand *right = IC_RIGHT(ic);
10490 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10491 /* if they are equivalent then do nothing */
10492 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10495 pic16_aopOp(right,ic,FALSE) ;
10496 pic16_aopOp(result,ic,FALSE);
10498 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10500 /* if the result is a bit */
10501 if (AOP_TYPE(result) == AOP_CRY) {
10503 /* if the right size is a literal then
10504 * we know what the value is */
10505 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10507 if (AOP_TYPE(right) == AOP_LIT) {
10508 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10509 pic16_popGet(AOP(result),0));
10511 if (((int) operandLitValue(right)))
10512 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10513 AOP(result)->aopu.aop_dir,
10514 AOP(result)->aopu.aop_dir);
10516 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10517 AOP(result)->aopu.aop_dir,
10518 AOP(result)->aopu.aop_dir);
10522 /* the right is also a bit variable */
10523 if (AOP_TYPE(right) == AOP_CRY) {
10525 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10527 pic16_emitcode("clrc","");
10528 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10529 AOP(right)->aopu.aop_dir,
10530 AOP(right)->aopu.aop_dir);
10531 pic16_aopPut(AOP(result),"c",0);
10535 /* we need to or */
10536 if (AOP_TYPE(right) == AOP_REG) {
10537 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10538 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10539 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10541 pic16_toBoolean(right);
10542 pic16_aopPut(AOP(result),"a",0);
10546 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10549 size = AOP_SIZE(result);
10551 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10553 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
10554 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10555 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10558 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10563 /* if they are the same size : or less */
10564 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10566 /* if they are in the same place */
10567 if (pic16_sameRegs(AOP(right),AOP(result)))
10570 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10572 if (IS_PTR_CONST(rtype))
10574 if (IS_CODEPTR(rtype))
10576 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10579 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10581 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10583 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10586 if(AOP_TYPE(right) == AOP_IMMD) {
10587 pCodeOp *pcop0, *pcop1, *pcop2;
10588 symbol *sym = OP_SYMBOL( right );
10590 size = AOP_SIZE(result);
10592 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10594 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10596 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10599 pic16_emitpcode(POC_MOVLW, pcop0);
10600 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10601 pic16_emitpcode(POC_MOVLW, pcop1);
10602 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10603 pic16_emitpcode(POC_MOVLW, pcop2);
10604 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10607 pic16_emitpcode(POC_MOVLW, pcop0);
10608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10609 pic16_emitpcode(POC_MOVLW, pcop1);
10610 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10612 pic16_emitpcode(POC_MOVLW, pcop0);
10613 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10617 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10618 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10619 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10620 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10622 if(AOP_SIZE(result) <2)
10623 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10625 /* if they in different places then copy */
10626 size = AOP_SIZE(result);
10629 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10630 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10637 /* if the result is of type pointer */
10638 if (IS_PTR(ctype)) {
10640 sym_link *type = operandType(right);
10641 sym_link *etype = getSpec(type);
10643 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
10645 /* pointer to generic pointer */
10646 if (IS_GENPTR(ctype)) {
10650 p_type = DCL_TYPE(type);
10652 /* we have to go by the storage class */
10653 p_type = PTR_TYPE(SPEC_OCLS(etype));
10655 /* if (SPEC_OCLS(etype)->codesp ) */
10656 /* p_type = CPOINTER ; */
10658 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10659 /* p_type = FPOINTER ; */
10661 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10662 /* p_type = PPOINTER; */
10664 /* if (SPEC_OCLS(etype) == idata ) */
10665 /* p_type = IPOINTER ; */
10667 /* p_type = POINTER ; */
10670 /* the first two bytes are known */
10671 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
10672 size = GPTRSIZE - 1;
10675 if(offset < AOP_SIZE(right)) {
10676 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
10677 if ((AOP_TYPE(right) == AOP_PCODE) &&
10678 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10679 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10682 pic16_aopPut(AOP(result),
10683 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10687 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10690 /* the last byte depending on type */
10694 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10697 pic16_emitcode(";BUG!? ","%d",__LINE__);
10701 pic16_emitcode(";BUG!? ","%d",__LINE__);
10705 pic16_emitcode(";BUG!? ","%d",__LINE__);
10710 /* this should never happen */
10711 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10712 "got unknown pointer type");
10715 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
10719 /* just copy the pointers */
10720 size = AOP_SIZE(result);
10723 pic16_aopPut(AOP(result),
10724 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10733 /* so we now know that the size of destination is greater
10734 than the size of the source.
10735 Now, if the next iCode is an operator then we might be
10736 able to optimize the operation without performing a cast.
10738 if(genMixedOperation(ic))
10741 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10743 /* we move to result for the size of source */
10744 size = AOP_SIZE(right);
10747 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10748 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10752 /* now depending on the sign of the destination */
10753 size = AOP_SIZE(result) - AOP_SIZE(right);
10754 /* if unsigned or not an integral type */
10755 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10757 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10759 /* we need to extend the sign :( */
10762 /* Save one instruction of casting char to int */
10763 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10764 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10765 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
10767 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10770 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10772 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10774 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
10782 pic16_freeAsmop(right,NULL,ic,TRUE);
10783 pic16_freeAsmop(result,NULL,ic,TRUE);
10787 /*-----------------------------------------------------------------*/
10788 /* genDjnz - generate decrement & jump if not zero instrucion */
10789 /*-----------------------------------------------------------------*/
10790 static int genDjnz (iCode *ic, iCode *ifx)
10792 symbol *lbl, *lbl1;
10793 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10798 /* if the if condition has a false label
10799 then we cannot save */
10803 /* if the minus is not of the form
10805 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10806 !IS_OP_LITERAL(IC_RIGHT(ic)))
10809 if (operandLitValue(IC_RIGHT(ic)) != 1)
10812 /* if the size of this greater than one then no
10814 if (getSize(operandType(IC_RESULT(ic))) > 1)
10817 /* otherwise we can save BIG */
10818 lbl = newiTempLabel(NULL);
10819 lbl1= newiTempLabel(NULL);
10821 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10823 if (IS_AOP_PREG(IC_RESULT(ic))) {
10824 pic16_emitcode("dec","%s",
10825 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10826 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10827 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10831 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10832 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10834 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10835 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10838 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10839 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10840 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10841 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10844 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10845 ifx->generated = 1;
10849 /*-----------------------------------------------------------------*/
10850 /* genReceive - generate code for a receive iCode */
10851 /*-----------------------------------------------------------------*/
10852 static void genReceive (iCode *ic)
10854 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10856 if (isOperandInFarSpace(IC_RESULT(ic)) &&
10857 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10858 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10860 int size = getSize(operandType(IC_RESULT(ic)));
10861 int offset = pic16_fReturnSizePic - size;
10864 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10865 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10869 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
10871 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10872 size = AOP_SIZE(IC_RESULT(ic));
10875 pic16_emitcode ("pop","acc");
10876 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10879 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
10882 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10884 assignResultValue(IC_RESULT(ic), 0);
10887 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10890 /*-----------------------------------------------------------------*/
10891 /* genDummyRead - generate code for dummy read of volatiles */
10892 /*-----------------------------------------------------------------*/
10894 genDummyRead (iCode * ic)
10896 pic16_emitcode ("; genDummyRead","");
10897 pic16_emitcode ("; not implemented","");
10902 /*-----------------------------------------------------------------*/
10903 /* genpic16Code - generate code for pic16 based controllers */
10904 /*-----------------------------------------------------------------*/
10906 * At this point, ralloc.c has gone through the iCode and attempted
10907 * to optimize in a way suitable for a PIC. Now we've got to generate
10908 * PIC instructions that correspond to the iCode.
10910 * Once the instructions are generated, we'll pass through both the
10911 * peep hole optimizer and the pCode optimizer.
10912 *-----------------------------------------------------------------*/
10914 void genpic16Code (iCode *lic)
10919 lineHead = lineCurr = NULL;
10921 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10922 pic16_addpBlock(pb);
10925 /* if debug information required */
10926 if (options.debug && currFunc) {
10928 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10930 if (IS_STATIC(currFunc->etype)) {
10931 pic16_emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
10932 //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10934 pic16_emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
10935 //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10942 for (ic = lic ; ic ; ic = ic->next ) {
10944 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10945 if ( cln != ic->lineno ) {
10946 if ( options.debug ) {
10948 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10949 FileBaseName(ic->filename),ic->lineno,
10950 ic->level,ic->block);
10954 if(!options.noCcodeInAsm) {
10955 pic16_addpCode2pBlock(pb,
10956 pic16_newpCodeCSource(ic->lineno, ic->filename,
10957 printCLine(ic->filename, ic->lineno)));
10963 if(options.iCodeInAsm) {
10964 /* insert here code to print iCode as comment */
10965 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10968 /* if the result is marked as
10969 spilt and rematerializable or code for
10970 this has already been generated then
10972 if (resultRemat(ic) || ic->generated )
10975 /* depending on the operation */
10994 /* IPOP happens only when trying to restore a
10995 spilt live range, if there is an ifx statement
10996 following this pop then the if statement might
10997 be using some of the registers being popped which
10998 would destroy the contents of the register so
10999 we need to check for this condition and handle it */
11001 ic->next->op == IFX &&
11002 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11003 genIfx (ic->next,ic);
11021 genEndFunction (ic);
11037 pic16_genPlus (ic) ;
11041 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11042 pic16_genMinus (ic);
11058 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11062 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11069 /* note these two are xlated by algebraic equivalence
11070 during parsing SDCC.y */
11071 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11072 "got '>=' or '<=' shouldn't have come here");
11076 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11088 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11092 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11096 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11120 genRightShift (ic);
11123 case GET_VALUE_AT_ADDRESS:
11128 if (POINTER_SET(ic))
11155 addSet(&_G.sendSet,ic);
11158 case DUMMY_READ_VOLATILE:
11168 /* now we are ready to call the
11169 peep hole optimizer */
11170 if (!options.nopeep) {
11171 peepHole (&lineHead);
11173 /* now do the actual printing */
11174 printLine (lineHead,codeOutFile);
11177 DFPRINTF((stderr,"printing pBlock\n\n"));
11178 pic16_printpBlock(stdout,pb);