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)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static void mov2f(asmop *dst, asmop *src, int offset);
62 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
63 static pCodeOp *pic16_popRegFromIdx(int rIdx);
65 //static int aopIdx (asmop *aop, int offset);
67 int pic16_labelOffset=0;
68 extern int pic16_debug_verbose;
69 static int optimized_for_speed = 0;
75 /* max_key keeps track of the largest label number used in
76 a function. This is then used to adjust the label offset
77 for the next function.
80 static int GpsuedoStkPtr=0;
82 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
84 unsigned int pic16aopLiteral (value *val, int offset);
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
91 static bool is_LitOp(operand *op);
92 static bool is_LitAOp(asmop *aop);
95 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
97 /* this is the down and dirty file with all kinds of
98 kludgy & hacky stuff. This is what it is all about
99 CODE GENERATION for a specific MCU . some of the
100 routines may be reusable, will have to see */
102 static char *zero = "#0x00";
103 static char *one = "#0x01";
104 //static char *spname = "sp";
108 * Function return value policy (MSB-->LSB):
110 * 16 bits -> PRODL:WREG
111 * 24 bits -> PRODH:PRODL:WREG
112 * 32 bits -> FSR0L:PRODH:PRODL:WREG
113 * >32 bits -> on stack, and FSR0 points to the beginning
118 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
119 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
120 static char **fReturn = fReturnpic16;
122 static char *accUse[] = {"WREG"};
124 //static short rbank = -1;
140 int stack_lat; /* stack offset latency */
144 /* Resolved ifx structure. This structure stores information
145 about an iCode ifx that makes it easier to generate code.
147 typedef struct resolvedIfx {
148 symbol *lbl; /* pointer to a label */
149 int condition; /* true or false ifx */
150 int generated; /* set true when the code associated with the ifx
154 extern int pic16_ptrRegReq ;
155 extern int pic16_nRegs;
156 extern FILE *codeOutFile;
157 //static void saverbank (int, iCode *,bool);
159 static lineNode *lineHead = NULL;
160 static lineNode *lineCurr = NULL;
162 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
163 0xE0, 0xC0, 0x80, 0x00};
164 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
165 0x07, 0x03, 0x01, 0x00};
169 /*-----------------------------------------------------------------*/
170 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
171 /* exponent of 2 is returned, otherwise -1 is */
173 /* note that this is similar to the function `powof2' in SDCCsymt */
177 /*-----------------------------------------------------------------*/
178 static int my_powof2 (unsigned long num)
181 if( (num & (num-1)) == 0) {
194 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
196 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
198 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
199 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
200 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
201 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
202 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
203 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
204 ((result) ? AOP_SIZE(result) : 0));
207 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
210 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
212 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
213 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
214 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
215 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
216 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
217 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
221 void pic16_emitpcomment (char *fmt, ...)
224 char lb[INITIAL_INLINEASM];
230 vsprintf(lb+1,fmt,ap);
232 while (isspace(*lbp)) lbp++;
235 lineCurr = (lineCurr ?
236 connectLine(lineCurr,newLineNode(lb)) :
237 (lineHead = newLineNode(lb)));
238 lineCurr->isInline = _G.inLine;
239 lineCurr->isDebug = _G.debugLine;
241 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
244 // fprintf(stderr, "%s\n", lb);
247 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
250 char lb[INITIAL_INLINEASM];
253 if(!pic16_debug_verbose)
260 sprintf(lb,"%s\t",inst);
262 sprintf(lb,"%s",inst);
263 vsprintf(lb+(strlen(lb)),fmt,ap);
267 while (isspace(*lbp)) lbp++;
270 lineCurr = (lineCurr ?
271 connectLine(lineCurr,newLineNode(lb)) :
272 (lineHead = newLineNode(lb)));
273 lineCurr->isInline = _G.inLine;
274 lineCurr->isDebug = _G.debugLine;
276 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
279 // fprintf(stderr, "%s\n", lb);
282 void pic16_emitpLabel(int key)
284 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
287 void pic16_emitpLabelFORCE(int key)
289 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
292 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
296 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
298 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
300 // fprintf(stderr, "%s\n", pcop->name);
303 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
306 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
312 #define pic16_emitcode DEBUGpic16_emitcode
314 /*-----------------------------------------------------------------*/
315 /* pic16_emitcode - writes the code into a file : for now it is simple */
316 /*-----------------------------------------------------------------*/
317 void pic16_emitcode (char *inst,char *fmt, ...)
320 char lb[INITIAL_INLINEASM];
327 sprintf(lb,"%s\t",inst);
329 sprintf(lb,"%s",inst);
330 vsprintf(lb+(strlen(lb)),fmt,ap);
334 while (isspace(*lbp)) lbp++;
337 lineCurr = (lineCurr ?
338 connectLine(lineCurr,newLineNode(lb)) :
339 (lineHead = newLineNode(lb)));
340 lineCurr->isInline = _G.inLine;
341 lineCurr->isDebug = _G.debugLine;
343 // VR fprintf(stderr, "lb = <%s>\n", lbp);
345 // if(pic16_debug_verbose)
346 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitDebuggerSymbol - associate the current code location */
355 /* with a debugger symbol */
356 /*-----------------------------------------------------------------*/
358 pic16_emitDebuggerSymbol (char * debugSym)
361 pic16_emitcode (";", "%s ==.", debugSym);
366 /*-----------------------------------------------------------------*/
367 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
368 /*-----------------------------------------------------------------*/
369 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
371 // bool r0iu = FALSE , r1iu = FALSE;
372 // bool r0ou = FALSE , r1ou = FALSE;
373 bool fsr0iu = FALSE, fsr0ou;
374 bool fsr2iu = FALSE, fsr2ou;
376 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
379 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
380 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
382 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
383 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
385 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
386 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
387 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
390 if(!fsr0iu && !fsr0ou) {
391 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
392 (*aopp)->type = AOP_FSR0;
394 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
396 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
400 /* no usage of FSR2 */
401 if(!fsr2iu && !fsr2ou) {
402 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
403 (*aopp)->type = AOP_FSR2;
405 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
409 /* now we know they both have usage */
410 /* if fsr0 not used in this instruction */
412 if (!_G.fsr0Pushed) {
413 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
414 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
418 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
419 (*aopp)->type = AOP_FSR0;
421 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
423 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
427 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
432 /* the logic: if r0 & r1 used in the instruction
433 then we are in trouble otherwise */
435 /* first check if r0 & r1 are used by this
436 instruction, in which case we are in trouble */
437 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
438 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
443 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
444 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
446 /* if no usage of r0 then return it */
447 if (!r0iu && !r0ou) {
448 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
449 (*aopp)->type = AOP_R0;
451 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
454 /* if no usage of r1 then return it */
455 if (!r1iu && !r1ou) {
456 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
457 (*aopp)->type = AOP_R1;
459 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
462 /* now we know they both have usage */
463 /* if r0 not used in this instruction */
465 /* push it if not already pushed */
467 //pic16_emitcode ("push","%s",
468 // pic16_regWithIdx(R0_IDX)->dname);
472 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
473 (*aopp)->type = AOP_R0;
475 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
478 /* if r1 not used then */
481 /* push it if not already pushed */
483 //pic16_emitcode ("push","%s",
484 // pic16_regWithIdx(R1_IDX)->dname);
488 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
489 (*aopp)->type = AOP_R1;
490 return pic16_regWithIdx(R1_IDX);
494 /* I said end of world but not quite end of world yet */
495 /* if this is a result then we can push it on the stack*/
497 (*aopp)->type = AOP_STK;
501 /* other wise this is true end of the world */
502 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
503 "getFreePtr should never reach here");
508 /*-----------------------------------------------------------------*/
509 /* newAsmop - creates a new asmOp */
510 /*-----------------------------------------------------------------*/
511 static asmop *newAsmop (short type)
515 aop = Safe_calloc(1,sizeof(asmop));
520 static void genSetDPTR(int n)
524 pic16_emitcode(";", "Select standard DPTR");
525 pic16_emitcode("mov", "dps, #0x00");
529 pic16_emitcode(";", "Select alternate DPTR");
530 pic16_emitcode("mov", "dps, #0x01");
534 /*-----------------------------------------------------------------*/
535 /* resolveIfx - converts an iCode ifx into a form more useful for */
536 /* generating code */
537 /*-----------------------------------------------------------------*/
538 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
541 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
547 resIfx->condition = 1; /* assume that the ifx is true */
548 resIfx->generated = 0; /* indicate that the ifx has not been used */
551 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
554 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
555 __FUNCTION__,__LINE__,resIfx->lbl->key);
560 resIfx->lbl = IC_TRUE(ifx);
562 resIfx->lbl = IC_FALSE(ifx);
563 resIfx->condition = 0;
568 DEBUGpic16_emitcode("; ***","ifx true is non-null");
570 DEBUGpic16_emitcode("; ***","ifx false is non-null");
574 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
578 /*-----------------------------------------------------------------*/
579 /* pointerCode - returns the code for a pointer type */
580 /*-----------------------------------------------------------------*/
581 static int pointerCode (sym_link *etype)
584 return PTR_TYPE(SPEC_OCLS(etype));
589 /*-----------------------------------------------------------------*/
590 /* aopForSym - for a true symbol */
591 /*-----------------------------------------------------------------*/
592 static asmop *aopForSym (iCode *ic, operand *op, bool result)
594 symbol *sym=OP_SYMBOL(op);
596 memmap *space= SPEC_OCLS(sym->etype);
598 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
600 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
602 // sym = OP_SYMBOL(op);
604 /* if already has one */
606 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
611 /* if symbol was initially placed onStack then we must re-place it
612 * to direct memory, since pic16 does not have a specific stack */
614 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
619 /* assign depending on the storage class */
620 /* if it is on the stack or indirectly addressable */
621 /* space we need to assign either r0 or r1 to it */
622 if (sym->onStack || sym->iaccess) {
626 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
627 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
629 /* acquire a temporary register -- it is saved in function */
631 sym->aop = aop = newAsmop(AOP_STA);
632 aop->aopu.stk.stk = sym->stack;
633 aop->size = getSize(sym->type);
636 DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
637 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
638 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
639 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
641 for(i=0;i<aop->size;i++)
642 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
643 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
645 for(i=0;i<aop->size;i++) {
646 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
647 _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
651 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
654 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
657 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
660 for(i=0;i<aop->size;i++) {
662 /* initialise for stack access via frame pointer */
663 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
665 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
666 pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
670 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
677 /* now assign the address of the variable to
678 the pointer register */
679 if (aop->type != AOP_STK) {
683 pic16_emitcode("push","acc");
685 pic16_emitcode("mov","a,_bp");
686 pic16_emitcode("add","a,#0x%02x",
688 ((char)(sym->stack - _G.nRegsSaved )) :
689 ((char)sym->stack)) & 0xff);
690 pic16_emitcode("mov","%s,a",
691 aop->aopu.aop_ptr->name);
694 pic16_emitcode("pop","acc");
696 pic16_emitcode("mov","%s,#%s",
697 aop->aopu.aop_ptr->name,
699 aop->paged = space->paged;
701 aop->aopu.aop_stk = sym->stack;
709 if (sym->onStack && options.stack10bit)
711 /* It's on the 10 bit stack, which is located in
715 //DEBUGpic16_emitcode(";","%d",__LINE__);
718 pic16_emitcode("push","acc");
720 pic16_emitcode("mov","a,_bp");
721 pic16_emitcode("add","a,#0x%02x",
723 ((char)(sym->stack - _G.nRegsSaved )) :
724 ((char)sym->stack)) & 0xff);
727 pic16_emitcode ("mov","dpx1,#0x40");
728 pic16_emitcode ("mov","dph1,#0x00");
729 pic16_emitcode ("mov","dpl1, a");
733 pic16_emitcode("pop","acc");
735 sym->aop = aop = newAsmop(AOP_DPTR2);
736 aop->size = getSize(sym->type);
740 //DEBUGpic16_emitcode(";","%d",__LINE__);
741 /* if in bit space */
742 if (IN_BITSPACE(space)) {
743 sym->aop = aop = newAsmop (AOP_CRY);
744 aop->aopu.aop_dir = sym->rname ;
745 aop->size = getSize(sym->type);
746 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
749 /* if it is in direct space */
750 if (IN_DIRSPACE(space)) {
751 sym->aop = aop = newAsmop (AOP_DIR);
752 aop->aopu.aop_dir = sym->rname ;
753 aop->size = getSize(sym->type);
754 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
755 pic16_allocDirReg( IC_LEFT(ic) );
759 if (IN_FARSPACE(space)) {
760 sym->aop = aop = newAsmop (AOP_DIR);
761 aop->aopu.aop_dir = sym->rname ;
762 aop->size = getSize(sym->type);
763 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
764 pic16_allocDirReg( IC_LEFT(ic) );
769 /* special case for a function */
770 if (IS_FUNC(sym->type)) {
771 sym->aop = aop = newAsmop(AOP_IMMD);
772 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
773 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
774 strcpy(aop->aopu.aop_immd,sym->rname);
775 aop->size = FPTRSIZE;
776 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
782 /* only remaining is far space */
783 /* in which case DPTR gets the address */
784 sym->aop = aop = newAsmop(AOP_PCODE);
786 /* change the next if to 1 to revert to good old immediate code */
787 if(IN_CODESPACE(space)) {
788 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
789 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
790 PCOI(aop->aopu.pcop)->index = 0;
792 /* try to allocate via direct register */
793 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
794 // aop->size = getSize( sym->type );
797 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
798 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
801 if(!pic16_allocDirReg (IC_LEFT(ic)))
805 if(IN_DIRSPACE( space ))
807 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
808 aop->size = FPTRSIZE;
809 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
810 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
811 else if(sym->onStack) {
817 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
819 /* if it is in code space */
820 if (IN_CODESPACE(space))
826 /*-----------------------------------------------------------------*/
827 /* aopForRemat - rematerialzes an object */
828 /*-----------------------------------------------------------------*/
829 static asmop *aopForRemat (operand *op) // x symbol *sym)
831 symbol *sym = OP_SYMBOL(op);
833 iCode *ic = NULL, *oldic;
834 asmop *aop = newAsmop(AOP_PCODE);
840 ic = sym->rematiCode;
842 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
844 if(IS_OP_POINTER(op)) {
845 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
851 // pic16_emitpcomment("ic: %s\n", printILine(ic));
854 val += (int) operandLitValue(IC_RIGHT(ic));
855 } else if (ic->op == '-') {
856 val -= (int) operandLitValue(IC_RIGHT(ic));
860 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
863 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
866 if(!op->isaddr)viaimmd++; else viaimmd=0;
868 /* set the following if to 1 to revert to good old immediate code */
869 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
872 DEBUGpic16_emitcode(";", "%s:%d immediate", __FILE__, __LINE__);
874 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
877 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
879 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
882 PCOI(aop->aopu.pcop)->index = val;
884 DEBUGpic16_emitcode(";", "%s:%d dir", __FILE__, __LINE__);
886 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
887 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
888 // aop->size = AOP_SIZE( IC_LEFT(ic) );
892 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
893 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
895 val, IS_PTR_CONST(operandType(op)));
897 val, IS_CODEPTR(operandType(op)));
900 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
902 pic16_allocDirReg (IC_LEFT(ic));
904 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
911 static int aopIdx (asmop *aop, int offset)
916 if(aop->type != AOP_REG)
919 return aop->aopu.aop_reg[offset]->rIdx;
924 /*-----------------------------------------------------------------*/
925 /* regsInCommon - two operands have some registers in common */
926 /*-----------------------------------------------------------------*/
927 static bool regsInCommon (operand *op1, operand *op2)
932 /* if they have registers in common */
933 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
936 sym1 = OP_SYMBOL(op1);
937 sym2 = OP_SYMBOL(op2);
939 if (sym1->nRegs == 0 || sym2->nRegs == 0)
942 for (i = 0 ; i < sym1->nRegs ; i++) {
947 for (j = 0 ; j < sym2->nRegs ;j++ ) {
951 if (sym2->regs[j] == sym1->regs[i])
959 /*-----------------------------------------------------------------*/
960 /* operandsEqu - equivalent */
961 /*-----------------------------------------------------------------*/
962 static bool operandsEqu ( operand *op1, operand *op2)
966 /* if they not symbols */
967 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
970 sym1 = OP_SYMBOL(op1);
971 sym2 = OP_SYMBOL(op2);
973 /* if both are itemps & one is spilt
974 and the other is not then false */
975 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
976 sym1->isspilt != sym2->isspilt )
979 /* if they are the same */
983 if (sym1->rname[0] && sym2->rname[0]
984 && strcmp (sym1->rname, sym2->rname) == 0)
988 /* if left is a tmp & right is not */
992 (sym1->usl.spillLoc == sym2))
999 (sym2->usl.spillLoc == sym1))
1005 /*-----------------------------------------------------------------*/
1006 /* pic16_sameRegs - two asmops have the same registers */
1007 /*-----------------------------------------------------------------*/
1008 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1015 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1016 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1018 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1020 if (aop1->type != AOP_REG ||
1021 aop2->type != AOP_REG )
1024 if (aop1->size != aop2->size )
1027 for (i = 0 ; i < aop1->size ; i++ ) {
1028 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1030 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1031 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1038 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1040 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1041 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1043 if(aop1 == aop2)return TRUE;
1044 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1046 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1052 /*-----------------------------------------------------------------*/
1053 /* pic16_aopOp - allocates an asmop for an operand : */
1054 /*-----------------------------------------------------------------*/
1055 void pic16_aopOp (operand *op, iCode *ic, bool result)
1064 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1066 /* if this a literal */
1067 if (IS_OP_LITERAL(op)) {
1068 op->aop = aop = newAsmop(AOP_LIT);
1069 aop->aopu.aop_lit = op->operand.valOperand;
1070 aop->size = getSize(operandType(op));
1075 sym_link *type = operandType(op);
1077 if(IS_PTR_CONST(type))
1079 if(IS_CODEPTR(type))
1081 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1084 /* if already has a asmop then continue */
1088 /* if the underlying symbol has a aop */
1089 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1090 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1091 op->aop = OP_SYMBOL(op)->aop;
1095 /* if this is a true symbol */
1096 if (IS_TRUE_SYMOP(op)) {
1097 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1098 op->aop = aopForSym(ic, op, result);
1102 /* this is a temporary : this has
1108 e) can be a return use only */
1110 sym = OP_SYMBOL(op);
1112 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1113 /* if the type is a conditional */
1114 if (sym->regType == REG_CND) {
1115 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1120 /* if it is spilt then two situations
1122 b) has a spill location */
1123 if (sym->isspilt || sym->nRegs == 0) {
1125 DEBUGpic16_emitcode(";","%d",__LINE__);
1126 /* rematerialize it NOW */
1129 sym->aop = op->aop = aop = aopForRemat (op);
1130 aop->size = getSize(sym->type);
1131 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1138 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1139 aop->size = getSize(sym->type);
1140 for ( i = 0 ; i < 1 ; i++ ) {
1141 aop->aopu.aop_str[i] = accUse[i];
1142 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1144 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1145 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1153 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1154 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1155 //pic16_allocDirReg (IC_LEFT(ic));
1156 aop->size = getSize(sym->type);
1161 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1162 aop->size = getSize(sym->type);
1163 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1164 aop->aopu.aop_str[i] = fReturn[i];
1166 DEBUGpic16_emitcode(";","%d",__LINE__);
1170 /* else spill location */
1171 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1172 /* force a new aop if sizes differ */
1173 sym->usl.spillLoc->aop = NULL;
1177 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1178 __FUNCTION__,__LINE__,
1179 sym->usl.spillLoc->rname,
1180 sym->rname, sym->usl.spillLoc->offset);
1183 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1184 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1185 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1187 sym->usl.spillLoc->offset, op);
1188 aop->size = getSize(sym->type);
1194 sym_link *type = operandType(op);
1196 if(IS_PTR_CONST(type))
1198 if(IS_CODEPTR(type))
1200 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1203 /* must be in a register */
1204 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1205 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1206 aop->size = sym->nRegs;
1207 for ( i = 0 ; i < sym->nRegs ;i++)
1208 aop->aopu.aop_reg[i] = sym->regs[i];
1211 /*-----------------------------------------------------------------*/
1212 /* pic16_freeAsmop - free up the asmop given to an operand */
1213 /*----------------------------------------------------------------*/
1214 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1231 /* depending on the asmop type only three cases need work AOP_RO
1232 , AOP_R1 && AOP_STK */
1234 switch (aop->type) {
1236 if (_G.fsr0Pushed ) {
1238 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1239 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1240 // pic16_emitcode ("pop","ar0");
1244 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1248 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1254 pic16_emitcode ("pop","ar0");
1258 bitVectUnSetBit(ic->rUsed,R0_IDX);
1264 pic16_emitcode ("pop","ar1");
1268 bitVectUnSetBit(ic->rUsed,R1_IDX);
1275 /* we must store the result on stack */
1276 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1277 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1278 for(i=0;i<aop->size;i++) {
1279 /* initialise for stack access via frame pointer */
1280 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1282 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1283 aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1286 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1290 for(i=0;i<aop->size;i++)
1291 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1300 int stk = aop->aopu.aop_stk + aop->size;
1301 bitVectUnSetBit(ic->rUsed,R0_IDX);
1302 bitVectUnSetBit(ic->rUsed,R1_IDX);
1304 getFreePtr(ic,&aop,FALSE);
1306 if (options.stack10bit)
1308 /* I'm not sure what to do here yet... */
1311 "*** Warning: probably generating bad code for "
1312 "10 bit stack mode.\n");
1316 pic16_emitcode ("mov","a,_bp");
1317 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1318 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1320 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1324 pic16_emitcode("pop","acc");
1325 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1327 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1330 pic16_freeAsmop(op,NULL,ic,TRUE);
1332 pic16_emitcode("pop","ar0");
1337 pic16_emitcode("pop","ar1");
1347 /* all other cases just dealloc */
1351 OP_SYMBOL(op)->aop = NULL;
1352 /* if the symbol has a spill */
1354 SPIL_LOC(op)->aop = NULL;
1359 /*-----------------------------------------------------------------*/
1360 /* pic16_aopGet - for fetching value of the aop */
1361 /*-----------------------------------------------------------------*/
1362 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1367 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1369 /* offset is greater than size then zero */
1370 if (offset > (aop->size - 1) &&
1371 aop->type != AOP_LIT)
1374 /* depending on type */
1375 switch (aop->type) {
1379 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1380 rs = Safe_calloc(1, strlen(s)+1);
1385 /* if we need to increment it */
1386 while (offset > aop->coff)
1388 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1392 while (offset < aop->coff)
1394 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1400 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1401 return (dname ? "acc" : "a");
1403 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1404 rs = Safe_calloc (1, strlen (s) + 1);
1412 sprintf (s,"%s",aop->aopu.aop_immd);
1415 sprintf(s,"(%s >> %d)",
1420 aop->aopu.aop_immd);
1421 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1422 rs = Safe_calloc(1,strlen(s)+1);
1428 sprintf(s,"(%s + %d)",
1431 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1433 sprintf(s,"%s",aop->aopu.aop_dir);
1434 rs = Safe_calloc(1,strlen(s)+1);
1440 // return aop->aopu.aop_reg[offset]->dname;
1442 return aop->aopu.aop_reg[offset]->name;
1445 //pic16_emitcode(";","%d",__LINE__);
1446 return aop->aopu.aop_dir;
1449 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1450 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1452 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1453 rs = Safe_strdup("WREG");
1457 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1458 rs = Safe_calloc(1,strlen(s)+1);
1463 aop->coff = offset ;
1464 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1467 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1469 return aop->aopu.aop_str[offset];
1473 pCodeOp *pcop = aop->aopu.pcop;
1474 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1476 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1477 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1478 sprintf(s,"%s", pcop->name);
1480 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1483 rs = Safe_calloc(1,strlen(s)+1);
1488 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1492 // pCodeOp *pcop = aop->aop
1497 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1498 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1499 "aopget got unsupported aop->type");
1505 /* lock has the following meaning: When allocating temporary registers
1506 * for stack variables storage, the value of the temporary register is
1507 * saved on stack. Its value is restored at the end. This procedure is
1508 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1509 * a possibility that before a call to pic16_aopOp, a temporary register
1510 * is allocated for a while and it is freed after some time, this will
1511 * mess the stack and values will not be restored properly. So use lock=1
1512 * to allocate temporary registers used internally by the programmer, and
1513 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1514 * to inform the compiler developer about a possible bug. This is an internal
1515 * feature for developing the compiler -- VR */
1517 int _TempReg_lock = 0;
1518 /*-----------------------------------------------------------------*/
1519 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1520 /*-----------------------------------------------------------------*/
1521 pCodeOp *pic16_popGetTempReg(int lock)
1526 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1528 werror(W_POSSBUG2, __FILE__, __LINE__);
1531 _TempReg_lock += lock;
1536 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1537 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1538 PCOR(pcop)->r->wasUsed=1;
1539 PCOR(pcop)->r->isFree=0;
1541 /* push value on stack */
1542 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1550 /*-----------------------------------------------------------------*/
1551 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1552 /* don't save if inside v */
1553 /*-----------------------------------------------------------------*/
1554 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1559 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1562 werror(W_POSSBUG2, __FILE__, __LINE__);
1565 _TempReg_lock += lock;
1570 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1571 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1572 PCOR(pcop)->r->wasUsed=1;
1573 PCOR(pcop)->r->isFree=0;
1575 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1576 /* push value on stack */
1577 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1587 /*-----------------------------------------------------------------*/
1588 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1589 /*-----------------------------------------------------------------*/
1590 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1592 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1594 _TempReg_lock -= lock;
1596 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1597 PCOR(pcop)->r->isFree = 1;
1598 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1601 /*-----------------------------------------------------------------*/
1602 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1603 /*-----------------------------------------------------------------*/
1604 pCodeOp *pic16_popGetLabel(unsigned int key)
1607 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1612 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1615 /*-----------------------------------------------------------------*/
1616 /* pic16_popCopyReg - copy a pcode operator */
1617 /*-----------------------------------------------------------------*/
1618 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1622 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1623 pcor->pcop.type = pc->pcop.type;
1625 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1626 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1628 pcor->pcop.name = NULL;
1631 pcor->rIdx = pc->rIdx;
1634 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1639 /*-----------------------------------------------------------------*/
1640 /* pic16_popGetLit - asm operator to pcode operator conversion */
1641 /*-----------------------------------------------------------------*/
1642 pCodeOp *pic16_popGetLit(int lit)
1644 return pic16_newpCodeOpLit(lit);
1647 /*-----------------------------------------------------------------*/
1648 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1649 /*-----------------------------------------------------------------*/
1650 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1652 return pic16_newpCodeOpLit2(lit, arg2);
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1661 return pic16_newpCodeOpImmd(name, offset,index, 0);
1665 /*-----------------------------------------------------------------*/
1666 /* pic16_popGet - asm operator to pcode operator conversion */
1667 /*-----------------------------------------------------------------*/
1668 pCodeOp *pic16_popGetWithString(char *str)
1674 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1678 pcop = pic16_newpCodeOp(str,PO_STR);
1683 /*-----------------------------------------------------------------*/
1684 /* pic16_popRegFromString - */
1685 /*-----------------------------------------------------------------*/
1686 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1689 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1690 pcop->type = PO_DIR;
1692 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1693 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1698 pcop->name = Safe_calloc(1,strlen(str)+1);
1699 strcpy(pcop->name,str);
1701 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1703 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1705 /* make sure that register doesn't exist,
1706 * and operand isn't NULL
1707 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1708 if((PCOR(pcop)->r == NULL)
1710 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1711 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1712 // __FUNCTION__, __LINE__, str, size, offset);
1714 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1715 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1718 PCOR(pcop)->instance = offset;
1723 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1727 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1729 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1730 PCOR(pcop)->rIdx = rIdx;
1731 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1733 PCOR(pcop)->r->isFree = 0;
1734 PCOR(pcop)->r->wasUsed = 1;
1736 pcop->type = PCOR(pcop)->r->pc_type;
1741 /*---------------------------------------------------------------------------------*/
1742 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1744 /*---------------------------------------------------------------------------------*/
1745 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1750 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1752 /* comment the following check, so errors to throw up */
1753 // if(!pcop2)return NULL;
1755 temp = pic16_popGet(aop_dst, offset);
1756 pcop2->pcop2 = temp;
1763 /*--------------------------------------------------------------------------------.-*/
1764 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1765 /* VR 030601 , adapted by Hans Dorn */
1766 /*--------------------------------------------------------------------------------.-*/
1767 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1771 pcop2 = (pCodeOpReg2 *)src;
1779 /*---------------------------------------------------------------------------------*/
1780 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1781 /* movff instruction */
1782 /*---------------------------------------------------------------------------------*/
1783 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1788 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1789 pcop2->pcop2 = pic16_popCopyReg(dst);
1791 /* the pCodeOp may be already allocated */
1792 pcop2 = (pCodeOpReg2 *)(src);
1793 pcop2->pcop2 = (pCodeOp *)(dst);
1800 /*-----------------------------------------------------------------*/
1801 /* pic16_popGet - asm operator to pcode operator conversion */
1802 /*-----------------------------------------------------------------*/
1803 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1805 //char *s = buffer ;
1809 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1810 /* offset is greater than
1813 // if (offset > (aop->size - 1) &&
1814 // aop->type != AOP_LIT)
1815 // return NULL; //zero;
1817 /* depending on type */
1818 switch (aop->type) {
1824 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1825 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1832 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1833 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1834 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1835 PCOR(pcop)->r->wasUsed = 1;
1836 PCOR(pcop)->r->isFree = 0;
1838 PCOR(pcop)->instance = offset;
1839 pcop->type = PCOR(pcop)->r->pc_type;
1843 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1844 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1847 /* pCodeOp is already allocated from aopForSym */
1848 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1849 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1855 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1857 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1859 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1861 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1862 PCOR(pcop)->rIdx = rIdx;
1863 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1864 PCOR(pcop)->r->wasUsed=1;
1865 PCOR(pcop)->r->isFree=0;
1867 PCOR(pcop)->instance = offset;
1868 pcop->type = PCOR(pcop)->r->pc_type;
1869 // rs = aop->aopu.aop_reg[offset]->name;
1870 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1874 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1875 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1881 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1882 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1886 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1888 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1890 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1891 // pcop->type = PO_GPR_REGISTER;
1892 PCOR(pcop)->rIdx = rIdx;
1893 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1894 PCOR(pcop)->r->wasUsed=1;
1895 PCOR(pcop)->r->isFree=0;
1897 PCOR(pcop)->instance = offset;
1898 pcop->type = PCOR(pcop)->r->pc_type;
1899 rs = aop->aopu.aop_reg[offset]->name;
1900 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1905 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1907 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1908 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1909 //if(PCOR(pcop)->r == NULL)
1910 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1914 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1915 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1918 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1919 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1922 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1923 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1924 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1925 pcop->type = PCOR(pcop)->r->pc_type;
1926 pcop->name = PCOR(pcop)->r->name;
1932 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1934 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1935 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1937 switch( aop->aopu.pcop->type ) {
1938 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1939 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1941 assert( 0 ); /* should never reach here */;
1944 PCOI(pcop)->offset = offset;
1949 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1950 "pic16_popGet got unsupported aop->type");
1953 /*-----------------------------------------------------------------*/
1954 /* pic16_aopPut - puts a string for a aop */
1955 /*-----------------------------------------------------------------*/
1956 void pic16_aopPut (asmop *aop, char *s, int offset)
1963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1965 if (aop->size && offset > ( aop->size - 1)) {
1966 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1967 "pic16_aopPut got offset > aop->size");
1971 /* will assign value to value */
1972 /* depending on where it is ofcourse */
1973 switch (aop->type) {
1976 sprintf(d,"(%s + %d)",
1977 aop->aopu.aop_dir,offset);
1978 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1981 sprintf(d,"%s",aop->aopu.aop_dir);
1984 DEBUGpic16_emitcode(";","%d",__LINE__);
1986 pic16_emitcode("movf","%s,w",s);
1987 pic16_emitcode("movwf","%s",d);
1990 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1991 if(offset >= aop->size) {
1992 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1995 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1998 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2005 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2006 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2009 strcmp(s,"r0") == 0 ||
2010 strcmp(s,"r1") == 0 ||
2011 strcmp(s,"r2") == 0 ||
2012 strcmp(s,"r3") == 0 ||
2013 strcmp(s,"r4") == 0 ||
2014 strcmp(s,"r5") == 0 ||
2015 strcmp(s,"r6") == 0 ||
2016 strcmp(s,"r7") == 0 )
2017 pic16_emitcode("mov","%s,%s ; %d",
2018 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2022 if(strcmp(s,"W")==0 )
2023 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2025 pic16_emitcode("movwf","%s",
2026 aop->aopu.aop_reg[offset]->name);
2028 if(strcmp(s,zero)==0) {
2029 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2031 } else if(strcmp(s,"W")==0) {
2032 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2033 pcop->type = PO_GPR_REGISTER;
2035 PCOR(pcop)->rIdx = -1;
2036 PCOR(pcop)->r = NULL;
2038 DEBUGpic16_emitcode(";","%d",__LINE__);
2039 pcop->name = Safe_strdup(s);
2040 pic16_emitpcode(POC_MOVFW,pcop);
2041 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2042 } else if(strcmp(s,one)==0) {
2043 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2044 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2046 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2054 if (aop->type == AOP_DPTR2)
2060 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2061 "pic16_aopPut writting to code space");
2065 while (offset > aop->coff) {
2067 pic16_emitcode ("inc","dptr");
2070 while (offset < aop->coff) {
2072 pic16_emitcode("lcall","__decdptr");
2077 /* if not in accumulater */
2080 pic16_emitcode ("movx","@dptr,a");
2082 if (aop->type == AOP_DPTR2)
2090 while (offset > aop->coff) {
2092 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2094 while (offset < aop->coff) {
2096 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2102 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2107 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2109 if (strcmp(s,"r0") == 0 ||
2110 strcmp(s,"r1") == 0 ||
2111 strcmp(s,"r2") == 0 ||
2112 strcmp(s,"r3") == 0 ||
2113 strcmp(s,"r4") == 0 ||
2114 strcmp(s,"r5") == 0 ||
2115 strcmp(s,"r6") == 0 ||
2116 strcmp(s,"r7") == 0 ) {
2118 sprintf(buffer,"a%s",s);
2119 pic16_emitcode("mov","@%s,%s",
2120 aop->aopu.aop_ptr->name,buffer);
2122 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2127 if (strcmp(s,"a") == 0)
2128 pic16_emitcode("push","acc");
2130 pic16_emitcode("push","%s",s);
2135 /* if bit variable */
2136 if (!aop->aopu.aop_dir) {
2137 pic16_emitcode("clr","a");
2138 pic16_emitcode("rlc","a");
2141 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2144 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2147 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2149 lbl = newiTempLabel(NULL);
2151 if (strcmp(s,"a")) {
2154 pic16_emitcode("clr","c");
2155 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2156 pic16_emitcode("cpl","c");
2157 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2158 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2165 if (strcmp(aop->aopu.aop_str[offset],s))
2166 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2171 if (!offset && (strcmp(s,"acc") == 0))
2174 if (strcmp(aop->aopu.aop_str[offset],s))
2175 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2179 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2180 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2181 // "pic16_aopPut got unsupported aop->type");
2187 /*-----------------------------------------------------------------*/
2188 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2189 /*-----------------------------------------------------------------*/
2190 static void mov2w (asmop *aop, int offset)
2192 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2195 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2197 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2200 static void mov2f(asmop *dst, asmop *src, int offset)
2202 if(is_LitAOp(src)) {
2203 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2204 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2206 if(pic16_sameRegsOfs(src, dst, offset))return;
2207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2208 pic16_popGet(dst, offset)));
2212 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2214 if(is_LitAOp(src)) {
2215 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2216 pic16_emitpcode(POC_MOVWF, dst);
2218 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2223 /* push pcop into stack */
2224 void pic16_pushpCodeOp(pCodeOp *pcop)
2226 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2227 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2230 /* pop pcop from stack */
2231 void pic16_poppCodeOp(pCodeOp *pcop)
2233 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2237 /*-----------------------------------------------------------------*/
2238 /* pushw - pushes wreg to stack */
2239 /*-----------------------------------------------------------------*/
2242 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2243 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2247 /*-----------------------------------------------------------------*/
2248 /* pushaop - pushes aop to stack */
2249 /*-----------------------------------------------------------------*/
2250 void pushaop(asmop *aop, int offset)
2252 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2253 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2256 /*-----------------------------------------------------------------*/
2257 /* popaop - pops aop from stack */
2258 /*-----------------------------------------------------------------*/
2259 void popaop(asmop *aop, int offset)
2261 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2262 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2265 void popaopidx(asmop *aop, int offset, int index)
2269 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2271 if(STACK_MODEL_LARGE)ofs++;
2273 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2274 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2277 /*-----------------------------------------------------------------*/
2278 /* reAdjustPreg - points a register back to where it should */
2279 /*-----------------------------------------------------------------*/
2280 static void reAdjustPreg (asmop *aop)
2284 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2286 if ((size = aop->size) <= 1)
2289 switch (aop->type) {
2293 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2297 if (aop->type == AOP_DPTR2)
2303 pic16_emitcode("lcall","__decdptr");
2306 if (aop->type == AOP_DPTR2)
2318 /*-----------------------------------------------------------------*/
2319 /* opIsGptr: returns non-zero if the passed operand is */
2320 /* a generic pointer type. */
2321 /*-----------------------------------------------------------------*/
2322 static int opIsGptr(operand *op)
2324 sym_link *type = operandType(op);
2326 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2327 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2335 /*-----------------------------------------------------------------*/
2336 /* pic16_getDataSize - get the operand data size */
2337 /*-----------------------------------------------------------------*/
2338 int pic16_getDataSize(operand *op)
2340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2343 return AOP_SIZE(op);
2345 // tsd- in the pic port, the genptr size is 1, so this code here
2346 // fails. ( in the 8051 port, the size was 4).
2349 size = AOP_SIZE(op);
2350 if (size == GPTRSIZE)
2352 sym_link *type = operandType(op);
2353 if (IS_GENPTR(type))
2355 /* generic pointer; arithmetic operations
2356 * should ignore the high byte (pointer type).
2359 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2366 /*-----------------------------------------------------------------*/
2367 /* pic16_outAcc - output Acc */
2368 /*-----------------------------------------------------------------*/
2369 void pic16_outAcc(operand *result)
2372 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2373 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2376 size = pic16_getDataSize(result);
2378 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2381 /* unsigned or positive */
2383 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2388 /*-----------------------------------------------------------------*/
2389 /* pic16_outBitC - output a bit C */
2390 /* Move to result the value of Carry flag -- VR */
2391 /*-----------------------------------------------------------------*/
2392 void pic16_outBitC(operand *result)
2396 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2397 /* if the result is bit */
2398 if (AOP_TYPE(result) == AOP_CRY) {
2399 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2400 pic16_aopPut(AOP(result),"c",0);
2403 i = AOP_SIZE(result);
2405 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2407 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2410 pic16_emitcode("clr","a ; %d", __LINE__);
2411 pic16_emitcode("rlc","a");
2412 pic16_outAcc(result);
2417 /*-----------------------------------------------------------------*/
2418 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2419 /*-----------------------------------------------------------------*/
2420 void pic16_toBoolean(operand *oper)
2422 int size = AOP_SIZE(oper) - 1;
2425 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2427 if ( AOP_TYPE(oper) != AOP_ACC) {
2428 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2431 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2436 #if !defined(GEN_Not)
2437 /*-----------------------------------------------------------------*/
2438 /* genNot - generate code for ! operation */
2439 /*-----------------------------------------------------------------*/
2440 static void pic16_genNot (iCode *ic)
2445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2446 /* assign asmOps to operand & result */
2447 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2448 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2450 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2451 /* if in bit space then a special case */
2452 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2453 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2454 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2455 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2457 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2458 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2459 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2464 size = AOP_SIZE(IC_LEFT(ic));
2466 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2467 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2468 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2471 pic16_toBoolean(IC_LEFT(ic));
2473 tlbl = newiTempLabel(NULL);
2474 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2475 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2476 pic16_outBitC(IC_RESULT(ic));
2479 /* release the aops */
2480 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2481 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2486 #if !defined(GEN_Cpl)
2487 /*-----------------------------------------------------------------*/
2488 /* genCpl - generate code for complement */
2489 /*-----------------------------------------------------------------*/
2490 static void pic16_genCpl (iCode *ic)
2496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2497 /* assign asmOps to operand & result */
2498 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2499 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2501 /* if both are in bit space then
2503 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2504 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2506 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2507 pic16_emitcode("cpl","c");
2508 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2512 size = AOP_SIZE(IC_RESULT(ic));
2515 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2517 pic16_emitcode("cpl","a");
2518 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2520 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2521 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2523 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2532 /* release the aops */
2533 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2534 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* genUminusFloat - unary minus for floating points */
2540 /*-----------------------------------------------------------------*/
2541 static void genUminusFloat(operand *op,operand *result)
2543 int size ,offset =0 ;
2546 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2547 /* for this we just need to flip the
2548 first it then copy the rest in place */
2549 size = AOP_SIZE(op) - 1;
2550 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2554 pic16_emitcode("cpl","acc.7");
2555 pic16_aopPut(AOP(result),"a",3);
2558 pic16_aopPut(AOP(result),
2559 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2565 /*-----------------------------------------------------------------*/
2566 /* genUminus - unary minus code generation */
2567 /*-----------------------------------------------------------------*/
2568 static void genUminus (iCode *ic)
2571 sym_link *optype, *rtype;
2573 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2576 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2577 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2579 /* if both in bit space then special case */
2580 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2581 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2583 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2584 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2585 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2590 optype = operandType(IC_LEFT(ic));
2591 rtype = operandType(IC_RESULT(ic));
2593 /* if float then do float stuff */
2594 if (IS_FLOAT(optype)) {
2595 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2599 /* otherwise subtract from zero by taking the 2's complement */
2600 size = AOP_SIZE(IC_LEFT(ic));
2602 for(i=0; i<size; i++) {
2603 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2604 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2606 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2607 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2611 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2612 for(i=1; i<size; i++) {
2614 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2618 /* release the aops */
2619 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2620 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2624 /*-----------------------------------------------------------------*/
2625 /* saveRegisters - will look for a call and save the registers */
2626 /*-----------------------------------------------------------------*/
2627 static void saveRegisters(iCode *lic)
2634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2636 for (ic = lic ; ic ; ic = ic->next)
2637 if (ic->op == CALL || ic->op == PCALL)
2641 fprintf(stderr,"found parameter push with no function call\n");
2645 /* if the registers have been saved already then
2647 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2650 /* find the registers in use at this time
2651 and push them away to safety */
2652 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2656 if (options.useXstack) {
2657 if (bitVectBitValue(rsave,R0_IDX))
2658 pic16_emitcode("mov","b,r0");
2659 pic16_emitcode("mov","r0,%s",spname);
2660 for (i = 0 ; i < pic16_nRegs ; i++) {
2661 if (bitVectBitValue(rsave,i)) {
2663 pic16_emitcode("mov","a,b");
2665 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2666 pic16_emitcode("movx","@r0,a");
2667 pic16_emitcode("inc","r0");
2670 pic16_emitcode("mov","%s,r0",spname);
2671 if (bitVectBitValue(rsave,R0_IDX))
2672 pic16_emitcode("mov","r0,b");
2674 //for (i = 0 ; i < pic16_nRegs ; i++) {
2675 // if (bitVectBitValue(rsave,i))
2676 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2679 dtype = operandType(IC_LEFT(ic));
2680 if (currFunc && dtype &&
2681 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2682 IFFUNC_ISISR(currFunc->type) &&
2685 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2688 /*-----------------------------------------------------------------*/
2689 /* unsaveRegisters - pop the pushed registers */
2690 /*-----------------------------------------------------------------*/
2691 static void unsaveRegisters (iCode *ic)
2696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2697 /* find the registers in use at this time
2698 and push them away to safety */
2699 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2702 if (options.useXstack) {
2703 pic16_emitcode("mov","r0,%s",spname);
2704 for (i = pic16_nRegs ; i >= 0 ; i--) {
2705 if (bitVectBitValue(rsave,i)) {
2706 pic16_emitcode("dec","r0");
2707 pic16_emitcode("movx","a,@r0");
2709 pic16_emitcode("mov","b,a");
2711 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2715 pic16_emitcode("mov","%s,r0",spname);
2716 if (bitVectBitValue(rsave,R0_IDX))
2717 pic16_emitcode("mov","r0,b");
2719 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2720 // if (bitVectBitValue(rsave,i))
2721 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2728 /*-----------------------------------------------------------------*/
2730 /*-----------------------------------------------------------------*/
2731 static void pushSide(operand * oper, int size)
2734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2736 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2737 if (AOP_TYPE(oper) != AOP_REG &&
2738 AOP_TYPE(oper) != AOP_DIR &&
2740 pic16_emitcode("mov","a,%s",l);
2741 pic16_emitcode("push","acc");
2743 pic16_emitcode("push","%s",l);
2748 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2750 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2751 pic16_emitpcode(POC_MOVFW, src);
2752 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2754 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2755 src, pic16_popGet(AOP(op), offset)));
2760 /*-----------------------------------------------------------------*/
2761 /* assignResultValue - assign results to oper, rescall==1 is */
2762 /* called from genCall() or genPCall() */
2763 /*-----------------------------------------------------------------*/
2764 static void assignResultValue(operand * oper, int rescall)
2766 int size = AOP_SIZE(oper);
2769 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2770 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2773 /* assign result from a call/pcall function() */
2775 /* function results are stored in a special order,
2776 * see top of file with Function return policy, or manual */
2779 /* 8-bits, result in WREG */
2780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2783 /* 16-bits, result in PRODL:WREG */
2784 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2788 /* 24-bits, result in PRODH:PRODL:WREG */
2789 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2793 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2794 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2798 /* >32-bits, result on stack, and FSR0 points to beginning.
2799 * Fix stack when done */
2802 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2803 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2805 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2810 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2811 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2812 if(STACK_MODEL_LARGE) {
2814 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2818 int areg = 0; /* matching argument register */
2820 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2821 /* its called from genReceive (probably) */
2822 if(!GpsuedoStkPtr) {
2823 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2824 /* The last byte in the assignment is in W */
2825 if(areg <= GpsuedoStkPtr) {
2827 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2831 _G.stack_lat = AOP_SIZE(oper)-1;
2835 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2836 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2837 if(areg <= GpsuedoStkPtr) {
2839 popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2848 /*-----------------------------------------------------------------*/
2849 /* genIpush - genrate code for pushing this gets a little complex */
2850 /*-----------------------------------------------------------------*/
2851 static void genIpush (iCode *ic)
2853 // int size, offset=0;
2855 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2859 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2861 /* send to stack as normal */
2862 addSet(&_G.sendSet,ic);
2863 // addSetHead(&_G.sendSet,ic);
2864 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2869 int size, offset = 0 ;
2873 /* if this is not a parm push : ie. it is spill push
2874 and spill push is always done on the local stack */
2875 if (!ic->parmPush) {
2877 /* and the item is spilt then do nothing */
2878 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2881 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2882 size = AOP_SIZE(IC_LEFT(ic));
2883 /* push it on the stack */
2885 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2890 pic16_emitcode("push","%s",l);
2895 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2899 /*-----------------------------------------------------------------*/
2900 /* genIpop - recover the registers: can happen only for spilling */
2901 /*-----------------------------------------------------------------*/
2902 static void genIpop (iCode *ic)
2904 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2909 /* if the temp was not pushed then */
2910 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2913 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2914 size = AOP_SIZE(IC_LEFT(ic));
2917 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2920 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2925 /*-----------------------------------------------------------------*/
2926 /* unsaverbank - restores the resgister bank from stack */
2927 /*-----------------------------------------------------------------*/
2928 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2930 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2938 if (options.useXstack) {
2940 r = getFreePtr(ic,&aop,FALSE);
2943 pic16_emitcode("mov","%s,_spx",r->name);
2944 pic16_emitcode("movx","a,@%s",r->name);
2945 pic16_emitcode("mov","psw,a");
2946 pic16_emitcode("dec","%s",r->name);
2949 pic16_emitcode ("pop","psw");
2952 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2953 if (options.useXstack) {
2954 pic16_emitcode("movx","a,@%s",r->name);
2955 //pic16_emitcode("mov","(%s+%d),a",
2956 // regspic16[i].base,8*bank+regspic16[i].offset);
2957 pic16_emitcode("dec","%s",r->name);
2960 pic16_emitcode("pop",""); //"(%s+%d)",
2961 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2964 if (options.useXstack) {
2966 pic16_emitcode("mov","_spx,%s",r->name);
2967 pic16_freeAsmop(NULL,aop,ic,TRUE);
2973 /*-----------------------------------------------------------------*/
2974 /* saverbank - saves an entire register bank on the stack */
2975 /*-----------------------------------------------------------------*/
2976 static void saverbank (int bank, iCode *ic, bool pushPsw)
2978 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2985 if (options.useXstack) {
2988 r = getFreePtr(ic,&aop,FALSE);
2989 pic16_emitcode("mov","%s,_spx",r->name);
2993 for (i = 0 ; i < pic16_nRegs ;i++) {
2994 if (options.useXstack) {
2995 pic16_emitcode("inc","%s",r->name);
2996 //pic16_emitcode("mov","a,(%s+%d)",
2997 // regspic16[i].base,8*bank+regspic16[i].offset);
2998 pic16_emitcode("movx","@%s,a",r->name);
3000 pic16_emitcode("push","");// "(%s+%d)",
3001 //regspic16[i].base,8*bank+regspic16[i].offset);
3005 if (options.useXstack) {
3006 pic16_emitcode("mov","a,psw");
3007 pic16_emitcode("movx","@%s,a",r->name);
3008 pic16_emitcode("inc","%s",r->name);
3009 pic16_emitcode("mov","_spx,%s",r->name);
3010 pic16_freeAsmop (NULL,aop,ic,TRUE);
3013 pic16_emitcode("push","psw");
3015 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3023 /*-----------------------------------------------------------------*/
3024 /* genCall - generates a call statement */
3025 /*-----------------------------------------------------------------*/
3026 static void genCall (iCode *ic)
3033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3035 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3036 /* if caller saves & we have not saved then */
3037 // if (!ic->regsSaved)
3038 // saveRegisters(ic);
3040 /* initialise stackParms for IPUSH pushes */
3041 // stackParms = psuedoStkPtr;
3042 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3043 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3046 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3049 /* if send set is not empty the assign */
3052 int psuedoStkPtr=-1;
3053 int firstTimeThruLoop = 1;
3057 /* reverse sendSet if function is not reentrant */
3058 if(!IFFUNC_ISREENT(ftype))
3059 _G.sendSet = reverseSet(_G.sendSet);
3062 /* First figure how many parameters are getting passed */
3064 /* do we really need to know this ? -- VR
3065 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3066 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3067 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3068 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3073 // stackParms = psuedoStkPtr;
3077 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3078 int size, offset = 0;
3080 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3081 size = AOP_SIZE(IC_LEFT(sic));
3086 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3087 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3088 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3090 if(!firstTimeThruLoop) {
3091 /* If this is not the first time we've been through the loop
3092 * then we need to save the parameter in a temporary
3093 * register. The last byte of the last parameter is
3097 // --psuedoStkPtr; // sanity check
3100 firstTimeThruLoop=0;
3102 mov2w (AOP(IC_LEFT(sic)), size);
3106 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3109 /* save last parameter to stack if functions has varargs */
3110 if(IFFUNC_HASVARARGS(ftype))pushw();
3111 else use_wreg = 1; /* last parameter in WREG */
3113 _G.stackRegSet = _G.sendSet;
3118 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3121 /* if we need to assign a result value */
3122 if ((IS_ITEMP(IC_RESULT(ic))
3123 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3124 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3125 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3128 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3131 assignResultValue(IC_RESULT(ic), 1);
3133 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3134 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3136 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3139 if(!stackParms && ic->parmBytes) {
3140 stackParms = ic->parmBytes;
3143 stackParms -= use_wreg;
3146 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3147 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3148 if(STACK_MODEL_LARGE) {
3150 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3155 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3158 /* adjust the stack for parameters if required */
3159 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3162 /* if register bank was saved then pop them */
3164 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3166 /* if we hade saved some registers then unsave them */
3167 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3168 unsaveRegisters (ic);
3174 /*-----------------------------------------------------------------*/
3175 /* genPcall - generates a call by pointer statement */
3176 /* new version, created from genCall - HJD */
3177 /*-----------------------------------------------------------------*/
3178 static void genPcall (iCode *ic)
3182 symbol *retlbl = newiTempLabel(NULL);
3183 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3186 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3188 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3190 /* if send set is not empty the assign */
3193 int psuedoStkPtr=-1;
3194 int firstTimeThruLoop = 1;
3196 /* For the Pic port, there is no data stack.
3197 * So parameters passed to functions are stored
3198 * in registers. (The pCode optimizer will get
3199 * rid of most of these :). */
3203 /* reverse sendSet if function is not reentrant */
3204 if(!IFFUNC_ISREENT(ftype))
3205 _G.sendSet = reverseSet(_G.sendSet);
3208 /* First figure how many parameters are getting passed */
3210 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3211 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3212 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3213 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3217 // stackParms = psuedoStkPtr;
3220 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3221 int size, offset = 0;
3223 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3224 size = AOP_SIZE(IC_LEFT(sic));
3228 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3229 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3230 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3232 if(!firstTimeThruLoop) {
3233 /* If this is not the first time we've been through the loop
3234 * then we need to save the parameter in a temporary
3235 * register. The last byte of the last parameter is
3239 --psuedoStkPtr; // sanity check
3242 firstTimeThruLoop=0;
3244 mov2w (AOP(IC_LEFT(sic)), size);
3250 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3253 if(IFFUNC_HASVARARGS(ftype))
3256 use_wreg = 1; /* last parameter in WREG */
3258 _G.stackRegSet = _G.sendSet;
3262 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3264 // push return address
3265 // push $ on return stack, then replace with retlbl
3267 pic16_emitpcodeNULLop(POC_PUSH);
3269 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3270 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3271 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3272 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3273 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3274 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3276 /* make the call by writing the pointer into pc */
3277 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3278 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3280 // note: MOVFF to PCL not allowed
3281 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3282 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3285 /* return address is here: (X) */
3286 pic16_emitpLabelFORCE(retlbl->key);
3288 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3291 /* if we need assign a result value */
3292 if ((IS_ITEMP(IC_RESULT(ic))
3293 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3294 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3295 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3298 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3301 assignResultValue(IC_RESULT(ic), 1);
3303 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3304 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3306 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3309 stackParms -= use_wreg;
3312 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3313 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3314 if(STACK_MODEL_LARGE) {
3315 /* this implies that stackParms < 256 !!! -- VR */
3317 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3322 /*-----------------------------------------------------------------*/
3323 /* resultRemat - result is rematerializable */
3324 /*-----------------------------------------------------------------*/
3325 static int resultRemat (iCode *ic)
3327 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3328 if (SKIP_IC(ic) || ic->op == IFX)
3331 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3332 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3333 if (sym->remat && !POINTER_SET(ic))
3340 #if defined(__BORLANDC__) || defined(_MSC_VER)
3341 #define STRCASECMP stricmp
3343 #define STRCASECMP strcasecmp
3347 /*-----------------------------------------------------------------*/
3348 /* inExcludeList - return 1 if the string is in exclude Reg list */
3349 /*-----------------------------------------------------------------*/
3350 static bool inExcludeList(char *s)
3352 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3355 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3356 if (options.excludeRegs[i] &&
3357 STRCASECMP(options.excludeRegs[i],"none") == 0)
3360 for ( i = 0 ; options.excludeRegs[i]; i++) {
3361 if (options.excludeRegs[i] &&
3362 STRCASECMP(s,options.excludeRegs[i]) == 0)
3369 /*-----------------------------------------------------------------*/
3370 /* genFunction - generated code for function entry */
3371 /*-----------------------------------------------------------------*/
3372 static void genFunction (iCode *ic)
3377 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3379 pic16_labelOffset += (max_key+4);
3384 ftype = operandType(IC_LEFT(ic));
3385 sym = OP_SYMBOL(IC_LEFT(ic));
3387 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3388 /* create an absolute section at the interrupt vector:
3389 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3397 sym = OP_SYMBOL( IC_LEFT(ic));
3399 if(interrupts[i]->name
3400 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3407 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3408 __FILE__, __LINE__, sym->name);
3411 _G.interruptvector = found;
3414 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3415 asym = newSymbol(asymname, 0);
3417 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3418 pic16_addpBlock( apb );
3420 pic16_addpCode2pBlock(apb,
3421 pic16_newpCodeCharP(";-----------------------------------------"));
3424 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3426 pic16_addpCode2pBlock(apb,
3427 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3429 /* mark the end of this tiny function */
3430 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3435 abSym = Safe_calloc(1, sizeof(absSym));
3436 abSym->name = Safe_strdup( asymname );
3438 switch( _G.interruptvector ) {
3439 case 0: abSym->address = 0x000000; break;
3440 case 1: abSym->address = 0x000008; break;
3441 case 2: abSym->address = 0x000018; break;
3444 /* relocate interrupt vectors if needed */
3445 abSym->address += pic16_options.ivt_loc;
3447 addSet(&absSymSet, abSym);
3452 /* create the function header */
3453 pic16_emitcode(";","-----------------------------------------");
3454 pic16_emitcode(";"," function %s",sym->name);
3455 pic16_emitcode(";","-----------------------------------------");
3457 pic16_emitcode("","%s:",sym->rname);
3458 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3464 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3465 if(!strcmp(ab->name, sym->name)) {
3466 pic16_pBlockConvert2Absolute(pb);
3473 if(IFFUNC_ISNAKED(ftype)) {
3474 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3478 /* if critical function then turn interrupts off */
3479 if (IFFUNC_ISCRITICAL(ftype)) {
3480 //pic16_emitcode("clr","ea");
3483 _G.fregsUsed = sym->regsUsed;
3485 /* if this is an interrupt service routine then
3486 * save acc, b, dpl, dph */
3487 if (IFFUNC_ISISR(sym->type)) {
3490 _G.usefastretfie = 1; /* use shadow registers by default */
3491 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3492 if(!(_G.interruptvector == 1)) {
3494 /* do not save WREG,STATUS,BSR for high priority interrupts
3495 * because they are stored in the hardware shadow registers already */
3496 _G.usefastretfie = 0;
3497 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3498 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3499 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3503 /* these should really be optimized somehow, because not all
3504 * interrupt handlers modify them */
3505 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3506 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3507 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3508 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3510 // pic16_pBlockConvert2ISR(pb);
3512 /* if any registers used */
3513 if (sym->regsUsed) {
3514 /* save the registers used */
3515 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3516 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3517 if (bitVectBitValue(sym->regsUsed,i)) {
3519 fprintf(stderr, "%s:%d function %s uses register %s\n",
3520 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3521 pic16_regWithIdx(i)->name);
3524 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3527 if(!pic16_regWithIdx(i)->wasUsed) {
3528 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3529 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3531 pic16_regWithIdx(i)->wasUsed = 1;
3537 /* emit code to setup stack frame if user enabled,
3538 * and function is not main() */
3540 // fprintf(stderr, "function name: %s\n", sym->name);
3541 if(strcmp(sym->name, "main")) {
3542 if(/*!options.ommitFramePtr || sym->regsUsed*/1) {
3543 /* setup the stack frame */
3544 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3545 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3546 if(STACK_MODEL_LARGE)
3547 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3551 /* if callee-save to be used for this function
3552 * then save the registers being used in this function */
3553 // if (IFFUNC_CALLEESAVES(sym->type))
3557 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3559 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3561 /* if any registers used */
3562 if (sym->regsUsed) {
3563 /* save the registers used */
3564 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3565 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3566 if (bitVectBitValue(sym->regsUsed,i)) {
3569 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3570 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3571 pic16_regWithIdx(i)->name,
3572 pic16_regWithIdx(i)->wasUsed,
3573 pic16_regWithIdx(i));
3576 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3578 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3579 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3580 // &pic16_pc_postdec1, 0));
3584 if(!pic16_regWithIdx(i)->wasUsed) {
3585 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3586 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3588 pic16_regWithIdx(i)->wasUsed = 1;
3600 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3602 if (options.useXstack) {
3603 pic16_emitcode("mov","r0,%s",spname);
3604 pic16_emitcode("mov","a,_bp");
3605 pic16_emitcode("movx","@r0,a");
3606 pic16_emitcode("inc","%s",spname);
3608 /* set up the stack */
3609 pic16_emitcode ("push","_bp"); /* save the callers stack */
3611 pic16_emitcode ("mov","_bp,%s",spname);
3614 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3616 /* adjust the stack for the function */
3621 werror(W_STACK_OVERFLOW,sym->name);
3623 if (i > 3 && sym->recvSize < 4) {
3624 pic16_emitcode ("mov","a,sp");
3625 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3626 pic16_emitcode ("mov","sp,a");
3629 pic16_emitcode("inc","sp");
3633 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3635 pic16_emitcode ("mov","a,_spx");
3636 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3637 pic16_emitcode ("mov","_spx,a");
3642 /*-----------------------------------------------------------------*/
3643 /* genEndFunction - generates epilogue for functions */
3644 /*-----------------------------------------------------------------*/
3645 static void genEndFunction (iCode *ic)
3647 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3651 if(IFFUNC_ISNAKED(sym->type)) {
3652 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3658 /* add code for ISCRITICAL */
3659 if(IFFUNC_ISCRITICAL(sym->type)) {
3660 /* if critical function, turn on interrupts */
3662 /* TODO: add code here -- VR */
3667 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3669 pic16_emitcode ("mov","%s,_bp",spname);
3673 /* if use external stack but some variables were
3674 added to the local stack then decrement the
3676 if (options.useXstack && sym->stack) {
3677 pic16_emitcode("mov","a,sp");
3678 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3679 pic16_emitcode("mov","sp,a");
3684 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3685 if (options.useXstack) {
3686 pic16_emitcode("mov","r0,%s",spname);
3687 pic16_emitcode("movx","a,@r0");
3688 pic16_emitcode("mov","_bp,a");
3689 pic16_emitcode("dec","%s",spname);
3693 pic16_emitcode ("pop","_bp");
3698 if (IFFUNC_ISISR(sym->type)) {
3699 /* now we need to restore the registers */
3700 /* if any registers used */
3701 if (sym->regsUsed) {
3704 /* restore registers used */
3705 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3706 for ( i = sym->regsUsed->size; i >= 0; i--) {
3707 if (bitVectBitValue(sym->regsUsed,i)) {
3709 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3710 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3711 // pic16_regWithIdx(i)->name);
3713 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3715 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3716 // &pic16_pc_preinc1,
3717 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3723 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3724 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3725 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3726 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3728 if(!(_G.interruptvector == 1)) {
3729 /* do not restore interrupt vector for WREG,STATUS,BSR
3730 * for high priority interrupt, see genFunction */
3732 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3733 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3734 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3737 _G.interruptvector = 0; /* sanity check */
3739 // pic16_pBlockConvert2ISR(pb);
3742 /* if debug then send end of function */
3743 /* if (options.debug && currFunc) */
3745 debugFile->writeEndFunction (currFunc, ic, 1);
3748 if(_G.usefastretfie)
3749 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3751 pic16_emitpcodeNULLop(POC_RETFIE);
3752 _G.usefastretfie = 0;
3754 if (IFFUNC_ISCRITICAL(sym->type))
3755 pic16_emitcode("setb","ea");
3758 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3760 /* if any registers used */
3761 if (sym->regsUsed) {
3763 /* save the registers used */
3764 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3765 for ( i = sym->regsUsed->size; i >= 0; i--) {
3766 if (bitVectBitValue(sym->regsUsed,i)) {
3768 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3769 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3770 // pic16_regWithIdx(i)->name);
3772 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3774 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3775 // &pic16_pc_preinc1,
3776 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3783 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3784 /* if debug then send end of function */
3786 debugFile->writeEndFunction (currFunc, ic, 1);
3789 /* insert code to restore stack frame, if user enabled it
3790 * and function is not main() */
3793 if(strcmp(sym->name, "main")) {
3794 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3795 /* restore stack frame */
3796 if(STACK_MODEL_LARGE)
3797 pic16_emitpcode(POC_MOVFF,
3798 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3799 pic16_emitpcode(POC_MOVFF,
3800 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3804 pic16_emitpcodeNULLop(POC_RETURN);
3806 /* Mark the end of a function */
3807 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3813 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3817 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3819 if(dest->type != PO_WREG)
3820 pic16_emitpcode(POC_MOVWF, dest);
3822 if(dest->type == PO_WREG && (offset == 0)) {
3823 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3827 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3828 pic16_popGet(AOP(op), offset), dest));
3832 /*-----------------------------------------------------------------*/
3833 /* genRet - generate code for return statement */
3834 /*-----------------------------------------------------------------*/
3835 static void genRet (iCode *ic)
3840 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3841 /* if we have no return value then
3842 * just generate the "ret" */
3847 /* we have something to return then
3848 * move the return value into place */
3849 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3850 size = AOP_SIZE(IC_LEFT(ic));
3854 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3855 // pic16_emitpcode(POC_MOVFF,
3856 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3859 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3860 // pic16_emitpcode(POC_MOVFF,
3861 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3864 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3865 // pic16_emitpcode(POC_MOVFF,
3866 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3869 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3871 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3872 // pic16_emitpcode(POC_MOVFF,
3873 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3876 /* >32-bits, setup stack and FSR0 */
3878 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3879 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3881 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3883 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3888 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3889 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3891 if(STACK_MODEL_LARGE) {
3892 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3893 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3895 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3900 /* old code, left here for reference -- VR */
3904 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3906 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3907 pic16_emitpcomment("push %s",l);
3910 DEBUGpic16_emitcode(";", "%d", __LINE__);
3911 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3912 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3914 if (strcmp(fReturn[offset],l)) {
3915 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3916 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3917 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3919 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3923 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3933 if (strcmp(fReturn[pushed],"a"))
3934 pic16_emitcode("pop",fReturn[pushed]);
3936 pic16_emitcode("pop","acc");
3942 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3945 /* generate a jump to the return label
3946 * if the next is not the return statement */
3947 if (!(ic->next && ic->next->op == LABEL
3948 && IC_LABEL(ic->next) == returnLabel)) {
3950 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3951 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3955 /*-----------------------------------------------------------------*/
3956 /* genLabel - generates a label */
3957 /*-----------------------------------------------------------------*/
3958 static void genLabel (iCode *ic)
3962 /* special case never generate */
3963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3964 if (IC_LABEL(ic) == entryLabel)
3967 pic16_emitpLabel(IC_LABEL(ic)->key);
3968 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3971 /*-----------------------------------------------------------------*/
3972 /* genGoto - generates a goto */
3973 /*-----------------------------------------------------------------*/
3975 static void genGoto (iCode *ic)
3977 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3978 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3982 /*-----------------------------------------------------------------*/
3983 /* genMultbits :- multiplication of bits */
3984 /*-----------------------------------------------------------------*/
3985 static void genMultbits (operand *left,
3989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3991 if(!pic16_sameRegs(AOP(result),AOP(right)))
3992 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3994 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3995 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3996 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4001 /*-----------------------------------------------------------------*/
4002 /* genMultOneByte : 8 bit multiplication & division */
4003 /*-----------------------------------------------------------------*/
4004 static void genMultOneByte (operand *left,
4009 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4010 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4011 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4013 /* (if two literals, the value is computed before) */
4014 /* if one literal, literal on the right */
4015 if (AOP_TYPE(left) == AOP_LIT){
4021 /* size is already checked in genMult == 1 */
4022 // size = AOP_SIZE(result);
4024 if (AOP_TYPE(right) == AOP_LIT){
4025 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4026 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4027 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4028 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4030 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4031 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4032 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4033 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4036 pic16_genMult8X8_8 (left, right,result);
4039 /*-----------------------------------------------------------------*/
4040 /* genMultOneWord : 16 bit multiplication */
4041 /*-----------------------------------------------------------------*/
4042 static void genMultOneWord (operand *left,
4047 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4048 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4049 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4051 /* (if two literals, the value is computed before)
4052 * if one literal, literal on the right */
4053 if (AOP_TYPE(left) == AOP_LIT){
4059 /* size is checked already == 2 */
4060 // size = AOP_SIZE(result);
4062 if (AOP_TYPE(right) == AOP_LIT) {
4063 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4064 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4065 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4066 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4068 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4069 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4070 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4071 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4074 pic16_genMult16X16_16(left, right,result);
4077 /*-----------------------------------------------------------------*/
4078 /* genMultOneLong : 32 bit multiplication */
4079 /*-----------------------------------------------------------------*/
4080 static void genMultOneLong (operand *left,
4085 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4086 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4087 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4089 /* (if two literals, the value is computed before)
4090 * if one literal, literal on the right */
4091 if (AOP_TYPE(left) == AOP_LIT){
4097 /* size is checked already == 4 */
4098 // size = AOP_SIZE(result);
4100 if (AOP_TYPE(right) == AOP_LIT) {
4101 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4102 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4103 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4104 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4106 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4107 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4108 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4109 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4112 pic16_genMult32X32_32(left, right,result);
4117 /*-----------------------------------------------------------------*/
4118 /* genMult - generates code for multiplication */
4119 /*-----------------------------------------------------------------*/
4120 static void genMult (iCode *ic)
4122 operand *left = IC_LEFT(ic);
4123 operand *right = IC_RIGHT(ic);
4124 operand *result= IC_RESULT(ic);
4126 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4127 /* assign the amsops */
4128 pic16_aopOp (left,ic,FALSE);
4129 pic16_aopOp (right,ic,FALSE);
4130 pic16_aopOp (result,ic,TRUE);
4132 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4134 /* special cases first *
4136 if (AOP_TYPE(left) == AOP_CRY
4137 && AOP_TYPE(right)== AOP_CRY) {
4138 genMultbits(left,right,result);
4142 /* if both are of size == 1 */
4143 if(AOP_SIZE(left) == 1
4144 && AOP_SIZE(right) == 1) {
4145 genMultOneByte(left,right,result);
4149 /* if both are of size == 2 */
4150 if(AOP_SIZE(left) == 2
4151 && AOP_SIZE(right) == 2) {
4152 genMultOneWord(left, right, result);
4156 /* if both are of size == 4 */
4157 if(AOP_SIZE(left) == 4
4158 && AOP_SIZE(right) == 4) {
4159 genMultOneLong(left, right, result);
4163 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4166 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4167 /* should have been converted to function call */
4171 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4172 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173 pic16_freeAsmop(result,NULL,ic,TRUE);
4176 /*-----------------------------------------------------------------*/
4177 /* genDivbits :- division of bits */
4178 /*-----------------------------------------------------------------*/
4179 static void genDivbits (operand *left,
4186 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4187 /* the result must be bit */
4188 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4189 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4193 pic16_emitcode("div","ab");
4194 pic16_emitcode("rrc","a");
4195 pic16_aopPut(AOP(result),"c",0);
4198 /*-----------------------------------------------------------------*/
4199 /* genDivOneByte : 8 bit division */
4200 /*-----------------------------------------------------------------*/
4201 static void genDivOneByte (operand *left,
4205 sym_link *opetype = operandType(result);
4210 /* result = divident / divisor
4211 * - divident may be a register or a literal,
4212 * - divisor may be a register or a literal,
4213 * so there are 3 cases (literal / literal is optimized
4214 * by the front-end) to handle.
4215 * In addition we must handle signed and unsigned, which
4216 * result in 6 final different cases -- VR */
4218 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4219 size = AOP_SIZE(result) - 1;
4221 /* signed or unsigned */
4222 if (SPEC_USIGN(opetype)) {
4223 pCodeOp *pct1, /* count */
4226 symbol *label1, *label2, *label3;;
4229 /* unsigned is easy */
4231 pct1 = pic16_popGetTempReg(1);
4232 pct2 = pic16_popGetTempReg(1);
4233 pct3 = pic16_popGetTempReg(1);
4235 label1 = newiTempLabel(NULL);
4236 label2 = newiTempLabel(NULL);
4237 label3 = newiTempLabel(NULL);
4239 /* the following algorithm is extracted from divuint.c */
4241 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4242 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4244 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4246 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4248 pic16_emitpLabel(label1->key);
4251 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4255 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4259 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4261 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4262 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4264 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4265 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4266 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4268 pic16_emitpLabel( label3->key );
4269 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4270 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4274 pic16_emitpLabel(label2->key);
4275 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4276 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4277 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4279 /* result is in wreg */
4280 if(AOP_TYPE(result) != AOP_ACC)
4281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4283 pic16_popReleaseTempReg( pct3, 1);
4284 pic16_popReleaseTempReg( pct2, 1);
4285 pic16_popReleaseTempReg( pct1, 1);
4290 /* signed is a little bit more difficult */
4292 /* save the signs of the operands */
4293 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4295 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4296 pic16_emitcode("push","acc"); /* save it on the stack */
4298 /* now sign adjust for both left & right */
4299 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4301 lbl = newiTempLabel(NULL);
4302 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4303 pic16_emitcode("cpl","a");
4304 pic16_emitcode("inc","a");
4305 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4306 pic16_emitcode("mov","b,a");
4308 /* sign adjust left side */
4309 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4312 lbl = newiTempLabel(NULL);
4313 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4314 pic16_emitcode("cpl","a");
4315 pic16_emitcode("inc","a");
4316 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4318 /* now the division */
4319 pic16_emitcode("div","ab");
4320 /* we are interested in the lower order
4322 pic16_emitcode("mov","b,a");
4323 lbl = newiTempLabel(NULL);
4324 pic16_emitcode("pop","acc");
4325 /* if there was an over flow we don't
4326 adjust the sign of the result */
4327 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4328 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4330 pic16_emitcode("clr","a");
4331 pic16_emitcode("subb","a,b");
4332 pic16_emitcode("mov","b,a");
4333 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4335 /* now we are done */
4336 pic16_aopPut(AOP(result),"b",0);
4338 pic16_emitcode("mov","c,b.7");
4339 pic16_emitcode("subb","a,acc");
4342 pic16_aopPut(AOP(result),"a",offset++);
4346 /*-----------------------------------------------------------------*/
4347 /* genDiv - generates code for division */
4348 /*-----------------------------------------------------------------*/
4349 static void genDiv (iCode *ic)
4351 operand *left = IC_LEFT(ic);
4352 operand *right = IC_RIGHT(ic);
4353 operand *result= IC_RESULT(ic);
4356 /* Division is a very lengthy algorithm, so it is better
4357 * to call support routines than inlining algorithm.
4358 * Division functions written here just in case someone
4359 * wants to inline and not use the support libraries -- VR */
4361 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4362 /* assign the amsops */
4363 pic16_aopOp (left,ic,FALSE);
4364 pic16_aopOp (right,ic,FALSE);
4365 pic16_aopOp (result,ic,TRUE);
4367 /* special cases first */
4369 if (AOP_TYPE(left) == AOP_CRY &&
4370 AOP_TYPE(right)== AOP_CRY) {
4371 genDivbits(left,right,result);
4375 /* if both are of size == 1 */
4376 if (AOP_SIZE(left) == 1 &&
4377 AOP_SIZE(right) == 1 ) {
4378 genDivOneByte(left,right,result);
4382 /* should have been converted to function call */
4385 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4386 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4387 pic16_freeAsmop(result,NULL,ic,TRUE);
4390 /*-----------------------------------------------------------------*/
4391 /* genModbits :- modulus of bits */
4392 /*-----------------------------------------------------------------*/
4393 static void genModbits (operand *left,
4400 /* the result must be bit */
4401 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4402 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4406 pic16_emitcode("div","ab");
4407 pic16_emitcode("mov","a,b");
4408 pic16_emitcode("rrc","a");
4409 pic16_aopPut(AOP(result),"c",0);
4412 /*-----------------------------------------------------------------*/
4413 /* genModOneByte : 8 bit modulus */
4414 /*-----------------------------------------------------------------*/
4415 static void genModOneByte (operand *left,
4419 sym_link *opetype = operandType(result);
4423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4424 /* signed or unsigned */
4425 if (SPEC_USIGN(opetype)) {
4426 /* unsigned is easy */
4427 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4428 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4430 pic16_emitcode("div","ab");
4431 pic16_aopPut(AOP(result),"b",0);
4435 /* signed is a little bit more difficult */
4437 /* save the signs of the operands */
4438 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4441 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4442 pic16_emitcode("push","acc"); /* save it on the stack */
4444 /* now sign adjust for both left & right */
4445 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4448 lbl = newiTempLabel(NULL);
4449 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4450 pic16_emitcode("cpl","a");
4451 pic16_emitcode("inc","a");
4452 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4453 pic16_emitcode("mov","b,a");
4455 /* sign adjust left side */
4456 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4459 lbl = newiTempLabel(NULL);
4460 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4461 pic16_emitcode("cpl","a");
4462 pic16_emitcode("inc","a");
4463 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4465 /* now the multiplication */
4466 pic16_emitcode("div","ab");
4467 /* we are interested in the lower order
4469 lbl = newiTempLabel(NULL);
4470 pic16_emitcode("pop","acc");
4471 /* if there was an over flow we don't
4472 adjust the sign of the result */
4473 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4474 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4476 pic16_emitcode("clr","a");
4477 pic16_emitcode("subb","a,b");
4478 pic16_emitcode("mov","b,a");
4479 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4481 /* now we are done */
4482 pic16_aopPut(AOP(result),"b",0);
4486 /*-----------------------------------------------------------------*/
4487 /* genMod - generates code for division */
4488 /*-----------------------------------------------------------------*/
4489 static void genMod (iCode *ic)
4491 operand *left = IC_LEFT(ic);
4492 operand *right = IC_RIGHT(ic);
4493 operand *result= IC_RESULT(ic);
4495 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4496 /* assign the amsops */
4497 pic16_aopOp (left,ic,FALSE);
4498 pic16_aopOp (right,ic,FALSE);
4499 pic16_aopOp (result,ic,TRUE);
4501 /* special cases first */
4503 if (AOP_TYPE(left) == AOP_CRY &&
4504 AOP_TYPE(right)== AOP_CRY) {
4505 genModbits(left,right,result);
4509 /* if both are of size == 1 */
4510 if (AOP_SIZE(left) == 1 &&
4511 AOP_SIZE(right) == 1 ) {
4512 genModOneByte(left,right,result);
4516 /* should have been converted to function call */
4520 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4521 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4522 pic16_freeAsmop(result,NULL,ic,TRUE);
4525 /*-----------------------------------------------------------------*/
4526 /* genIfxJump :- will create a jump depending on the ifx */
4527 /*-----------------------------------------------------------------*/
4529 note: May need to add parameter to indicate when a variable is in bit space.
4531 static void genIfxJump (iCode *ic, char *jval)
4534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4535 /* if true label then we jump if condition
4537 if ( IC_TRUE(ic) ) {
4539 if(strcmp(jval,"a") == 0)
4541 else if (strcmp(jval,"c") == 0)
4544 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4545 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4548 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4549 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4553 /* false label is present */
4554 if(strcmp(jval,"a") == 0)
4556 else if (strcmp(jval,"c") == 0)
4559 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4560 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4563 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4564 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4569 /* mark the icode as generated */
4576 /*-----------------------------------------------------------------*/
4578 /*-----------------------------------------------------------------*/
4579 static void genSkip(iCode *ifx,int status_bit)
4581 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4585 if ( IC_TRUE(ifx) ) {
4586 switch(status_bit) {
4601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4602 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4606 switch(status_bit) {
4620 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4621 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4628 /*-----------------------------------------------------------------*/
4630 /*-----------------------------------------------------------------*/
4631 static void genSkipc(resolvedIfx *rifx)
4633 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4643 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4644 rifx->generated = 1;
4647 /*-----------------------------------------------------------------*/
4649 /*-----------------------------------------------------------------*/
4650 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4652 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4657 if( (rifx->condition ^ invert_condition) & 1)
4662 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4663 rifx->generated = 1;
4667 /*-----------------------------------------------------------------*/
4669 /*-----------------------------------------------------------------*/
4670 static void genSkipz(iCode *ifx, int condition)
4681 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4683 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4686 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4688 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4693 /*-----------------------------------------------------------------*/
4695 /*-----------------------------------------------------------------*/
4696 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4702 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4704 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4707 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4708 rifx->generated = 1;
4712 /*-----------------------------------------------------------------*/
4713 /* genChkZeroes :- greater or less than comparison */
4714 /* For each byte in a literal that is zero, inclusive or the */
4715 /* the corresponding byte in the operand with W */
4716 /* returns true if any of the bytes are zero */
4717 /*-----------------------------------------------------------------*/
4718 static int genChkZeroes(operand *op, int lit, int size)
4725 i = (lit >> (size*8)) & 0xff;
4729 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4731 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4740 /*-----------------------------------------------------------------*/
4741 /* genCmp :- greater or less than comparison */
4742 /*-----------------------------------------------------------------*/
4743 static void genCmp (operand *left,operand *right,
4744 operand *result, iCode *ifx, int sign)
4746 int size; //, offset = 0 ;
4747 unsigned long lit = 0L,i = 0;
4748 resolvedIfx rFalseIfx;
4749 // resolvedIfx rTrueIfx;
4751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4754 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4755 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4759 resolveIfx(&rFalseIfx,ifx);
4760 truelbl = newiTempLabel(NULL);
4761 size = max(AOP_SIZE(left),AOP_SIZE(right));
4763 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4767 /* if literal is on the right then swap with left */
4768 if ((AOP_TYPE(right) == AOP_LIT)) {
4769 operand *tmp = right ;
4770 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4771 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4774 lit = (lit - 1) & mask;
4777 rFalseIfx.condition ^= 1;
4780 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4781 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4785 //if(IC_TRUE(ifx) == NULL)
4786 /* if left & right are bit variables */
4787 if (AOP_TYPE(left) == AOP_CRY &&
4788 AOP_TYPE(right) == AOP_CRY ) {
4789 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4790 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4792 /* subtract right from left if at the
4793 end the carry flag is set then we know that
4794 left is greater than right */
4796 symbol *lbl = newiTempLabel(NULL);
4799 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4800 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4804 if(AOP_TYPE(right) == AOP_LIT) {
4806 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4808 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4815 genSkipCond(&rFalseIfx,left,size-1,7);
4817 /* no need to compare to 0...*/
4818 /* NOTE: this is a de-generate compare that most certainly
4819 * creates some dead code. */
4820 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4822 if(ifx) ifx->generated = 1;
4829 //i = (lit >> (size*8)) & 0xff;
4830 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4834 i = ((0-lit) & 0xff);
4837 /* lit is 0x7f, all signed chars are less than
4838 * this except for 0x7f itself */
4839 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4840 genSkipz2(&rFalseIfx,0);
4842 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4843 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4844 genSkipc(&rFalseIfx);
4849 genSkipz2(&rFalseIfx,1);
4851 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4852 genSkipc(&rFalseIfx);
4856 if(ifx) ifx->generated = 1;
4860 /* chars are out of the way. now do ints and longs */
4863 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4870 genSkipCond(&rFalseIfx,left,size,7);
4871 if(ifx) ifx->generated = 1;
4876 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4878 //rFalseIfx.condition ^= 1;
4879 //genSkipCond(&rFalseIfx,left,size,7);
4880 //rFalseIfx.condition ^= 1;
4882 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4883 if(rFalseIfx.condition)
4884 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4886 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4888 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4889 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4890 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4893 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4895 if(rFalseIfx.condition) {
4897 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4903 genSkipc(&rFalseIfx);
4904 pic16_emitpLabel(truelbl->key);
4905 if(ifx) ifx->generated = 1;
4912 if( (lit & 0xff) == 0) {
4913 /* lower byte is zero */
4914 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4915 i = ((lit >> 8) & 0xff) ^0x80;
4916 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4917 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4918 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4919 genSkipc(&rFalseIfx);
4922 if(ifx) ifx->generated = 1;
4927 /* Special cases for signed longs */
4928 if( (lit & 0xffffff) == 0) {
4929 /* lower byte is zero */
4930 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4931 i = ((lit >> 8*3) & 0xff) ^0x80;
4932 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4933 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4934 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4935 genSkipc(&rFalseIfx);
4938 if(ifx) ifx->generated = 1;
4946 if(lit & (0x80 << (size*8))) {
4947 /* lit is negative */
4948 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4950 //genSkipCond(&rFalseIfx,left,size,7);
4952 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4954 if(rFalseIfx.condition)
4955 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4957 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4961 /* lit is positive */
4962 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4963 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4964 if(rFalseIfx.condition)
4965 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4967 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4972 This works, but is only good for ints.
4973 It also requires a "known zero" register.
4974 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4975 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4976 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4977 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4978 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4979 genSkipc(&rFalseIfx);
4981 pic16_emitpLabel(truelbl->key);
4982 if(ifx) ifx->generated = 1;
4986 /* There are no more special cases, so perform a general compare */
4988 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4989 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4995 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4997 //rFalseIfx.condition ^= 1;
4998 genSkipc(&rFalseIfx);
5000 pic16_emitpLabel(truelbl->key);
5002 if(ifx) ifx->generated = 1;
5009 /* sign is out of the way. So now do an unsigned compare */
5010 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5013 /* General case - compare to an unsigned literal on the right.*/
5015 i = (lit >> (size*8)) & 0xff;
5016 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5017 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5019 i = (lit >> (size*8)) & 0xff;
5022 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5024 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5026 /* this byte of the lit is zero,
5027 *if it's not the last then OR in the variable */
5029 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5034 pic16_emitpLabel(lbl->key);
5035 // pic16_emitpLabel(truelbl->key);
5036 //if(emitFinalCheck)
5037 genSkipc(&rFalseIfx);
5039 pic16_emitpLabel(truelbl->key);
5041 if(ifx) ifx->generated = 1;
5048 if(AOP_TYPE(left) == AOP_LIT) {
5049 //symbol *lbl = newiTempLabel(NULL);
5051 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5054 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5057 if((lit == 0) && (sign == 0)){
5060 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5062 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5064 genSkipz2(&rFalseIfx,0);
5065 if(ifx) ifx->generated = 1;
5072 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5073 /* degenerate compare can never be true */
5074 if(rFalseIfx.condition == 0)
5075 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5077 if(ifx) ifx->generated = 1;
5082 /* signed comparisons to a literal byte */
5084 int lp1 = (lit+1) & 0xff;
5086 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5089 rFalseIfx.condition ^= 1;
5090 genSkipCond(&rFalseIfx,right,0,7);
5093 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5094 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5095 genSkipz2(&rFalseIfx,1);
5098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5099 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5100 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5101 rFalseIfx.condition ^= 1;
5102 genSkipc(&rFalseIfx);
5106 /* unsigned comparisons to a literal byte */
5108 switch(lit & 0xff ) {
5110 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5111 genSkipz2(&rFalseIfx,0);
5114 rFalseIfx.condition ^= 1;
5115 genSkipCond(&rFalseIfx,right,0,7);
5119 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5120 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5122 rFalseIfx.condition ^= 1;
5123 if (AOP_TYPE(result) == AOP_CRY)
5124 genSkipc(&rFalseIfx);
5126 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5127 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5133 if(ifx) ifx->generated = 1;
5134 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5140 /* Size is greater than 1 */
5148 /* this means lit = 0xffffffff, or -1 */
5151 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5152 rFalseIfx.condition ^= 1;
5153 genSkipCond(&rFalseIfx,right,size,7);
5154 if(ifx) ifx->generated = 1;
5161 if(rFalseIfx.condition) {
5162 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5163 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5166 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5168 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5172 if(rFalseIfx.condition) {
5173 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5174 pic16_emitpLabel(truelbl->key);
5176 rFalseIfx.condition ^= 1;
5177 genSkipCond(&rFalseIfx,right,s,7);
5180 if(ifx) ifx->generated = 1;
5184 if((size == 1) && (0 == (lp1&0xff))) {
5185 /* lower byte of signed word is zero */
5186 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5187 i = ((lp1 >> 8) & 0xff) ^0x80;
5188 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5189 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5190 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5191 rFalseIfx.condition ^= 1;
5192 genSkipc(&rFalseIfx);
5195 if(ifx) ifx->generated = 1;
5199 if(lit & (0x80 << (size*8))) {
5200 /* Lit is less than zero */
5201 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5202 //rFalseIfx.condition ^= 1;
5203 //genSkipCond(&rFalseIfx,left,size,7);
5204 //rFalseIfx.condition ^= 1;
5205 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5206 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5208 if(rFalseIfx.condition)
5209 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5211 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5215 /* Lit is greater than or equal to zero */
5216 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5217 //rFalseIfx.condition ^= 1;
5218 //genSkipCond(&rFalseIfx,right,size,7);
5219 //rFalseIfx.condition ^= 1;
5221 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5222 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5224 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5225 if(rFalseIfx.condition)
5226 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5228 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5233 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5234 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5238 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5240 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5242 rFalseIfx.condition ^= 1;
5243 //rFalseIfx.condition = 1;
5244 genSkipc(&rFalseIfx);
5246 pic16_emitpLabel(truelbl->key);
5248 if(ifx) ifx->generated = 1;
5253 /* compare word or long to an unsigned literal on the right.*/
5258 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5261 break; /* handled above */
5264 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5266 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5267 genSkipz2(&rFalseIfx,0);
5271 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5273 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5276 if(rFalseIfx.condition)
5277 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5279 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5282 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5283 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5285 rFalseIfx.condition ^= 1;
5286 genSkipc(&rFalseIfx);
5289 pic16_emitpLabel(truelbl->key);
5291 if(ifx) ifx->generated = 1;
5297 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5298 i = (lit >> (size*8)) & 0xff;
5300 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5301 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5304 i = (lit >> (size*8)) & 0xff;
5307 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5309 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5311 /* this byte of the lit is zero,
5312 * if it's not the last then OR in the variable */
5314 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5319 pic16_emitpLabel(lbl->key);
5321 rFalseIfx.condition ^= 1;
5323 genSkipc(&rFalseIfx);
5327 pic16_emitpLabel(truelbl->key);
5328 if(ifx) ifx->generated = 1;
5332 /* Compare two variables */
5334 DEBUGpic16_emitcode(";sign","%d",sign);
5338 /* Sigh. thus sucks... */
5342 pctemp = pic16_popGetTempReg(1);
5343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5344 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5346 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5347 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5348 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5349 pic16_popReleaseTempReg(pctemp, 1);
5351 /* Signed char comparison */
5352 /* Special thanks to Nikolai Golovchenko for this snippet */
5353 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5354 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5355 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5356 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5357 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5358 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5360 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5361 genSkipc(&rFalseIfx);
5363 if(ifx) ifx->generated = 1;
5369 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5370 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374 /* The rest of the bytes of a multi-byte compare */
5378 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5381 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5382 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5387 pic16_emitpLabel(lbl->key);
5389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5390 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5391 (AOP_TYPE(result) == AOP_REG)) {
5392 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5393 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5395 genSkipc(&rFalseIfx);
5397 //genSkipc(&rFalseIfx);
5398 if(ifx) ifx->generated = 1;
5405 if ((AOP_TYPE(result) != AOP_CRY)
5406 && AOP_SIZE(result)) {
5407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5409 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5411 pic16_outBitC(result);
5413 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5414 /* if the result is used in the next
5415 ifx conditional branch then generate
5416 code a little differently */
5418 genIfxJump (ifx,"c");
5420 pic16_outBitC(result);
5421 /* leave the result in acc */
5426 /*-----------------------------------------------------------------*/
5427 /* genCmpGt :- greater than comparison */
5428 /*-----------------------------------------------------------------*/
5429 static void genCmpGt (iCode *ic, iCode *ifx)
5431 operand *left, *right, *result;
5432 sym_link *letype , *retype;
5435 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5437 right= IC_RIGHT(ic);
5438 result = IC_RESULT(ic);
5440 letype = getSpec(operandType(left));
5441 retype =getSpec(operandType(right));
5442 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5443 /* assign the amsops */
5444 pic16_aopOp (left,ic,FALSE);
5445 pic16_aopOp (right,ic,FALSE);
5446 pic16_aopOp (result,ic,TRUE);
5448 genCmp(right, left, result, ifx, sign);
5450 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5451 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5452 pic16_freeAsmop(result,NULL,ic,TRUE);
5455 /*-----------------------------------------------------------------*/
5456 /* genCmpLt - less than comparisons */
5457 /*-----------------------------------------------------------------*/
5458 static void genCmpLt (iCode *ic, iCode *ifx)
5460 operand *left, *right, *result;
5461 sym_link *letype , *retype;
5464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5466 right= IC_RIGHT(ic);
5467 result = IC_RESULT(ic);
5469 letype = getSpec(operandType(left));
5470 retype =getSpec(operandType(right));
5471 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5473 /* assign the amsops */
5474 pic16_aopOp (left,ic,FALSE);
5475 pic16_aopOp (right,ic,FALSE);
5476 pic16_aopOp (result,ic,TRUE);
5478 genCmp(left, right, result, ifx, sign);
5480 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5481 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5482 pic16_freeAsmop(result,NULL,ic,TRUE);
5487 // FIXME reenable literal optimisation when the pic16 port is stable
5489 /*-----------------------------------------------------------------*/
5490 /* genc16bit2lit - compare a 16 bit value to a literal */
5491 /*-----------------------------------------------------------------*/
5492 static void genc16bit2lit(operand *op, int lit, int offset)
5496 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5497 if( (lit&0xff) == 0)
5502 switch( BYTEofLONG(lit,i)) {
5504 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5507 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5510 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5513 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5514 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5519 switch( BYTEofLONG(lit,i)) {
5521 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5525 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5529 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5532 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5534 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5543 /*-----------------------------------------------------------------*/
5544 /* gencjneshort - compare and jump if not equal */
5545 /*-----------------------------------------------------------------*/
5546 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5548 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5550 int res_offset = 0; /* the result may be a different size then left or right */
5551 int res_size = AOP_SIZE(result);
5553 symbol *lbl, *lbl_done;
5555 unsigned long lit = 0L;
5556 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5559 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5561 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5562 resolveIfx(&rIfx,ifx);
5563 lbl = newiTempLabel(NULL);
5564 lbl_done = newiTempLabel(NULL);
5567 /* if the left side is a literal or
5568 if the right is in a pointer register and left
5570 if ((AOP_TYPE(left) == AOP_LIT) ||
5571 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5576 if(AOP_TYPE(right) == AOP_LIT)
5577 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5579 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5580 preserve_result = 1;
5582 if(result && !preserve_result)
5585 for(i = 0; i < AOP_SIZE(result); i++)
5586 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5590 /* if the right side is a literal then anything goes */
5591 if (AOP_TYPE(right) == AOP_LIT &&
5592 AOP_TYPE(left) != AOP_DIR ) {
5595 genc16bit2lit(left, lit, 0);
5597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5603 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5604 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5606 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5610 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5612 if(res_offset < res_size-1)
5620 /* if the right side is in a register or in direct space or
5621 if the left is a pointer register & right is not */
5622 else if (AOP_TYPE(right) == AOP_REG ||
5623 AOP_TYPE(right) == AOP_DIR ||
5624 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5625 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5626 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5627 int lbl_key = lbl->key;
5630 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5631 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5633 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5634 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5635 __FUNCTION__,__LINE__);
5639 /* switch(size) { */
5641 /* genc16bit2lit(left, lit, 0); */
5643 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5648 if((AOP_TYPE(left) == AOP_DIR) &&
5649 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5651 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5652 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5654 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5656 switch (lit & 0xff) {
5658 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5661 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5662 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5667 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5668 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5669 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5670 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5675 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5680 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5683 if(AOP_TYPE(result) == AOP_CRY) {
5684 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5691 /* fix me. probably need to check result size too */
5692 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5698 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5705 if(res_offset < res_size-1)
5710 } else if(AOP_TYPE(right) == AOP_REG &&
5711 AOP_TYPE(left) != AOP_DIR){
5714 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5715 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5716 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5721 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5723 if(res_offset < res_size-1)
5728 /* right is a pointer reg need both a & b */
5730 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5732 pic16_emitcode("mov","b,%s",l);
5733 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5734 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5739 if(result && preserve_result)
5742 for(i = 0; i < AOP_SIZE(result); i++)
5743 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5746 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5748 if(result && preserve_result)
5749 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5752 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5754 pic16_emitpLabel(lbl->key);
5756 if(result && preserve_result)
5759 for(i = 0; i < AOP_SIZE(result); i++)
5760 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5762 pic16_emitpLabel(lbl_done->key);
5765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5773 /*-----------------------------------------------------------------*/
5774 /* gencjne - compare and jump if not equal */
5775 /*-----------------------------------------------------------------*/
5776 static void gencjne(operand *left, operand *right, iCode *ifx)
5778 symbol *tlbl = newiTempLabel(NULL);
5780 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5781 gencjneshort(left, right, lbl);
5783 pic16_emitcode("mov","a,%s",one);
5784 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5785 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5786 pic16_emitcode("clr","a");
5787 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5789 pic16_emitpLabel(lbl->key);
5790 pic16_emitpLabel(tlbl->key);
5796 /*-----------------------------------------------------------------*/
5797 /* is_LitOp - check if operand has to be treated as literal */
5798 /*-----------------------------------------------------------------*/
5799 static bool is_LitOp(operand *op)
5801 return (AOP_TYPE(op) == AOP_LIT)
5802 || ( (AOP_TYPE(op) == AOP_PCODE)
5803 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5804 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5807 /*-----------------------------------------------------------------*/
5808 /* is_LitAOp - check if operand has to be treated as literal */
5809 /*-----------------------------------------------------------------*/
5810 static bool is_LitAOp(asmop *aop)
5812 return (aop->type == AOP_LIT)
5813 || ( (aop->type == AOP_PCODE)
5814 && ( (aop->aopu.pcop->type == PO_LITERAL)
5815 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5820 /*-----------------------------------------------------------------*/
5821 /* genCmpEq - generates code for equal to */
5822 /*-----------------------------------------------------------------*/
5823 static void genCmpEq (iCode *ic, iCode *ifx)
5825 operand *left, *right, *result;
5826 symbol *falselbl = newiTempLabel(NULL);
5827 symbol *donelbl = newiTempLabel(NULL);
5829 int preserve_result = 0;
5830 int generate_result = 0;
5833 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5834 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5835 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5838 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5840 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5842 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5843 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5847 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5849 operand *tmp = right ;
5854 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5855 preserve_result = 1;
5857 if(result && AOP_SIZE(result))
5858 generate_result = 1;
5860 if(generate_result && !preserve_result)
5862 for(i = 0; i < AOP_SIZE(result); i++)
5863 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5866 for(i=0; i < AOP_SIZE(left); i++)
5868 if(AOP_TYPE(left) != AOP_ACC)
5871 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5873 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5876 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5878 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5880 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5885 if(generate_result && preserve_result)
5887 for(i = 0; i < AOP_SIZE(result); i++)
5888 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5892 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5894 if(generate_result && preserve_result)
5895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5897 if(ifx && IC_TRUE(ifx))
5898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5900 if(ifx && IC_FALSE(ifx))
5901 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5903 pic16_emitpLabel(falselbl->key);
5907 if(ifx && IC_FALSE(ifx))
5908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5910 if(generate_result && preserve_result)
5912 for(i = 0; i < AOP_SIZE(result); i++)
5913 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5916 pic16_emitpLabel(donelbl->key);
5922 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5923 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5924 pic16_freeAsmop(result,NULL,ic,TRUE);
5930 // old version kept for reference
5932 /*-----------------------------------------------------------------*/
5933 /* genCmpEq - generates code for equal to */
5934 /*-----------------------------------------------------------------*/
5935 static void genCmpEq (iCode *ic, iCode *ifx)
5937 operand *left, *right, *result;
5938 unsigned long lit = 0L;
5940 symbol *falselbl = newiTempLabel(NULL);
5943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5946 DEBUGpic16_emitcode ("; ifx is non-null","");
5948 DEBUGpic16_emitcode ("; ifx is null","");
5950 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5951 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5952 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5954 size = max(AOP_SIZE(left),AOP_SIZE(right));
5956 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5958 /* if literal, literal on the right or
5959 if the right is in a pointer register and left
5961 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5962 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5963 operand *tmp = right ;
5969 if(ifx && !AOP_SIZE(result)){
5971 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5972 /* if they are both bit variables */
5973 if (AOP_TYPE(left) == AOP_CRY &&
5974 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5975 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5976 if(AOP_TYPE(right) == AOP_LIT){
5977 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5979 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5980 pic16_emitcode("cpl","c");
5981 } else if(lit == 1L) {
5982 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5984 pic16_emitcode("clr","c");
5986 /* AOP_TYPE(right) == AOP_CRY */
5988 symbol *lbl = newiTempLabel(NULL);
5989 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5990 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5991 pic16_emitcode("cpl","c");
5992 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5994 /* if true label then we jump if condition
5996 tlbl = newiTempLabel(NULL);
5997 if ( IC_TRUE(ifx) ) {
5998 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5999 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6001 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6002 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6004 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6007 /* left and right are both bit variables, result is carry */
6010 resolveIfx(&rIfx,ifx);
6012 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6013 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6014 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6015 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6020 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6022 /* They're not both bit variables. Is the right a literal? */
6023 if(AOP_TYPE(right) == AOP_LIT) {
6024 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6029 switch(lit & 0xff) {
6031 if ( IC_TRUE(ifx) ) {
6032 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6034 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6036 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6037 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6041 if ( IC_TRUE(ifx) ) {
6042 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6044 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6046 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6047 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6051 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6053 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6058 /* end of size == 1 */
6062 genc16bit2lit(left,lit,offset);
6065 /* end of size == 2 */
6070 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6071 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6072 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6073 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6076 /* search for patterns that can be optimized */
6078 genc16bit2lit(left,lit,0);
6082 emitSKPZ; // if hi word unequal
6084 emitSKPNZ; // if hi word equal
6086 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6087 genc16bit2lit(left,lit,2);
6090 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6091 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6095 pic16_emitpLabel(falselbl->key);
6104 } else if(AOP_TYPE(right) == AOP_CRY ) {
6105 /* we know the left is not a bit, but that the right is */
6106 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6107 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6108 pic16_popGet(AOP(right),offset));
6109 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6111 /* if the two are equal, then W will be 0 and the Z bit is set
6112 * we could test Z now, or go ahead and check the high order bytes if
6113 * the variable we're comparing is larger than a byte. */
6116 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6118 if ( IC_TRUE(ifx) ) {
6120 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6121 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6124 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6125 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6129 /* They're both variables that are larger than bits */
6132 tlbl = newiTempLabel(NULL);
6135 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6136 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6138 if ( IC_TRUE(ifx) ) {
6142 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6144 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6145 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6149 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6152 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6153 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6158 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6160 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6161 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6165 if(s>1 && IC_TRUE(ifx)) {
6166 pic16_emitpLabel(tlbl->key);
6167 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6171 /* mark the icode as generated */
6176 /* if they are both bit variables */
6177 if (AOP_TYPE(left) == AOP_CRY &&
6178 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6179 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6180 if(AOP_TYPE(right) == AOP_LIT){
6181 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6183 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6184 pic16_emitcode("cpl","c");
6185 } else if(lit == 1L) {
6186 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6188 pic16_emitcode("clr","c");
6190 /* AOP_TYPE(right) == AOP_CRY */
6192 symbol *lbl = newiTempLabel(NULL);
6193 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6194 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6195 pic16_emitcode("cpl","c");
6196 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6199 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6200 pic16_outBitC(result);
6204 genIfxJump (ifx,"c");
6207 /* if the result is used in an arithmetic operation
6208 then put the result in place */
6209 pic16_outBitC(result);
6212 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6213 gencjne(left,right,result,ifx);
6216 gencjne(left,right,newiTempLabel(NULL));
6218 if(IC_TRUE(ifx)->key)
6219 gencjne(left,right,IC_TRUE(ifx)->key);
6221 gencjne(left,right,IC_FALSE(ifx)->key);
6225 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6226 pic16_aopPut(AOP(result),"a",0);
6231 genIfxJump (ifx,"a");
6235 /* if the result is used in an arithmetic operation
6236 then put the result in place */
6238 if (AOP_TYPE(result) != AOP_CRY)
6239 pic16_outAcc(result);
6241 /* leave the result in acc */
6245 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6246 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6247 pic16_freeAsmop(result,NULL,ic,TRUE);
6251 /*-----------------------------------------------------------------*/
6252 /* ifxForOp - returns the icode containing the ifx for operand */
6253 /*-----------------------------------------------------------------*/
6254 static iCode *ifxForOp ( operand *op, iCode *ic )
6256 /* if true symbol then needs to be assigned */
6257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6258 if (IS_TRUE_SYMOP(op))
6261 /* if this has register type condition and
6262 the next instruction is ifx with the same operand
6263 and live to of the operand is upto the ifx only then */
6265 && ic->next->op == IFX
6266 && IC_COND(ic->next)->key == op->key
6267 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6269 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6274 ic->next->op == IFX &&
6275 IC_COND(ic->next)->key == op->key) {
6276 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6280 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6282 ic->next->op == IFX)
6283 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6286 ic->next->op == IFX &&
6287 IC_COND(ic->next)->key == op->key) {
6288 DEBUGpic16_emitcode ("; "," key is okay");
6289 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6290 OP_SYMBOL(op)->liveTo,
6295 /* the code below is completely untested
6296 * it just allows ulong2fs.c compile -- VR */
6299 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6300 __FILE__, __FUNCTION__, __LINE__);
6302 /* if this has register type condition and
6303 the next instruction is ifx with the same operand
6304 and live to of the operand is upto the ifx only then */
6306 ic->next->op == IFX &&
6307 IC_COND(ic->next)->key == op->key &&
6308 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6312 ic->next->op == IFX &&
6313 IC_COND(ic->next)->key == op->key) {
6314 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6318 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6319 __FILE__, __FUNCTION__, __LINE__);
6321 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6326 /*-----------------------------------------------------------------*/
6327 /* genAndOp - for && operation */
6328 /*-----------------------------------------------------------------*/
6329 static void genAndOp (iCode *ic)
6331 operand *left,*right, *result;
6334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6335 /* note here that && operations that are in an
6336 if statement are taken away by backPatchLabels
6337 only those used in arthmetic operations remain */
6338 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6339 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6340 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6342 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6344 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6345 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6346 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6348 /* if both are bit variables */
6349 /* if (AOP_TYPE(left) == AOP_CRY && */
6350 /* AOP_TYPE(right) == AOP_CRY ) { */
6351 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6352 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6353 /* pic16_outBitC(result); */
6355 /* tlbl = newiTempLabel(NULL); */
6356 /* pic16_toBoolean(left); */
6357 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6358 /* pic16_toBoolean(right); */
6359 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6360 /* pic16_outBitAcc(result); */
6363 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6364 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6365 pic16_freeAsmop(result,NULL,ic,TRUE);
6369 /*-----------------------------------------------------------------*/
6370 /* genOrOp - for || operation */
6371 /*-----------------------------------------------------------------*/
6374 modified this code, but it doesn't appear to ever get called
6377 static void genOrOp (iCode *ic)
6379 operand *left,*right, *result;
6382 /* note here that || operations that are in an
6383 if statement are taken away by backPatchLabels
6384 only those used in arthmetic operations remain */
6385 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6386 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6387 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6388 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6390 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6392 /* if both are bit variables */
6393 if (AOP_TYPE(left) == AOP_CRY &&
6394 AOP_TYPE(right) == AOP_CRY ) {
6395 pic16_emitcode("clrc","");
6396 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6397 AOP(left)->aopu.aop_dir,
6398 AOP(left)->aopu.aop_dir);
6399 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6400 AOP(right)->aopu.aop_dir,
6401 AOP(right)->aopu.aop_dir);
6402 pic16_emitcode("setc","");
6405 tlbl = newiTempLabel(NULL);
6406 pic16_toBoolean(left);
6408 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6409 pic16_toBoolean(right);
6410 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6412 pic16_outBitAcc(result);
6415 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6416 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6417 pic16_freeAsmop(result,NULL,ic,TRUE);
6420 /*-----------------------------------------------------------------*/
6421 /* isLiteralBit - test if lit == 2^n */
6422 /*-----------------------------------------------------------------*/
6423 static int isLiteralBit(unsigned long lit)
6425 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6426 0x100L,0x200L,0x400L,0x800L,
6427 0x1000L,0x2000L,0x4000L,0x8000L,
6428 0x10000L,0x20000L,0x40000L,0x80000L,
6429 0x100000L,0x200000L,0x400000L,0x800000L,
6430 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6431 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6435 for(idx = 0; idx < 32; idx++)
6441 /*-----------------------------------------------------------------*/
6442 /* continueIfTrue - */
6443 /*-----------------------------------------------------------------*/
6444 static void continueIfTrue (iCode *ic)
6446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6448 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6452 /*-----------------------------------------------------------------*/
6454 /*-----------------------------------------------------------------*/
6455 static void jumpIfTrue (iCode *ic)
6457 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6459 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6463 /*-----------------------------------------------------------------*/
6464 /* jmpTrueOrFalse - */
6465 /*-----------------------------------------------------------------*/
6466 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6468 // ugly but optimized by peephole
6469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6471 symbol *nlbl = newiTempLabel(NULL);
6472 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6473 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6474 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6475 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6478 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6479 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6484 /*-----------------------------------------------------------------*/
6485 /* genAnd - code for and */
6486 /*-----------------------------------------------------------------*/
6487 static void genAnd (iCode *ic, iCode *ifx)
6489 operand *left, *right, *result;
6491 unsigned long lit = 0L;
6496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6497 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6498 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6499 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6501 resolveIfx(&rIfx,ifx);
6503 /* if left is a literal & right is not then exchange them */
6504 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6505 AOP_NEEDSACC(left)) {
6506 operand *tmp = right ;
6511 /* if result = right then exchange them */
6512 if(pic16_sameRegs(AOP(result),AOP(right))){
6513 operand *tmp = right ;
6518 /* if right is bit then exchange them */
6519 if (AOP_TYPE(right) == AOP_CRY &&
6520 AOP_TYPE(left) != AOP_CRY){
6521 operand *tmp = right ;
6525 if(AOP_TYPE(right) == AOP_LIT)
6526 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6528 size = AOP_SIZE(result);
6530 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6533 // result = bit & yy;
6534 if (AOP_TYPE(left) == AOP_CRY){
6535 // c = bit & literal;
6536 if(AOP_TYPE(right) == AOP_LIT){
6538 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6541 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6544 if(size && (AOP_TYPE(result) == AOP_CRY)){
6545 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6548 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6552 pic16_emitcode("clr","c");
6555 if (AOP_TYPE(right) == AOP_CRY){
6557 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6558 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6561 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6563 pic16_emitcode("rrc","a");
6564 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6570 pic16_outBitC(result);
6572 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6573 genIfxJump(ifx, "c");
6577 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6578 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6579 if((AOP_TYPE(right) == AOP_LIT) &&
6580 (AOP_TYPE(result) == AOP_CRY) &&
6581 (AOP_TYPE(left) != AOP_CRY)){
6582 int posbit = isLiteralBit(lit);
6586 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6589 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6595 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6596 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6598 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6599 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6602 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6603 size = AOP_SIZE(left);
6606 int bp = posbit, ofs=0;
6613 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6614 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6618 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6619 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6621 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6628 symbol *tlbl = newiTempLabel(NULL);
6629 int sizel = AOP_SIZE(left);
6635 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6637 /* patch provided by Aaron Colwell */
6638 if((posbit = isLiteralBit(bytelit)) != 0) {
6639 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6640 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
6641 (posbit-1),0, PO_GPR_REGISTER));
6643 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6644 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6646 if (bytelit == 0xff) {
6647 /* Aaron had a MOVF instruction here, changed to MOVFW cause
6648 * a peephole could optimize it out -- VR */
6649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6651 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6652 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6655 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6656 pic16_popGetLabel(tlbl->key));
6660 /* old code, left here for reference -- VR 09/2004 */
6661 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6663 if((posbit = isLiteralBit(bytelit)) != 0)
6664 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6666 if(bytelit != 0x0FFL)
6667 pic16_emitcode("anl","a,%s",
6668 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6669 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6675 // bit = left & literal
6678 pic16_emitpLabel(tlbl->key);
6680 // if(left & literal)
6683 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6684 pic16_emitpLabel(tlbl->key);
6691 pic16_outBitC(result);
6695 /* if left is same as result */
6696 if(pic16_sameRegs(AOP(result),AOP(left))){
6698 for(;size--; offset++,lit>>=8) {
6699 if(AOP_TYPE(right) == AOP_LIT){
6700 switch(lit & 0xff) {
6702 /* and'ing with 0 has clears the result */
6703 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6704 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6707 /* and'ing with 0xff is a nop when the result and left are the same */
6712 int p = my_powof2( (~lit) & 0xff );
6714 /* only one bit is set in the literal, so use a bcf instruction */
6715 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6716 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6719 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6720 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6721 if(know_W != (lit&0xff))
6722 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6724 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6729 if (AOP_TYPE(left) == AOP_ACC) {
6730 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6732 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6733 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6740 // left & result in different registers
6741 if(AOP_TYPE(result) == AOP_CRY){
6743 // if(size), result in bit
6744 // if(!size && ifx), conditional oper: if(left & right)
6745 symbol *tlbl = newiTempLabel(NULL);
6746 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6748 pic16_emitcode("setb","c");
6750 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6751 pic16_emitcode("anl","a,%s",
6752 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6753 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6758 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6759 pic16_outBitC(result);
6761 jmpTrueOrFalse(ifx, tlbl);
6763 for(;(size--);offset++) {
6765 // result = left & right
6766 if(AOP_TYPE(right) == AOP_LIT){
6767 int t = (lit >> (offset*8)) & 0x0FFL;
6770 pic16_emitcode("clrf","%s",
6771 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6772 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6775 pic16_emitcode("movf","%s,w",
6776 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6777 pic16_emitcode("movwf","%s",
6778 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6779 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6780 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6783 pic16_emitcode("movlw","0x%x",t);
6784 pic16_emitcode("andwf","%s,w",
6785 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6786 pic16_emitcode("movwf","%s",
6787 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6789 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6790 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6791 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6796 if (AOP_TYPE(left) == AOP_ACC) {
6797 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6798 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6800 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6801 pic16_emitcode("andwf","%s,w",
6802 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6803 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6804 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6806 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6807 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6813 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6814 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6815 pic16_freeAsmop(result,NULL,ic,TRUE);
6818 /*-----------------------------------------------------------------*/
6819 /* genOr - code for or */
6820 /*-----------------------------------------------------------------*/
6821 static void genOr (iCode *ic, iCode *ifx)
6823 operand *left, *right, *result;
6825 unsigned long lit = 0L;
6827 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6829 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6830 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6831 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6833 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6835 /* if left is a literal & right is not then exchange them */
6836 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6837 AOP_NEEDSACC(left)) {
6838 operand *tmp = right ;
6843 /* if result = right then exchange them */
6844 if(pic16_sameRegs(AOP(result),AOP(right))){
6845 operand *tmp = right ;
6850 /* if right is bit then exchange them */
6851 if (AOP_TYPE(right) == AOP_CRY &&
6852 AOP_TYPE(left) != AOP_CRY){
6853 operand *tmp = right ;
6858 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6860 if(AOP_TYPE(right) == AOP_LIT)
6861 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6863 size = AOP_SIZE(result);
6867 if (AOP_TYPE(left) == AOP_CRY){
6868 if(AOP_TYPE(right) == AOP_LIT){
6869 // c = bit & literal;
6871 // lit != 0 => result = 1
6872 if(AOP_TYPE(result) == AOP_CRY){
6874 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6875 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6876 // AOP(result)->aopu.aop_dir,
6877 // AOP(result)->aopu.aop_dir);
6879 continueIfTrue(ifx);
6883 // lit == 0 => result = left
6884 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6886 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6889 if (AOP_TYPE(right) == AOP_CRY){
6890 if(pic16_sameRegs(AOP(result),AOP(left))){
6892 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6893 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6894 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6896 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6897 AOP(result)->aopu.aop_dir,
6898 AOP(result)->aopu.aop_dir);
6899 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6900 AOP(right)->aopu.aop_dir,
6901 AOP(right)->aopu.aop_dir);
6902 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6903 AOP(result)->aopu.aop_dir,
6904 AOP(result)->aopu.aop_dir);
6906 if( AOP_TYPE(result) == AOP_ACC) {
6907 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6908 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6909 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6910 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6914 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6915 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6916 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6917 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6919 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6920 AOP(result)->aopu.aop_dir,
6921 AOP(result)->aopu.aop_dir);
6922 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6923 AOP(right)->aopu.aop_dir,
6924 AOP(right)->aopu.aop_dir);
6925 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6926 AOP(left)->aopu.aop_dir,
6927 AOP(left)->aopu.aop_dir);
6928 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6929 AOP(result)->aopu.aop_dir,
6930 AOP(result)->aopu.aop_dir);
6935 symbol *tlbl = newiTempLabel(NULL);
6936 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6939 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6940 if( AOP_TYPE(right) == AOP_ACC) {
6941 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6943 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6944 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6949 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6950 pic16_emitcode(";XXX setb","c");
6951 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6952 AOP(left)->aopu.aop_dir,tlbl->key+100);
6953 pic16_toBoolean(right);
6954 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6955 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6956 jmpTrueOrFalse(ifx, tlbl);
6960 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6967 pic16_outBitC(result);
6969 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6970 genIfxJump(ifx, "c");
6974 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6975 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6976 if((AOP_TYPE(right) == AOP_LIT) &&
6977 (AOP_TYPE(result) == AOP_CRY) &&
6978 (AOP_TYPE(left) != AOP_CRY)){
6980 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6983 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6985 continueIfTrue(ifx);
6988 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6989 // lit = 0, result = boolean(left)
6991 pic16_emitcode(";XXX setb","c");
6992 pic16_toBoolean(right);
6994 symbol *tlbl = newiTempLabel(NULL);
6995 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6997 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6999 genIfxJump (ifx,"a");
7003 pic16_outBitC(result);
7007 /* if left is same as result */
7008 if(pic16_sameRegs(AOP(result),AOP(left))){
7010 for(;size--; offset++,lit>>=8) {
7011 if(AOP_TYPE(right) == AOP_LIT){
7012 if((lit & 0xff) == 0)
7013 /* or'ing with 0 has no effect */
7016 int p = my_powof2(lit & 0xff);
7018 /* only one bit is set in the literal, so use a bsf instruction */
7019 pic16_emitpcode(POC_BSF,
7020 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7022 if(know_W != (lit & 0xff))
7023 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7024 know_W = lit & 0xff;
7025 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7030 if (AOP_TYPE(left) == AOP_ACC) {
7031 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7032 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7034 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7035 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7037 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7038 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7044 // left & result in different registers
7045 if(AOP_TYPE(result) == AOP_CRY){
7047 // if(size), result in bit
7048 // if(!size && ifx), conditional oper: if(left | right)
7049 symbol *tlbl = newiTempLabel(NULL);
7050 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7051 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7055 pic16_emitcode(";XXX setb","c");
7057 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7058 pic16_emitcode(";XXX orl","a,%s",
7059 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7060 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7065 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7066 pic16_outBitC(result);
7068 jmpTrueOrFalse(ifx, tlbl);
7069 } else for(;(size--);offset++){
7071 // result = left & right
7072 if(AOP_TYPE(right) == AOP_LIT){
7073 int t = (lit >> (offset*8)) & 0x0FFL;
7076 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7079 pic16_emitcode("movf","%s,w",
7080 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7081 pic16_emitcode("movwf","%s",
7082 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7085 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7086 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7087 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7089 pic16_emitcode("movlw","0x%x",t);
7090 pic16_emitcode("iorwf","%s,w",
7091 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7092 pic16_emitcode("movwf","%s",
7093 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7099 // faster than result <- left, anl result,right
7100 // and better if result is SFR
7101 if (AOP_TYPE(left) == AOP_ACC) {
7102 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7103 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7105 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7106 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7108 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7109 pic16_emitcode("iorwf","%s,w",
7110 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7112 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7113 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7118 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7119 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7120 pic16_freeAsmop(result,NULL,ic,TRUE);
7123 /*-----------------------------------------------------------------*/
7124 /* genXor - code for xclusive or */
7125 /*-----------------------------------------------------------------*/
7126 static void genXor (iCode *ic, iCode *ifx)
7128 operand *left, *right, *result;
7130 unsigned long lit = 0L;
7132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7134 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7135 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7136 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7138 /* if left is a literal & right is not ||
7139 if left needs acc & right does not */
7140 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7141 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7142 operand *tmp = right ;
7147 /* if result = right then exchange them */
7148 if(pic16_sameRegs(AOP(result),AOP(right))){
7149 operand *tmp = right ;
7154 /* if right is bit then exchange them */
7155 if (AOP_TYPE(right) == AOP_CRY &&
7156 AOP_TYPE(left) != AOP_CRY){
7157 operand *tmp = right ;
7161 if(AOP_TYPE(right) == AOP_LIT)
7162 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7164 size = AOP_SIZE(result);
7168 if (AOP_TYPE(left) == AOP_CRY){
7169 if(AOP_TYPE(right) == AOP_LIT){
7170 // c = bit & literal;
7172 // lit>>1 != 0 => result = 1
7173 if(AOP_TYPE(result) == AOP_CRY){
7175 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7176 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7178 continueIfTrue(ifx);
7181 pic16_emitcode("setb","c");
7185 // lit == 0, result = left
7186 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7188 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7190 // lit == 1, result = not(left)
7191 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7192 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7193 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7194 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7197 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7198 pic16_emitcode("cpl","c");
7205 symbol *tlbl = newiTempLabel(NULL);
7206 if (AOP_TYPE(right) == AOP_CRY){
7208 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7211 int sizer = AOP_SIZE(right);
7213 // if val>>1 != 0, result = 1
7214 pic16_emitcode("setb","c");
7216 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7218 // test the msb of the lsb
7219 pic16_emitcode("anl","a,#0xfe");
7220 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7224 pic16_emitcode("rrc","a");
7226 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7227 pic16_emitcode("cpl","c");
7228 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7233 pic16_outBitC(result);
7235 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7236 genIfxJump(ifx, "c");
7240 if(pic16_sameRegs(AOP(result),AOP(left))){
7241 /* if left is same as result */
7242 for(;size--; offset++) {
7243 if(AOP_TYPE(right) == AOP_LIT){
7244 int t = (lit >> (offset*8)) & 0x0FFL;
7248 if (IS_AOP_PREG(left)) {
7249 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7250 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7251 pic16_aopPut(AOP(result),"a",offset);
7253 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7254 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7255 pic16_emitcode("xrl","%s,%s",
7256 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7257 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7260 if (AOP_TYPE(left) == AOP_ACC)
7261 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7263 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7264 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7266 if (IS_AOP_PREG(left)) {
7267 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7268 pic16_aopPut(AOP(result),"a",offset);
7270 pic16_emitcode("xrl","%s,a",
7271 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7277 // left & result in different registers
7278 if(AOP_TYPE(result) == AOP_CRY){
7280 // if(size), result in bit
7281 // if(!size && ifx), conditional oper: if(left ^ right)
7282 symbol *tlbl = newiTempLabel(NULL);
7283 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7285 pic16_emitcode("setb","c");
7287 if((AOP_TYPE(right) == AOP_LIT) &&
7288 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7289 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7291 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7292 pic16_emitcode("xrl","a,%s",
7293 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7295 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7300 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7301 pic16_outBitC(result);
7303 jmpTrueOrFalse(ifx, tlbl);
7304 } else for(;(size--);offset++){
7306 // result = left & right
7307 if(AOP_TYPE(right) == AOP_LIT){
7308 int t = (lit >> (offset*8)) & 0x0FFL;
7311 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7312 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7313 pic16_emitcode("movf","%s,w",
7314 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7315 pic16_emitcode("movwf","%s",
7316 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7319 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7320 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7321 pic16_emitcode("comf","%s,w",
7322 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7323 pic16_emitcode("movwf","%s",
7324 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7327 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7328 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7329 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7330 pic16_emitcode("movlw","0x%x",t);
7331 pic16_emitcode("xorwf","%s,w",
7332 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7333 pic16_emitcode("movwf","%s",
7334 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7340 // faster than result <- left, anl result,right
7341 // and better if result is SFR
7342 if (AOP_TYPE(left) == AOP_ACC) {
7343 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7344 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7346 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7347 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7348 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7349 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7351 if ( AOP_TYPE(result) != AOP_ACC){
7352 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7353 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7359 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7360 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7361 pic16_freeAsmop(result,NULL,ic,TRUE);
7364 /*-----------------------------------------------------------------*/
7365 /* genInline - write the inline code out */
7366 /*-----------------------------------------------------------------*/
7367 static void genInline (iCode *ic)
7369 char *buffer, *bp, *bp1;
7371 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7373 _G.inLine += (!options.asmpeep);
7375 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7376 strcpy(buffer,IC_INLINE(ic));
7378 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7380 /* emit each line as a code */
7386 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7394 /* print label, use this special format with NULL directive
7395 * to denote that the argument should not be indented with tab */
7396 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7403 if ((bp1 != bp) && *bp1)
7404 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7409 _G.inLine -= (!options.asmpeep);
7412 /*-----------------------------------------------------------------*/
7413 /* genRRC - rotate right with carry */
7414 /*-----------------------------------------------------------------*/
7415 static void genRRC (iCode *ic)
7417 operand *left , *result ;
7418 int size, offset = 0, same;
7420 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7422 /* rotate right with carry */
7424 result=IC_RESULT(ic);
7425 pic16_aopOp (left,ic,FALSE);
7426 pic16_aopOp (result,ic,FALSE);
7428 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7430 same = pic16_sameRegs(AOP(result),AOP(left));
7432 size = AOP_SIZE(result);
7434 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7436 /* get the lsb and put it into the carry */
7437 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7444 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7446 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7447 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7453 pic16_freeAsmop(left,NULL,ic,TRUE);
7454 pic16_freeAsmop(result,NULL,ic,TRUE);
7457 /*-----------------------------------------------------------------*/
7458 /* genRLC - generate code for rotate left with carry */
7459 /*-----------------------------------------------------------------*/
7460 static void genRLC (iCode *ic)
7462 operand *left , *result ;
7463 int size, offset = 0;
7466 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7467 /* rotate right with carry */
7469 result=IC_RESULT(ic);
7470 pic16_aopOp (left,ic,FALSE);
7471 pic16_aopOp (result,ic,FALSE);
7473 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7475 same = pic16_sameRegs(AOP(result),AOP(left));
7477 /* move it to the result */
7478 size = AOP_SIZE(result);
7480 /* get the msb and put it into the carry */
7481 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7488 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7490 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7491 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7498 pic16_freeAsmop(left,NULL,ic,TRUE);
7499 pic16_freeAsmop(result,NULL,ic,TRUE);
7503 /* gpasm can get the highest order bit with HIGH/UPPER
7504 * so the following probably is not needed -- VR */
7506 /*-----------------------------------------------------------------*/
7507 /* genGetHbit - generates code get highest order bit */
7508 /*-----------------------------------------------------------------*/
7509 static void genGetHbit (iCode *ic)
7511 operand *left, *result;
7513 result=IC_RESULT(ic);
7514 pic16_aopOp (left,ic,FALSE);
7515 pic16_aopOp (result,ic,FALSE);
7517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7518 /* get the highest order byte into a */
7519 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7520 if(AOP_TYPE(result) == AOP_CRY){
7521 pic16_emitcode("rlc","a");
7522 pic16_outBitC(result);
7525 pic16_emitcode("rl","a");
7526 pic16_emitcode("anl","a,#0x01");
7527 pic16_outAcc(result);
7531 pic16_freeAsmop(left,NULL,ic,TRUE);
7532 pic16_freeAsmop(result,NULL,ic,TRUE);
7536 /*-----------------------------------------------------------------*/
7537 /* AccRol - rotate left accumulator by known count */
7538 /*-----------------------------------------------------------------*/
7539 static void AccRol (int shCount)
7541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7542 shCount &= 0x0007; // shCount : 0..7
7547 pic16_emitcode("rl","a");
7550 pic16_emitcode("rl","a");
7551 pic16_emitcode("rl","a");
7554 pic16_emitcode("swap","a");
7555 pic16_emitcode("rr","a");
7558 pic16_emitcode("swap","a");
7561 pic16_emitcode("swap","a");
7562 pic16_emitcode("rl","a");
7565 pic16_emitcode("rr","a");
7566 pic16_emitcode("rr","a");
7569 pic16_emitcode("rr","a");
7575 /*-----------------------------------------------------------------*/
7576 /* AccLsh - left shift accumulator by known count */
7577 /*-----------------------------------------------------------------*/
7578 static void AccLsh (int shCount)
7580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7586 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7589 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7590 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7593 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7594 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7597 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7600 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7601 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7604 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7605 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7608 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7612 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7615 /*-----------------------------------------------------------------*/
7616 /* AccRsh - right shift accumulator by known count */
7617 /*-----------------------------------------------------------------*/
7618 static void AccRsh (int shCount, int andmask)
7620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7625 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7628 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7629 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7632 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7633 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7636 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7639 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7640 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7643 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7644 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7647 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7652 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7654 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7658 /*-----------------------------------------------------------------*/
7659 /* AccSRsh - signed right shift accumulator by known count */
7660 /*-----------------------------------------------------------------*/
7661 static void AccSRsh (int shCount)
7664 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7667 pic16_emitcode("mov","c,acc.7");
7668 pic16_emitcode("rrc","a");
7669 } else if(shCount == 2){
7670 pic16_emitcode("mov","c,acc.7");
7671 pic16_emitcode("rrc","a");
7672 pic16_emitcode("mov","c,acc.7");
7673 pic16_emitcode("rrc","a");
7675 tlbl = newiTempLabel(NULL);
7676 /* rotate right accumulator */
7677 AccRol(8 - shCount);
7678 /* and kill the higher order bits */
7679 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7680 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7681 pic16_emitcode("orl","a,#0x%02x",
7682 (unsigned char)~SRMask[shCount]);
7683 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7689 /*-----------------------------------------------------------------*/
7690 /* shiftR1Left2Result - shift right one byte from left to result */
7691 /*-----------------------------------------------------------------*/
7692 static void shiftR1Left2ResultSigned (operand *left, int offl,
7693 operand *result, int offr,
7698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7700 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7704 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7706 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7708 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7709 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7715 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7717 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7719 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7720 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7722 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7723 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7729 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7731 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7732 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7735 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
7736 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7737 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7739 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7740 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7746 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7747 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7748 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7749 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7750 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7754 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7756 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7759 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7760 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7761 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7762 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7763 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7768 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7769 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7771 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7772 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7775 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7776 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7777 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7778 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7779 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7785 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7786 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7787 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7790 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7791 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7792 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7800 /*-----------------------------------------------------------------*/
7801 /* shiftR1Left2Result - shift right one byte from left to result */
7802 /*-----------------------------------------------------------------*/
7803 static void shiftR1Left2Result (operand *left, int offl,
7804 operand *result, int offr,
7805 int shCount, int sign)
7809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7811 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7813 /* Copy the msb into the carry if signed. */
7815 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7825 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7827 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7828 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7834 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7836 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7840 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7845 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7847 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7851 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
7852 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7858 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7859 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7864 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7865 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
7866 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7868 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
7873 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
7874 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
7875 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7876 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7877 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
7882 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7883 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7884 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7893 /*-----------------------------------------------------------------*/
7894 /* shiftL1Left2Result - shift left one byte from left to result */
7895 /*-----------------------------------------------------------------*/
7896 static void shiftL1Left2Result (operand *left, int offl,
7897 operand *result, int offr, int shCount)
7902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7904 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7905 DEBUGpic16_emitcode ("; ***","same = %d",same);
7906 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7908 /* shift left accumulator */
7909 //AccLsh(shCount); // don't comment out just yet...
7910 // pic16_aopPut(AOP(result),"a",offr);
7914 /* Shift left 1 bit position */
7915 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7917 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7919 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7920 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7924 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7925 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7926 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7927 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7930 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7931 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7932 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7934 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7937 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7938 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7939 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7942 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7943 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7944 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7945 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7948 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7949 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7950 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7951 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7952 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7955 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7956 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7957 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7961 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7966 /*-----------------------------------------------------------------*/
7967 /* movLeft2Result - move byte from left to result */
7968 /*-----------------------------------------------------------------*/
7969 static void movLeft2Result (operand *left, int offl,
7970 operand *result, int offr)
7973 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7974 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7975 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7977 if (*l == '@' && (IS_AOP_PREG(result))) {
7978 pic16_emitcode("mov","a,%s",l);
7979 pic16_aopPut(AOP(result),"a",offr);
7981 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7982 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7987 /*-----------------------------------------------------------------*/
7988 /* shiftL2Left2Result - shift left two bytes from left to result */
7989 /*-----------------------------------------------------------------*/
7990 static void shiftL2Left2Result (operand *left, int offl,
7991 operand *result, int offr, int shCount)
7993 int same = pic16_sameRegs(AOP(result), AOP(left));
7996 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7998 if (same && (offl != offr)) { // shift bytes
8001 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8002 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8004 } else { // just treat as different later on
8017 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8018 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8019 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8023 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8024 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8030 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8031 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8032 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8033 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8034 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8035 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8036 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8038 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8039 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8043 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8045 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8046 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8047 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8048 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8049 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8050 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8051 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8052 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8055 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8056 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8057 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8058 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8059 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8069 /* note, use a mov/add for the shift since the mov has a
8070 chance of getting optimized out */
8071 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8073 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8074 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8079 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8086 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8087 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8089 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8090 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8091 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8092 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8093 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8097 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8098 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8102 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8103 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8104 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8105 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8107 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8108 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8109 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8110 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8111 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8112 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8113 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8114 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8117 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8118 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8120 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8121 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8126 /*-----------------------------------------------------------------*/
8127 /* shiftR2Left2Result - shift right two bytes from left to result */
8128 /*-----------------------------------------------------------------*/
8129 static void shiftR2Left2Result (operand *left, int offl,
8130 operand *result, int offr,
8131 int shCount, int sign)
8133 int same = pic16_sameRegs(AOP(result), AOP(left));
8135 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8137 if (same && (offl != offr)) { // shift right bytes
8140 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8141 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8143 } else { // just treat as different later on
8155 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8160 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8161 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8163 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8165 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8171 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8174 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8175 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8182 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8183 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8184 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8186 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8187 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8188 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8189 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8191 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8192 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8195 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8196 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8197 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8198 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8199 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8203 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8204 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8208 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8209 pic16_emitpcode(POC_BTFSC,
8210 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8211 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8219 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8220 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8222 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8223 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8224 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8225 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8227 pic16_emitpcode(POC_BTFSC,
8228 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8229 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8231 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8232 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8233 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8234 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8236 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8237 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8238 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8239 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8240 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8241 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8242 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8243 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8245 pic16_emitpcode(POC_BTFSC,
8246 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8247 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8249 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8250 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8257 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8258 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8259 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8260 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8263 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8265 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8270 /*-----------------------------------------------------------------*/
8271 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8272 /*-----------------------------------------------------------------*/
8273 static void shiftLLeftOrResult (operand *left, int offl,
8274 operand *result, int offr, int shCount)
8276 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8278 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8279 /* shift left accumulator */
8281 /* or with result */
8282 /* back to result */
8283 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8286 /*-----------------------------------------------------------------*/
8287 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8288 /*-----------------------------------------------------------------*/
8289 static void shiftRLeftOrResult (operand *left, int offl,
8290 operand *result, int offr, int shCount)
8292 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8294 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8295 /* shift right accumulator */
8297 /* or with result */
8298 /* back to result */
8299 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8302 /*-----------------------------------------------------------------*/
8303 /* genlshOne - left shift a one byte quantity by known count */
8304 /*-----------------------------------------------------------------*/
8305 static void genlshOne (operand *result, operand *left, int shCount)
8307 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8308 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8311 /*-----------------------------------------------------------------*/
8312 /* genlshTwo - left shift two bytes by known amount != 0 */
8313 /*-----------------------------------------------------------------*/
8314 static void genlshTwo (operand *result,operand *left, int shCount)
8318 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8319 size = pic16_getDataSize(result);
8321 /* if shCount >= 8 */
8327 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8329 movLeft2Result(left, LSB, result, MSB16);
8331 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8334 /* 1 <= shCount <= 7 */
8337 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8339 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8343 /*-----------------------------------------------------------------*/
8344 /* shiftLLong - shift left one long from left to result */
8345 /* offr = LSB or MSB16 */
8346 /*-----------------------------------------------------------------*/
8347 static void shiftLLong (operand *left, operand *result, int offr )
8349 int size = AOP_SIZE(result);
8350 int same = pic16_sameRegs(AOP(left),AOP(result));
8353 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8355 if (same && (offr == MSB16)) { //shift one byte
8356 for(i=size-1;i>=MSB16;i--) {
8357 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8358 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8361 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8364 if (size > LSB+offr ){
8366 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8368 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8369 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8373 if(size > MSB16+offr){
8375 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8377 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8378 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8382 if(size > MSB24+offr){
8384 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8386 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8387 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8391 if(size > MSB32+offr){
8393 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8395 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8396 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8400 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8404 /*-----------------------------------------------------------------*/
8405 /* genlshFour - shift four byte by a known amount != 0 */
8406 /*-----------------------------------------------------------------*/
8407 static void genlshFour (operand *result, operand *left, int shCount)
8411 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8412 size = AOP_SIZE(result);
8414 /* if shifting more that 3 bytes */
8415 if (shCount >= 24 ) {
8418 /* lowest order of left goes to the highest
8419 order of the destination */
8420 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8422 movLeft2Result(left, LSB, result, MSB32);
8424 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8425 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8426 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8431 /* more than two bytes */
8432 else if ( shCount >= 16 ) {
8433 /* lower order two bytes goes to higher order two bytes */
8435 /* if some more remaining */
8437 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8439 movLeft2Result(left, MSB16, result, MSB32);
8440 movLeft2Result(left, LSB, result, MSB24);
8442 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8443 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8447 /* if more than 1 byte */
8448 else if ( shCount >= 8 ) {
8449 /* lower order three bytes goes to higher order three bytes */
8453 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8455 movLeft2Result(left, LSB, result, MSB16);
8457 else{ /* size = 4 */
8459 movLeft2Result(left, MSB24, result, MSB32);
8460 movLeft2Result(left, MSB16, result, MSB24);
8461 movLeft2Result(left, LSB, result, MSB16);
8462 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8464 else if(shCount == 1)
8465 shiftLLong(left, result, MSB16);
8467 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8468 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8469 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8470 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8475 /* 1 <= shCount <= 7 */
8476 else if(shCount <= 3)
8478 shiftLLong(left, result, LSB);
8479 while(--shCount >= 1)
8480 shiftLLong(result, result, LSB);
8482 /* 3 <= shCount <= 7, optimize */
8484 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8485 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8486 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8490 /*-----------------------------------------------------------------*/
8491 /* genLeftShiftLiteral - left shifting by known count */
8492 /*-----------------------------------------------------------------*/
8493 static void genLeftShiftLiteral (operand *left,
8498 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8501 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8502 pic16_freeAsmop(right,NULL,ic,TRUE);
8504 pic16_aopOp(left,ic,FALSE);
8505 pic16_aopOp(result,ic,FALSE);
8507 size = getSize(operandType(result));
8510 pic16_emitcode("; shift left ","result %d, left %d",size,
8514 /* I suppose that the left size >= result size */
8517 movLeft2Result(left, size, result, size);
8521 else if(shCount >= (size * 8))
8523 pic16_aopPut(AOP(result),zero,size);
8527 genlshOne (result,left,shCount);
8532 genlshTwo (result,left,shCount);
8536 genlshFour (result,left,shCount);
8540 pic16_freeAsmop(left,NULL,ic,TRUE);
8541 pic16_freeAsmop(result,NULL,ic,TRUE);
8544 /*-----------------------------------------------------------------*
8545 * genMultiAsm - repeat assembly instruction for size of register.
8546 * if endian == 1, then the high byte (i.e base address + size of
8547 * register) is used first else the low byte is used first;
8548 *-----------------------------------------------------------------*/
8549 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8567 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8572 /*-----------------------------------------------------------------*/
8573 /* genLeftShift - generates code for left shifting */
8574 /*-----------------------------------------------------------------*/
8575 static void genLeftShift (iCode *ic)
8577 operand *left,*right, *result;
8580 symbol *tlbl , *tlbl1;
8583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8585 right = IC_RIGHT(ic);
8587 result = IC_RESULT(ic);
8589 pic16_aopOp(right,ic,FALSE);
8591 /* if the shift count is known then do it
8592 as efficiently as possible */
8593 if (AOP_TYPE(right) == AOP_LIT) {
8594 genLeftShiftLiteral (left,right,result,ic);
8598 /* shift count is unknown then we have to form
8599 * a loop. Get the loop count in WREG : Note: we take
8600 * only the lower order byte since shifting
8601 * more than 32 bits make no sense anyway, ( the
8602 * largest size of an object can be only 32 bits ) */
8604 pic16_aopOp(left,ic,FALSE);
8605 pic16_aopOp(result,ic,FALSE);
8607 /* now move the left to the result if they are not the
8608 * same, and if size > 1,
8609 * and if right is not same to result (!!!) -- VR */
8610 if (!pic16_sameRegs(AOP(left),AOP(result))
8611 && (AOP_SIZE(result) > 1)) {
8613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8615 size = AOP_SIZE(result);
8620 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8621 if (*l == '@' && (IS_AOP_PREG(result))) {
8623 pic16_emitcode("mov","a,%s",l);
8624 pic16_aopPut(AOP(result),"a",offset);
8628 /* we don't know if left is a literal or a register, take care -- VR */
8629 mov2f(AOP(result), AOP(left), offset);
8635 size = AOP_SIZE(result);
8637 /* if it is only one byte then */
8639 if(optimized_for_speed) {
8640 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8641 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8642 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8643 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8644 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8645 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8646 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8647 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8648 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8649 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8650 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8651 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8654 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8656 tlbl = newiTempLabel(NULL);
8659 /* this is already done, why change it? */
8660 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8661 mov2f(AOP(result), AOP(left), 0);
8665 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8666 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8667 pic16_emitpLabel(tlbl->key);
8668 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8669 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8676 if (pic16_sameRegs(AOP(left),AOP(result))) {
8678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8680 tlbl = newiTempLabel(NULL);
8681 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8682 genMultiAsm(POC_RRCF, result, size,1);
8683 pic16_emitpLabel(tlbl->key);
8684 genMultiAsm(POC_RLCF, result, size,0);
8685 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8687 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8691 //tlbl = newiTempLabel(NULL);
8693 //tlbl1 = newiTempLabel(NULL);
8695 //reAdjustPreg(AOP(result));
8697 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8698 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8699 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8701 //pic16_emitcode("add","a,acc");
8702 //pic16_aopPut(AOP(result),"a",offset++);
8704 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8706 // pic16_emitcode("rlc","a");
8707 // pic16_aopPut(AOP(result),"a",offset++);
8709 //reAdjustPreg(AOP(result));
8711 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8712 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8715 tlbl = newiTempLabel(NULL);
8716 tlbl1= newiTempLabel(NULL);
8718 size = AOP_SIZE(result);
8721 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
8723 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8725 /* offset should be 0, 1 or 3 */
8727 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8729 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8731 pic16_emitpcode(POC_MOVWF, pctemp);
8734 pic16_emitpLabel(tlbl->key);
8737 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8739 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8741 pic16_emitpcode(POC_DECFSZ, pctemp);
8742 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8743 pic16_emitpLabel(tlbl1->key);
8745 pic16_popReleaseTempReg(pctemp,1);
8749 pic16_freeAsmop (right,NULL,ic,TRUE);
8750 pic16_freeAsmop(left,NULL,ic,TRUE);
8751 pic16_freeAsmop(result,NULL,ic,TRUE);
8757 #error old code (left here for reference)
8758 /*-----------------------------------------------------------------*/
8759 /* genLeftShift - generates code for left shifting */
8760 /*-----------------------------------------------------------------*/
8761 static void genLeftShift (iCode *ic)
8763 operand *left,*right, *result;
8766 symbol *tlbl , *tlbl1;
8769 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8771 right = IC_RIGHT(ic);
8773 result = IC_RESULT(ic);
8775 pic16_aopOp(right,ic,FALSE);
8777 /* if the shift count is known then do it
8778 as efficiently as possible */
8779 if (AOP_TYPE(right) == AOP_LIT) {
8780 genLeftShiftLiteral (left,right,result,ic);
8784 /* shift count is unknown then we have to form
8785 a loop get the loop count in B : Note: we take
8786 only the lower order byte since shifting
8787 more that 32 bits make no sense anyway, ( the
8788 largest size of an object can be only 32 bits ) */
8791 pic16_aopOp(left,ic,FALSE);
8792 pic16_aopOp(result,ic,FALSE);
8794 /* now move the left to the result if they are not the
8796 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8797 AOP_SIZE(result) > 1) {
8799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8801 size = AOP_SIZE(result);
8804 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8805 if (*l == '@' && (IS_AOP_PREG(result))) {
8807 pic16_emitcode("mov","a,%s",l);
8808 pic16_aopPut(AOP(result),"a",offset);
8811 /* we don't know if left is a literal or a register, take care -- VR */
8812 mov2f(AOP(result), AOP(left), offset);
8818 size = AOP_SIZE(result);
8820 /* if it is only one byte then */
8822 if(optimized_for_speed) {
8823 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8824 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8825 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8826 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8827 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8828 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8829 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8830 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8831 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8832 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8833 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8834 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8839 tlbl = newiTempLabel(NULL);
8840 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8841 mov2f(AOP(result), AOP(left), 0);
8843 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8844 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8847 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8848 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8849 pic16_emitpLabel(tlbl->key);
8850 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8851 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8853 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8858 if (pic16_sameRegs(AOP(left),AOP(result))) {
8860 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8862 tlbl = newiTempLabel(NULL);
8863 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8864 genMultiAsm(POC_RRCF, result, size,1);
8865 pic16_emitpLabel(tlbl->key);
8866 genMultiAsm(POC_RLCF, result, size,0);
8867 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8869 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8873 //tlbl = newiTempLabel(NULL);
8875 //tlbl1 = newiTempLabel(NULL);
8877 //reAdjustPreg(AOP(result));
8879 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8880 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8881 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8883 //pic16_emitcode("add","a,acc");
8884 //pic16_aopPut(AOP(result),"a",offset++);
8886 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8888 // pic16_emitcode("rlc","a");
8889 // pic16_aopPut(AOP(result),"a",offset++);
8891 //reAdjustPreg(AOP(result));
8893 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8894 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8897 tlbl = newiTempLabel(NULL);
8898 tlbl1= newiTempLabel(NULL);
8900 size = AOP_SIZE(result);
8903 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
8905 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8907 /* offset should be 0, 1 or 3 */
8909 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8911 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8913 pic16_emitpcode(POC_MOVWF, pctemp);
8916 pic16_emitpLabel(tlbl->key);
8919 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8921 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8923 pic16_emitpcode(POC_DECFSZ, pctemp);
8924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8925 pic16_emitpLabel(tlbl1->key);
8927 pic16_popReleaseTempReg(pctemp,1);
8931 pic16_freeAsmop (right,NULL,ic,TRUE);
8932 pic16_freeAsmop(left,NULL,ic,TRUE);
8933 pic16_freeAsmop(result,NULL,ic,TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* genrshOne - right shift a one byte quantity by known count */
8939 /*-----------------------------------------------------------------*/
8940 static void genrshOne (operand *result, operand *left,
8941 int shCount, int sign)
8943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8944 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8947 /*-----------------------------------------------------------------*/
8948 /* genrshTwo - right shift two bytes by known amount != 0 */
8949 /*-----------------------------------------------------------------*/
8950 static void genrshTwo (operand *result,operand *left,
8951 int shCount, int sign)
8953 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8954 /* if shCount >= 8 */
8958 shiftR1Left2Result(left, MSB16, result, LSB,
8961 movLeft2Result(left, MSB16, result, LSB);
8963 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8966 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8967 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8971 /* 1 <= shCount <= 7 */
8973 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8976 /*-----------------------------------------------------------------*/
8977 /* shiftRLong - shift right one long from left to result */
8978 /* offl = LSB or MSB16 */
8979 /*-----------------------------------------------------------------*/
8980 static void shiftRLong (operand *left, int offl,
8981 operand *result, int sign)
8983 int size = AOP_SIZE(result);
8984 int same = pic16_sameRegs(AOP(left),AOP(result));
8986 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8988 if (same && (offl == MSB16)) { //shift one byte right
8989 for(i=MSB16;i<size;i++) {
8990 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8991 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8996 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9002 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9004 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9009 /* add sign of "a" */
9010 pic16_addSign(result, MSB32, sign);
9014 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9016 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9021 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9028 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9031 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9032 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9037 /*-----------------------------------------------------------------*/
9038 /* genrshFour - shift four byte by a known amount != 0 */
9039 /*-----------------------------------------------------------------*/
9040 static void genrshFour (operand *result, operand *left,
9041 int shCount, int sign)
9043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9044 /* if shifting more that 3 bytes */
9045 if(shCount >= 24 ) {
9048 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9050 movLeft2Result(left, MSB32, result, LSB);
9052 pic16_addSign(result, MSB16, sign);
9054 else if(shCount >= 16){
9057 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9059 movLeft2Result(left, MSB24, result, LSB);
9060 movLeft2Result(left, MSB32, result, MSB16);
9062 pic16_addSign(result, MSB24, sign);
9064 else if(shCount >= 8){
9067 shiftRLong(left, MSB16, result, sign);
9068 else if(shCount == 0){
9069 movLeft2Result(left, MSB16, result, LSB);
9070 movLeft2Result(left, MSB24, result, MSB16);
9071 movLeft2Result(left, MSB32, result, MSB24);
9072 pic16_addSign(result, MSB32, sign);
9074 else{ //shcount >= 2
9075 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9076 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9077 /* the last shift is signed */
9078 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9079 pic16_addSign(result, MSB32, sign);
9082 else{ /* 1 <= shCount <= 7 */
9084 shiftRLong(left, LSB, result, sign);
9086 shiftRLong(result, LSB, result, sign);
9089 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9090 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9091 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9096 /*-----------------------------------------------------------------*/
9097 /* genRightShiftLiteral - right shifting by known count */
9098 /*-----------------------------------------------------------------*/
9099 static void genRightShiftLiteral (operand *left,
9105 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9108 pic16_freeAsmop(right,NULL,ic,TRUE);
9110 pic16_aopOp(left,ic,FALSE);
9111 pic16_aopOp(result,ic,FALSE);
9113 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9116 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9120 lsize = pic16_getDataSize(left);
9121 res_size = pic16_getDataSize(result);
9122 /* test the LEFT size !!! */
9124 /* I suppose that the left size >= result size */
9127 movLeft2Result(left, lsize, result, res_size);
9130 else if(shCount >= (lsize * 8)){
9133 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9135 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9136 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9141 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9142 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9143 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9150 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9157 genrshOne (result,left,shCount,sign);
9161 genrshTwo (result,left,shCount,sign);
9165 genrshFour (result,left,shCount,sign);
9173 pic16_freeAsmop(left,NULL,ic,TRUE);
9174 pic16_freeAsmop(result,NULL,ic,TRUE);
9177 /*-----------------------------------------------------------------*/
9178 /* genSignedRightShift - right shift of signed number */
9179 /*-----------------------------------------------------------------*/
9180 static void genSignedRightShift (iCode *ic)
9182 operand *right, *left, *result;
9185 symbol *tlbl, *tlbl1 ;
9188 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9190 /* we do it the hard way put the shift count in b
9191 and loop thru preserving the sign */
9192 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9194 right = IC_RIGHT(ic);
9196 result = IC_RESULT(ic);
9198 pic16_aopOp(right,ic,FALSE);
9199 pic16_aopOp(left,ic,FALSE);
9200 pic16_aopOp(result,ic,FALSE);
9203 if ( AOP_TYPE(right) == AOP_LIT) {
9204 genRightShiftLiteral (left,right,result,ic,1);
9207 /* shift count is unknown then we have to form
9208 a loop get the loop count in B : Note: we take
9209 only the lower order byte since shifting
9210 more that 32 bits make no sense anyway, ( the
9211 largest size of an object can be only 32 bits ) */
9213 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9214 //pic16_emitcode("inc","b");
9215 //pic16_freeAsmop (right,NULL,ic,TRUE);
9216 //pic16_aopOp(left,ic,FALSE);
9217 //pic16_aopOp(result,ic,FALSE);
9219 /* now move the left to the result if they are not the
9221 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9222 AOP_SIZE(result) > 1) {
9224 size = AOP_SIZE(result);
9228 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9229 if (*l == '@' && IS_AOP_PREG(result)) {
9231 pic16_emitcode("mov","a,%s",l);
9232 pic16_aopPut(AOP(result),"a",offset);
9234 pic16_aopPut(AOP(result),l,offset);
9236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
9237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9243 /* mov the highest order bit to OVR */
9244 tlbl = newiTempLabel(NULL);
9245 tlbl1= newiTempLabel(NULL);
9247 size = AOP_SIZE(result);
9250 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9252 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9254 /* offset should be 0, 1 or 3 */
9255 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9257 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9259 pic16_emitpcode(POC_MOVWF, pctemp);
9262 pic16_emitpLabel(tlbl->key);
9264 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
9265 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
9268 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
9271 pic16_emitpcode(POC_DECFSZ, pctemp);
9272 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9273 pic16_emitpLabel(tlbl1->key);
9275 pic16_popReleaseTempReg(pctemp,1);
9277 size = AOP_SIZE(result);
9279 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9280 pic16_emitcode("rlc","a");
9281 pic16_emitcode("mov","ov,c");
9282 /* if it is only one byte then */
9284 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9286 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9287 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9288 pic16_emitcode("mov","c,ov");
9289 pic16_emitcode("rrc","a");
9290 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9291 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9292 pic16_aopPut(AOP(result),"a",0);
9296 reAdjustPreg(AOP(result));
9297 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9298 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9299 pic16_emitcode("mov","c,ov");
9301 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9303 pic16_emitcode("rrc","a");
9304 pic16_aopPut(AOP(result),"a",offset--);
9306 reAdjustPreg(AOP(result));
9307 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9308 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9313 pic16_freeAsmop(left,NULL,ic,TRUE);
9314 pic16_freeAsmop(result,NULL,ic,TRUE);
9315 pic16_freeAsmop(right,NULL,ic,TRUE);
9318 /*-----------------------------------------------------------------*/
9319 /* genRightShift - generate code for right shifting */
9320 /*-----------------------------------------------------------------*/
9321 static void genRightShift (iCode *ic)
9323 operand *right, *left, *result;
9327 symbol *tlbl, *tlbl1 ;
9329 /* if signed then we do it the hard way preserve the
9330 sign bit moving it inwards */
9331 letype = getSpec(operandType(IC_LEFT(ic)));
9332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9334 if (!SPEC_USIGN(letype)) {
9335 genSignedRightShift (ic);
9339 /* signed & unsigned types are treated the same : i.e. the
9340 signed is NOT propagated inwards : quoting from the
9341 ANSI - standard : "for E1 >> E2, is equivalent to division
9342 by 2**E2 if unsigned or if it has a non-negative value,
9343 otherwise the result is implementation defined ", MY definition
9344 is that the sign does not get propagated */
9346 right = IC_RIGHT(ic);
9348 result = IC_RESULT(ic);
9350 pic16_aopOp(right,ic,FALSE);
9352 /* if the shift count is known then do it
9353 as efficiently as possible */
9354 if (AOP_TYPE(right) == AOP_LIT) {
9355 genRightShiftLiteral (left,right,result,ic, 0);
9359 /* shift count is unknown then we have to form
9360 a loop get the loop count in B : Note: we take
9361 only the lower order byte since shifting
9362 more that 32 bits make no sense anyway, ( the
9363 largest size of an object can be only 32 bits ) */
9365 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9366 pic16_emitcode("inc","b");
9367 pic16_aopOp(left,ic,FALSE);
9368 pic16_aopOp(result,ic,FALSE);
9370 /* now move the left to the result if they are not the
9372 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9373 AOP_SIZE(result) > 1) {
9375 size = AOP_SIZE(result);
9378 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9379 if (*l == '@' && IS_AOP_PREG(result)) {
9381 pic16_emitcode("mov","a,%s",l);
9382 pic16_aopPut(AOP(result),"a",offset);
9384 pic16_aopPut(AOP(result),l,offset);
9389 tlbl = newiTempLabel(NULL);
9390 tlbl1= newiTempLabel(NULL);
9391 size = AOP_SIZE(result);
9394 /* if it is only one byte then */
9397 tlbl = newiTempLabel(NULL);
9398 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9399 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9400 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9403 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9404 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9405 pic16_emitpLabel(tlbl->key);
9406 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9407 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9409 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9414 reAdjustPreg(AOP(result));
9415 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9416 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9419 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9421 pic16_emitcode("rrc","a");
9422 pic16_aopPut(AOP(result),"a",offset--);
9424 reAdjustPreg(AOP(result));
9426 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9427 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9430 pic16_freeAsmop(left,NULL,ic,TRUE);
9431 pic16_freeAsmop (right,NULL,ic,TRUE);
9432 pic16_freeAsmop(result,NULL,ic,TRUE);
9436 void pic16_loadFSR0(operand *op)
9438 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9441 /*-----------------------------------------------------------------*/
9442 /* genUnpackBits - generates code for unpacking bits */
9443 /*-----------------------------------------------------------------*/
9444 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9452 etype = getSpec(operandType(result));
9454 /* the following call to pic16_loadFSR0 is temporary until
9455 * optimization to handle single bit assignments is added
9456 * to the function. Until then use the old safe way! -- VR */
9457 pic16_loadFSR0( left );
9459 /* read the first byte */
9466 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9469 pic16_emitcode("clr","a");
9470 pic16_emitcode("movc","a","@a+dptr");
9475 /* if we have bitdisplacement then it fits */
9476 /* into this byte completely or if length is */
9477 /* less than a byte */
9478 if ((shCnt = SPEC_BSTR(etype)) ||
9479 (SPEC_BLEN(etype) <= 8)) {
9481 /* shift right acc */
9484 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9485 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9487 /* VR -- normally I would use the following, but since we use the hack,
9488 * to avoid the masking from AccRsh, why not mask it right now? */
9491 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9500 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9501 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9504 /* bit field did not fit in a byte */
9505 rlen = SPEC_BLEN(etype) - 8;
9506 pic16_aopPut(AOP(result),"a",offset++);
9513 pic16_emitcode("inc","%s",rname);
9514 pic16_emitcode("mov","a,@%s",rname);
9518 pic16_emitcode("inc","%s",rname);
9519 pic16_emitcode("movx","a,@%s",rname);
9523 pic16_emitcode("inc","dptr");
9524 pic16_emitcode("movx","a,@dptr");
9528 pic16_emitcode("clr","a");
9529 pic16_emitcode("inc","dptr");
9530 pic16_emitcode("movc","a","@a+dptr");
9534 pic16_emitcode("inc","dptr");
9535 pic16_emitcode("lcall","__gptrget");
9540 /* if we are done */
9544 pic16_aopPut(AOP(result),"a",offset++);
9549 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9550 pic16_aopPut(AOP(result),"a",offset);
9557 static void genDataPointerGet(operand *left,
9561 int size, offset = 0, leoffset=0 ;
9563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9564 pic16_aopOp(result, ic, FALSE);
9566 size = AOP_SIZE(result);
9567 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9571 /* The following tests may save a redudant movff instruction when
9572 * accessing unions */
9574 /* if they are the same */
9575 if (operandsEqu (left, result)) {
9576 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9582 /* if they are the same registers */
9583 if (pic16_sameRegs(AOP(left),AOP(result))) {
9584 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9590 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9591 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9592 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9599 if ( AOP_TYPE(left) == AOP_PCODE) {
9600 fprintf(stderr,"genDataPointerGet %s, %d\n",
9601 AOP(left)->aopu.pcop->name,
9602 (AOP(left)->aopu.pcop->type == PO_DIR)?
9603 PCOR(AOP(left)->aopu.pcop)->instance:
9604 PCOI(AOP(left)->aopu.pcop)->offset);
9608 if(AOP(left)->aopu.pcop->type == PO_DIR)
9609 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9611 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9614 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9616 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9617 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9618 mov2w(AOP(left), offset); // patch 8
9619 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9621 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9622 pic16_popGet(AOP(left), offset), //patch 8
9623 pic16_popGet(AOP(result), offset)));
9631 pic16_freeAsmop(result,NULL,ic,TRUE);
9636 /*-----------------------------------------------------------------*/
9637 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9638 /*-----------------------------------------------------------------*/
9639 static void genNearPointerGet (operand *left,
9644 //regs *preg = NULL ;
9645 sym_link *rtype, *retype;
9646 sym_link *ltype = operandType(left);
9648 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9649 rtype = operandType(result);
9650 retype= getSpec(rtype);
9652 pic16_aopOp(left,ic,FALSE);
9654 // pic16_DumpOp("(left)",left);
9655 // pic16_DumpOp("(result)",result);
9657 /* if left is rematerialisable and
9658 * result is not bit variable type and
9659 * the left is pointer to data space i.e
9660 * lower 128 bytes of space */
9661 if (AOP_TYPE(left) == AOP_PCODE
9662 && !IS_BITFIELD(retype)
9663 && DCL_TYPE(ltype) == POINTER) {
9665 genDataPointerGet (left,result,ic);
9666 pic16_freeAsmop(left, NULL, ic, TRUE);
9670 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9672 /* if the value is already in a pointer register
9673 * then don't need anything more */
9674 if (!AOP_INPREG(AOP(left))) {
9675 /* otherwise get a free pointer register */
9676 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9678 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9679 if( (AOP_TYPE(left) == AOP_PCODE)
9680 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9681 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9683 if(!IS_BITFIELD(retype))
9684 pic16_loadFSR0( left ); // patch 10
9686 // set up FSR0 with address from left
9687 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9688 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9692 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9694 pic16_aopOp (result,ic,FALSE);
9696 /* if bitfield then unpack the bits */
9697 if (IS_BITFIELD(retype))
9698 genUnpackBits (result, left, NULL, POINTER);
9700 /* we have can just get the values */
9701 int size = AOP_SIZE(result);
9704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9707 /* fsr0 is loaded already -- VR */
9708 // pic16_loadFSR0( left );
9710 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9711 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9715 pic16_emitpcode(POC_MOVFF,
9716 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9717 pic16_popGet(AOP(result), offset++)));
9719 pic16_emitpcode(POC_MOVFF,
9720 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9721 pic16_popGet(AOP(result), offset++)));
9725 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9726 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9728 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9732 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9734 pic16_emitcode("mov","a,@%s",rname);
9735 pic16_aopPut(AOP(result),"a",offset);
9737 sprintf(buffer,"@%s",rname);
9738 pic16_aopPut(AOP(result),buffer,offset);
9742 pic16_emitcode("inc","%s",rname);
9747 /* now some housekeeping stuff */
9749 /* we had to allocate for this iCode */
9750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9751 pic16_freeAsmop(NULL,aop,ic,TRUE);
9753 /* we did not allocate which means left
9754 already in a pointer register, then
9755 if size > 0 && this could be used again
9756 we have to point it back to where it
9758 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9759 if (AOP_SIZE(result) > 1 &&
9760 !OP_SYMBOL(left)->remat &&
9761 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9763 // int size = AOP_SIZE(result) - 1;
9765 // pic16_emitcode("dec","%s",rname);
9770 pic16_freeAsmop(left,NULL,ic,TRUE);
9771 pic16_freeAsmop(result,NULL,ic,TRUE);
9775 /*-----------------------------------------------------------------*/
9776 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9777 /*-----------------------------------------------------------------*/
9778 static void genPagedPointerGet (operand *left,
9785 sym_link *rtype, *retype;
9787 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9789 rtype = operandType(result);
9790 retype= getSpec(rtype);
9792 pic16_aopOp(left,ic,FALSE);
9794 /* if the value is already in a pointer register
9795 then don't need anything more */
9796 if (!AOP_INPREG(AOP(left))) {
9797 /* otherwise get a free pointer register */
9799 preg = getFreePtr(ic,&aop,FALSE);
9800 pic16_emitcode("mov","%s,%s",
9802 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9803 rname = preg->name ;
9805 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9807 pic16_freeAsmop(left,NULL,ic,TRUE);
9808 pic16_aopOp (result,ic,FALSE);
9810 /* if bitfield then unpack the bits */
9811 if (IS_BITFIELD(retype))
9812 genUnpackBits (result,left,rname,PPOINTER);
9814 /* we have can just get the values */
9815 int size = AOP_SIZE(result);
9820 pic16_emitcode("movx","a,@%s",rname);
9821 pic16_aopPut(AOP(result),"a",offset);
9826 pic16_emitcode("inc","%s",rname);
9830 /* now some housekeeping stuff */
9832 /* we had to allocate for this iCode */
9833 pic16_freeAsmop(NULL,aop,ic,TRUE);
9835 /* we did not allocate which means left
9836 already in a pointer register, then
9837 if size > 0 && this could be used again
9838 we have to point it back to where it
9840 if (AOP_SIZE(result) > 1 &&
9841 !OP_SYMBOL(left)->remat &&
9842 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9844 int size = AOP_SIZE(result) - 1;
9846 pic16_emitcode("dec","%s",rname);
9851 pic16_freeAsmop(result,NULL,ic,TRUE);
9856 /*-----------------------------------------------------------------*/
9857 /* genFarPointerGet - gget value from far space */
9858 /*-----------------------------------------------------------------*/
9859 static void genFarPointerGet (operand *left,
9860 operand *result, iCode *ic)
9863 sym_link *retype = getSpec(operandType(result));
9865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9867 pic16_aopOp(left,ic,FALSE);
9869 /* if the operand is already in dptr
9870 then we do nothing else we move the value to dptr */
9871 if (AOP_TYPE(left) != AOP_STR) {
9872 /* if this is remateriazable */
9873 if (AOP_TYPE(left) == AOP_IMMD)
9874 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9875 else { /* we need to get it byte by byte */
9876 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9877 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9878 if (options.model == MODEL_FLAT24)
9880 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9884 /* so dptr know contains the address */
9885 pic16_freeAsmop(left,NULL,ic,TRUE);
9886 pic16_aopOp(result,ic,FALSE);
9888 /* if bit then unpack */
9889 if (IS_BITFIELD(retype))
9890 genUnpackBits(result,left,"dptr",FPOINTER);
9892 size = AOP_SIZE(result);
9896 pic16_emitcode("movx","a,@dptr");
9897 pic16_aopPut(AOP(result),"a",offset++);
9899 pic16_emitcode("inc","dptr");
9903 pic16_freeAsmop(result,NULL,ic,TRUE);
9906 /*-----------------------------------------------------------------*/
9907 /* genCodePointerGet - get value from code space */
9908 /*-----------------------------------------------------------------*/
9909 static void genCodePointerGet (operand *left,
9910 operand *result, iCode *ic)
9913 sym_link *retype = getSpec(operandType(result));
9915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9917 pic16_aopOp(left,ic,FALSE);
9919 /* if the operand is already in dptr
9920 then we do nothing else we move the value to dptr */
9921 if (AOP_TYPE(left) != AOP_STR) {
9922 /* if this is remateriazable */
9923 if (AOP_TYPE(left) == AOP_IMMD)
9924 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9925 else { /* we need to get it byte by byte */
9926 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9927 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9928 if (options.model == MODEL_FLAT24)
9930 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9934 /* so dptr know contains the address */
9935 pic16_freeAsmop(left,NULL,ic,TRUE);
9936 pic16_aopOp(result,ic,FALSE);
9938 /* if bit then unpack */
9939 if (IS_BITFIELD(retype))
9940 genUnpackBits(result,left,"dptr",CPOINTER);
9942 size = AOP_SIZE(result);
9946 pic16_emitcode("clr","a");
9947 pic16_emitcode("movc","a,@a+dptr");
9948 pic16_aopPut(AOP(result),"a",offset++);
9950 pic16_emitcode("inc","dptr");
9954 pic16_freeAsmop(result,NULL,ic,TRUE);
9958 /*-----------------------------------------------------------------*/
9959 /* genGenPointerGet - gget value from generic pointer space */
9960 /*-----------------------------------------------------------------*/
9961 static void genGenPointerGet (operand *left,
9962 operand *result, iCode *ic)
9964 int size, offset, lit;
9965 sym_link *retype = getSpec(operandType(result));
9967 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9968 pic16_aopOp(left,ic,FALSE);
9969 pic16_aopOp(result,ic,FALSE);
9970 size = AOP_SIZE(result);
9972 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9974 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9976 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9977 // load FSR0 from immediate
9978 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9980 // pic16_loadFSR0( left );
9985 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9987 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9994 else { /* we need to get it byte by byte */
9995 // set up FSR0 with address from left
9996 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9997 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10003 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10005 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10012 /* if bit then unpack */
10013 if (IS_BITFIELD(retype))
10014 genUnpackBits(result,left,"BAD",GPOINTER);
10017 pic16_freeAsmop(left,NULL,ic,TRUE);
10018 pic16_freeAsmop(result,NULL,ic,TRUE);
10023 extern set *externs;
10025 /*-----------------------------------------------------------------*/
10026 /* genGenPointerGet - gget value from generic pointer space */
10027 /*-----------------------------------------------------------------*/
10028 static void genGenPointerGet (operand *left,
10029 operand *result, iCode *ic)
10031 int size, offset, lit;
10032 sym_link *retype = getSpec(operandType(result));
10035 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10036 pic16_aopOp(left,ic,FALSE);
10037 pic16_aopOp(result,ic,FALSE);
10038 size = AOP_SIZE(result);
10040 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10042 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10044 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10045 // load FSR0 from immediate
10046 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10048 werror(W_POSSBUG2, __FILE__, __LINE__);
10053 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10055 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10062 } else { /* we need to get it byte by byte */
10064 /* set up WREG:PRODL:FSR0L with address from left */
10065 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10066 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10067 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10070 case 1: strcpy(fgptrget, "__gptrget1"); break;
10071 case 2: strcpy(fgptrget, "__gptrget2"); break;
10072 case 3: strcpy(fgptrget, "__gptrget3"); break;
10073 case 4: strcpy(fgptrget, "__gptrget4"); break;
10075 werror(W_POSSBUG2, __FILE__, __LINE__);
10079 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10081 assignResultValue(result, 1);
10086 sym = newSymbol( fgptrget, 0 );
10087 strcpy(sym->rname, fgptrget);
10088 checkAddSym(&externs, sym);
10090 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10096 /* if bit then unpack */
10097 if (IS_BITFIELD(retype))
10098 genUnpackBits(result,left,"BAD",GPOINTER);
10101 pic16_freeAsmop(left,NULL,ic,TRUE);
10102 pic16_freeAsmop(result,NULL,ic,TRUE);
10105 /*-----------------------------------------------------------------*/
10106 /* genConstPointerGet - get value from const generic pointer space */
10107 /*-----------------------------------------------------------------*/
10108 static void genConstPointerGet (operand *left,
10109 operand *result, iCode *ic)
10111 //sym_link *retype = getSpec(operandType(result));
10112 // symbol *albl = newiTempLabel(NULL); // patch 15
10113 // symbol *blbl = newiTempLabel(NULL); //
10114 // PIC_OPCODE poc; // patch 15
10118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10119 pic16_aopOp(left,ic,FALSE);
10120 pic16_aopOp(result,ic,TRUE);
10121 size = AOP_SIZE(result);
10123 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10125 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10127 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10128 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10129 pic16_emitpLabel(albl->key);
10131 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
10133 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
10134 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
10135 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
10136 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
10137 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
10139 pic16_emitpLabel(blbl->key);
10141 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
10145 // set up table pointer
10146 if( (AOP_TYPE(left) == AOP_PCODE)
10147 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
10148 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
10150 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
10151 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10152 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
10153 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10154 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
10155 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10159 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
10160 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
10161 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
10167 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10168 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
10172 pic16_freeAsmop(left,NULL,ic,TRUE);
10173 pic16_freeAsmop(result,NULL,ic,TRUE);
10178 /*-----------------------------------------------------------------*/
10179 /* genPointerGet - generate code for pointer get */
10180 /*-----------------------------------------------------------------*/
10181 static void genPointerGet (iCode *ic)
10183 operand *left, *result ;
10184 sym_link *type, *etype;
10187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10189 left = IC_LEFT(ic);
10190 result = IC_RESULT(ic) ;
10192 /* depending on the type of pointer we need to
10193 move it to the correct pointer register */
10194 type = operandType(left);
10195 etype = getSpec(type);
10198 if (IS_PTR_CONST(type))
10200 if (IS_CODEPTR(type))
10202 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
10204 /* if left is of type of pointer then it is simple */
10205 if (IS_PTR(type) && !IS_FUNC(type->next))
10206 p_type = DCL_TYPE(type);
10208 /* we have to go by the storage class */
10209 p_type = PTR_TYPE(SPEC_OCLS(etype));
10211 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
10213 if (SPEC_OCLS(etype)->codesp ) {
10214 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
10215 //p_type = CPOINTER ;
10218 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
10219 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
10220 /*p_type = FPOINTER ;*/
10222 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
10223 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
10224 /* p_type = PPOINTER; */
10226 if (SPEC_OCLS(etype) == idata )
10227 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
10228 /* p_type = IPOINTER; */
10230 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
10231 /* p_type = POINTER ; */
10234 /* now that we have the pointer type we assign
10235 the pointer values */
10240 genNearPointerGet (left,result,ic);
10244 genPagedPointerGet(left,result,ic);
10248 genFarPointerGet (left,result,ic);
10252 genConstPointerGet (left,result,ic);
10253 //pic16_emitcodePointerGet (left,result,ic);
10258 if (IS_PTR_CONST(type))
10259 genConstPointerGet (left,result,ic);
10262 genGenPointerGet (left,result,ic);
10266 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10267 "genPointerGet: illegal pointer type");
10273 /*-----------------------------------------------------------------*/
10274 /* genPackBits - generates code for packed bit storage */
10275 /*-----------------------------------------------------------------*/
10276 static void genPackBits (sym_link *etype , operand *result,
10278 char *rname, int p_type)
10286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10287 blen = SPEC_BLEN(etype);
10288 bstr = SPEC_BSTR(etype);
10290 if(AOP_TYPE(right) == AOP_LIT) {
10291 if((blen == 1) && (bstr < 8)) {
10293 /* it is a single bit, so use the appropriate bit instructions */
10295 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
10297 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10298 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10299 if((p_type == POINTER) && (result)) {
10300 /* workaround to reduce the extra lfsr instruction */
10302 pic16_emitpcode(POC_BSF,
10303 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10305 pic16_emitpcode(POC_BCF,
10306 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10311 pic16_emitpcode(POC_BSF,
10312 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10314 pic16_emitpcode(POC_BCF,
10315 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10322 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10325 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10327 /* if the bit lenth is less than or */
10328 /* it exactly fits a byte then */
10329 if((shCnt=SPEC_BSTR(etype))
10330 || SPEC_BLEN(etype) <= 8 ) {
10332 /* shift left acc */
10335 /* using PRODL as a temporary register here */
10336 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10342 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10343 // pic16_emitcode ("mov","b,a");
10344 // pic16_emitcode("mov","a,@%s",rname);
10348 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10349 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10350 (unsigned char)(0xff >> (8-bstr))) ));
10351 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10352 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10359 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10360 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10365 if ( SPEC_BLEN(etype) <= 8 )
10368 pic16_emitcode("inc","%s",rname);
10369 rLen = SPEC_BLEN(etype) ;
10373 /* now generate for lengths greater than one byte */
10376 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10386 pic16_emitcode("mov","@%s,a",rname);
10388 pic16_emitcode("mov","@%s,%s",rname,l);
10393 pic16_emitcode("movx","@dptr,a");
10398 DEBUGpic16_emitcode(";lcall","__gptrput");
10401 pic16_emitcode ("inc","%s",rname);
10406 /* last last was not complete */
10408 /* save the byte & read byte */
10411 pic16_emitcode ("mov","b,a");
10412 pic16_emitcode("mov","a,@%s",rname);
10416 pic16_emitcode ("mov","b,a");
10417 pic16_emitcode("movx","a,@dptr");
10421 pic16_emitcode ("push","b");
10422 pic16_emitcode ("push","acc");
10423 pic16_emitcode ("lcall","__gptrget");
10424 pic16_emitcode ("pop","b");
10428 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10429 pic16_emitcode ("orl","a,b");
10432 if (p_type == GPOINTER)
10433 pic16_emitcode("pop","b");
10438 pic16_emitcode("mov","@%s,a",rname);
10442 pic16_emitcode("movx","@dptr,a");
10446 DEBUGpic16_emitcode(";lcall","__gptrput");
10450 /*-----------------------------------------------------------------*/
10451 /* genDataPointerSet - remat pointer to data space */
10452 /*-----------------------------------------------------------------*/
10453 static void genDataPointerSet(operand *right,
10457 int size, offset = 0, resoffset=0 ;
10459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10460 pic16_aopOp(right,ic,FALSE);
10462 size = AOP_SIZE(right);
10464 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10467 if ( AOP_TYPE(result) == AOP_PCODE) {
10468 fprintf(stderr,"genDataPointerSet %s, %d\n",
10469 AOP(result)->aopu.pcop->name,
10470 (AOP(result)->aopu.pcop->type == PO_DIR)?
10471 PCOR(AOP(result)->aopu.pcop)->instance:
10472 PCOI(AOP(result)->aopu.pcop)->offset);
10476 if(AOP(result)->aopu.pcop->type == PO_DIR)
10477 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10480 if (AOP_TYPE(right) == AOP_LIT) {
10481 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10483 lit = lit >> (8*offset);
10485 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10486 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10488 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10491 mov2w(AOP(right), offset);
10492 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10498 pic16_freeAsmop(right,NULL,ic,TRUE);
10503 /*-----------------------------------------------------------------*/
10504 /* genNearPointerSet - pic16_emitcode for near pointer put */
10505 /*-----------------------------------------------------------------*/
10506 static void genNearPointerSet (operand *right,
10513 sym_link *ptype = operandType(result);
10514 sym_link *resetype;
10516 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10517 retype= getSpec(operandType(right));
10518 resetype = getSpec(operandType(result));
10520 pic16_aopOp(result,ic,FALSE);
10522 /* if the result is rematerializable &
10523 * in data space & not a bit variable */
10525 /* and result is not a bit variable */
10526 if (AOP_TYPE(result) == AOP_PCODE
10527 // && AOP_TYPE(result) == AOP_IMMD
10528 && DCL_TYPE(ptype) == POINTER
10529 && !IS_BITFIELD(retype)
10530 && !IS_BITFIELD(resetype)) {
10532 genDataPointerSet (right,result,ic);
10533 pic16_freeAsmop(result,NULL,ic,TRUE);
10537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10538 pic16_aopOp(right,ic,FALSE);
10539 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10541 /* if the value is already in a pointer register
10542 * then don't need anything more */
10543 if (!AOP_INPREG(AOP(result))) {
10544 /* otherwise get a free pointer register */
10545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10547 if( (AOP_TYPE(result) == AOP_PCODE)
10548 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10549 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10551 if(!IS_BITFIELD(resetype))
10552 pic16_loadFSR0( result ); // patch 10
10554 // set up FSR0 with address of result
10555 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10556 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10561 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10565 /* if bitfield then unpack the bits */
10566 if (IS_BITFIELD(resetype)) {
10567 genPackBits (resetype, result, right, NULL, POINTER);
10569 /* we have can just get the values */
10570 int size = AOP_SIZE(right);
10573 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10575 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10578 //pic16_emitcode("mov","@%s,a",rname);
10579 pic16_emitcode("movf","indf0,w ;1");
10582 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10583 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10585 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10587 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10589 } else { // no literal //
10591 pic16_emitpcode(POC_MOVFF, //
10592 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10593 pic16_popCopyReg(&pic16_pc_postinc0))); //
10595 pic16_emitpcode(POC_MOVFF, //
10596 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10597 pic16_popCopyReg(&pic16_pc_indf0))); //
10605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10606 /* now some housekeeping stuff */
10608 /* we had to allocate for this iCode */
10609 pic16_freeAsmop(NULL,aop,ic,TRUE);
10611 /* we did not allocate which means left
10612 * already in a pointer register, then
10613 * if size > 0 && this could be used again
10614 * we have to point it back to where it
10616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10617 if (AOP_SIZE(right) > 1
10618 && !OP_SYMBOL(result)->remat
10619 && ( OP_SYMBOL(result)->liveTo > ic->seq
10622 int size = AOP_SIZE(right) - 1;
10625 pic16_emitcode("decf","fsr0,f");
10626 //pic16_emitcode("dec","%s",rname);
10630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10633 pic16_freeAsmop(right,NULL,ic,TRUE);
10634 pic16_freeAsmop(result,NULL,ic,TRUE);
10637 /*-----------------------------------------------------------------*/
10638 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10639 /*-----------------------------------------------------------------*/
10640 static void genPagedPointerSet (operand *right,
10645 regs *preg = NULL ;
10649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10651 retype= getSpec(operandType(right));
10653 pic16_aopOp(result,ic,FALSE);
10655 /* if the value is already in a pointer register
10656 then don't need anything more */
10657 if (!AOP_INPREG(AOP(result))) {
10658 /* otherwise get a free pointer register */
10660 preg = getFreePtr(ic,&aop,FALSE);
10661 pic16_emitcode("mov","%s,%s",
10663 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10664 rname = preg->name ;
10666 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10668 pic16_freeAsmop(result,NULL,ic,TRUE);
10669 pic16_aopOp (right,ic,FALSE);
10671 /* if bitfield then unpack the bits */
10672 if (IS_BITFIELD(retype))
10673 genPackBits (retype,result,right,rname,PPOINTER);
10675 /* we have can just get the values */
10676 int size = AOP_SIZE(right);
10680 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10683 pic16_emitcode("movx","@%s,a",rname);
10686 pic16_emitcode("inc","%s",rname);
10692 /* now some housekeeping stuff */
10694 /* we had to allocate for this iCode */
10695 pic16_freeAsmop(NULL,aop,ic,TRUE);
10697 /* we did not allocate which means left
10698 already in a pointer register, then
10699 if size > 0 && this could be used again
10700 we have to point it back to where it
10702 if (AOP_SIZE(right) > 1 &&
10703 !OP_SYMBOL(result)->remat &&
10704 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10706 int size = AOP_SIZE(right) - 1;
10708 pic16_emitcode("dec","%s",rname);
10713 pic16_freeAsmop(right,NULL,ic,TRUE);
10718 /*-----------------------------------------------------------------*/
10719 /* genFarPointerSet - set value from far space */
10720 /*-----------------------------------------------------------------*/
10721 static void genFarPointerSet (operand *right,
10722 operand *result, iCode *ic)
10725 sym_link *retype = getSpec(operandType(right));
10727 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10728 pic16_aopOp(result,ic,FALSE);
10730 /* if the operand is already in dptr
10731 then we do nothing else we move the value to dptr */
10732 if (AOP_TYPE(result) != AOP_STR) {
10733 /* if this is remateriazable */
10734 if (AOP_TYPE(result) == AOP_IMMD)
10735 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10736 else { /* we need to get it byte by byte */
10737 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10738 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10739 if (options.model == MODEL_FLAT24)
10741 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10745 /* so dptr know contains the address */
10746 pic16_freeAsmop(result,NULL,ic,TRUE);
10747 pic16_aopOp(right,ic,FALSE);
10749 /* if bit then unpack */
10750 if (IS_BITFIELD(retype))
10751 genPackBits(retype,result,right,"dptr",FPOINTER);
10753 size = AOP_SIZE(right);
10757 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10759 pic16_emitcode("movx","@dptr,a");
10761 pic16_emitcode("inc","dptr");
10765 pic16_freeAsmop(right,NULL,ic,TRUE);
10768 /*-----------------------------------------------------------------*/
10769 /* genGenPointerSet - set value from generic pointer space */
10770 /*-----------------------------------------------------------------*/
10772 static void genGenPointerSet (operand *right,
10773 operand *result, iCode *ic)
10775 int i, size, offset, lit;
10776 sym_link *retype = getSpec(operandType(right));
10778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10780 pic16_aopOp(result,ic,FALSE);
10781 pic16_aopOp(right,ic,FALSE);
10782 size = AOP_SIZE(right);
10785 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10787 /* if the operand is already in dptr
10788 then we do nothing else we move the value to dptr */
10789 if (AOP_TYPE(result) != AOP_STR) {
10790 /* if this is remateriazable */
10791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10792 // WARNING: anythig until "else" is untested!
10793 if (AOP_TYPE(result) == AOP_IMMD) {
10794 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10795 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10796 // load FSR0 from immediate
10797 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10801 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10803 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10809 else { /* we need to get it byte by byte */
10810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10811 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10813 // set up FSR0 with address of result
10814 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10815 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10817 /* hack hack! see if this the FSR. If so don't load W */
10818 if(AOP_TYPE(right) != AOP_ACC) {
10820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10822 if(AOP_TYPE(right) == AOP_LIT)
10825 // note: pic16_popGet handles sign extension
10826 for(i=0;i<size;i++) {
10827 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10829 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10831 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10836 for(i=0;i<size;i++) {
10838 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10839 pic16_popCopyReg(&pic16_pc_postinc0)));
10841 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10842 pic16_popCopyReg(&pic16_pc_indf0)));
10848 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10849 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10851 } // if (AOP_TYPE(result) != AOP_IMMD)
10853 } // if (AOP_TYPE(result) != AOP_STR)
10854 /* so dptr know contains the address */
10857 /* if bit then unpack */
10858 if (IS_BITFIELD(retype))
10859 genPackBits(retype,result,right,"dptr",GPOINTER);
10861 size = AOP_SIZE(right);
10864 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10866 // set up FSR0 with address of result
10867 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10871 if (AOP_TYPE(right) == AOP_LIT) {
10872 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10874 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10876 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10878 } else { // no literal
10880 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10882 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10890 pic16_freeAsmop(right,NULL,ic,TRUE);
10891 pic16_freeAsmop(result,NULL,ic,TRUE);
10895 static void genGenPointerSet (operand *right,
10896 operand *result, iCode *ic)
10899 sym_link *retype = getSpec(operandType(right));
10902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10904 pic16_aopOp(result,ic,FALSE);
10905 pic16_aopOp(right,ic,FALSE);
10906 size = AOP_SIZE(right);
10908 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10911 /* if bit then unpack */
10912 if (IS_BITFIELD(retype)) {
10913 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10914 genPackBits(retype,result,right,"dptr",GPOINTER);
10918 size = AOP_SIZE(right);
10920 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10924 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
10926 /* value of right+0 is placed on stack, which will be retrieved
10927 * by the support function this restoring the stack. The important
10928 * thing is that there is no need to manually restore stack pointer
10930 mov2fp(pic16_popCopyReg(&pic16_pc_gptrreg), AOP(right), 0);
10931 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
10932 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
10933 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
10935 /* load address to write to in WREG:FSR0H:FSR0L */
10936 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
10937 pic16_popCopyReg(&pic16_pc_fsr0l)));
10938 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
10939 pic16_popCopyReg(&pic16_pc_prodl)));
10940 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
10943 /* put code here */
10945 case 1: strcpy(fgptrput, "__gptrput1"); break;
10946 case 2: strcpy(fgptrput, "__gptrput2"); break;
10947 case 3: strcpy(fgptrput, "__gptrput3"); break;
10948 case 4: strcpy(fgptrput, "__gptrput4"); break;
10950 werror(W_POSSBUG2, __FILE__, __LINE__);
10954 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
10959 sym = newSymbol( fgptrput, 0 );
10960 strcpy(sym->rname, fgptrput);
10961 checkAddSym(&externs, sym);
10964 sym = newSymbol("__GPTRREG", 0);
10965 strcpy(sym->rname, "__GPTRREG");
10966 checkAddSym(&externs, sym);
10969 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10973 pic16_freeAsmop(right,NULL,ic,TRUE);
10974 pic16_freeAsmop(result,NULL,ic,TRUE);
10977 /*-----------------------------------------------------------------*/
10978 /* genPointerSet - stores the value into a pointer location */
10979 /*-----------------------------------------------------------------*/
10980 static void genPointerSet (iCode *ic)
10982 operand *right, *result ;
10983 sym_link *type, *etype;
10986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10988 right = IC_RIGHT(ic);
10989 result = IC_RESULT(ic) ;
10991 /* depending on the type of pointer we need to
10992 move it to the correct pointer register */
10993 type = operandType(result);
10994 etype = getSpec(type);
10995 /* if left is of type of pointer then it is simple */
10996 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10997 p_type = DCL_TYPE(type);
11000 /* we have to go by the storage class */
11001 p_type = PTR_TYPE(SPEC_OCLS(etype));
11003 /* if (SPEC_OCLS(etype)->codesp ) { */
11004 /* p_type = CPOINTER ; */
11007 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11008 /* p_type = FPOINTER ; */
11010 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11011 /* p_type = PPOINTER ; */
11013 /* if (SPEC_OCLS(etype) == idata ) */
11014 /* p_type = IPOINTER ; */
11016 /* p_type = POINTER ; */
11019 /* now that we have the pointer type we assign
11020 the pointer values */
11025 genNearPointerSet (right,result,ic);
11029 genPagedPointerSet (right,result,ic);
11033 genFarPointerSet (right,result,ic);
11037 genGenPointerSet (right,result,ic);
11041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11042 "genPointerSet: illegal pointer type");
11046 /*-----------------------------------------------------------------*/
11047 /* genIfx - generate code for Ifx statement */
11048 /*-----------------------------------------------------------------*/
11049 static void genIfx (iCode *ic, iCode *popIc)
11051 operand *cond = IC_COND(ic);
11054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11056 pic16_aopOp(cond,ic,FALSE);
11058 /* get the value into acc */
11059 if (AOP_TYPE(cond) != AOP_CRY)
11060 pic16_toBoolean(cond);
11063 /* the result is now in the accumulator */
11064 pic16_freeAsmop(cond,NULL,ic,TRUE);
11066 /* if there was something to be popped then do it */
11070 /* if the condition is a bit variable */
11071 if (isbit && IS_ITEMP(cond) &&
11073 genIfxJump(ic,SPIL_LOC(cond)->rname);
11074 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11077 if (isbit && !IS_ITEMP(cond))
11078 genIfxJump(ic,OP_SYMBOL(cond)->rname);
11080 genIfxJump(ic,"a");
11086 /*-----------------------------------------------------------------*/
11087 /* genAddrOf - generates code for address of */
11088 /*-----------------------------------------------------------------*/
11089 static void genAddrOf (iCode *ic)
11091 operand *result, *left;
11093 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
11094 pCodeOp *pcop0, *pcop1, *pcop2;
11096 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11098 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
11100 sym = OP_SYMBOL( IC_LEFT(ic) );
11103 /* get address of symbol on stack */
11104 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
11106 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
11107 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
11110 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11111 pic16_popCopyReg(&pic16_pc_fsr2l),
11112 pic16_popGet(AOP(result), 0)));
11113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11114 pic16_popCopyReg(&pic16_pc_fsr2h),
11115 pic16_popGet(AOP(result), 1)));
11117 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
11118 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
11120 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
11125 // if(pic16_debug_verbose) {
11126 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
11127 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
11130 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
11131 size = AOP_SIZE(IC_RESULT(ic));
11134 /* Assume that what we want the address of is in data space
11135 * since there is no stack on the PIC, yet! -- VR */
11137 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11138 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11139 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11142 pic16_emitpcode(POC_MOVLW, pcop0);
11143 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11144 pic16_emitpcode(POC_MOVLW, pcop1);
11145 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11146 pic16_emitpcode(POC_MOVLW, pcop2);
11147 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11150 pic16_emitpcode(POC_MOVLW, pcop0);
11151 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11152 pic16_emitpcode(POC_MOVLW, pcop1);
11153 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11155 pic16_emitpcode(POC_MOVLW, pcop0);
11156 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11159 pic16_freeAsmop(left, NULL, ic, FALSE);
11161 pic16_freeAsmop(result,NULL,ic,TRUE);
11166 /*-----------------------------------------------------------------*/
11167 /* genFarFarAssign - assignment when both are in far space */
11168 /*-----------------------------------------------------------------*/
11169 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
11171 int size = AOP_SIZE(right);
11174 /* first push the right side on to the stack */
11176 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11178 pic16_emitcode ("push","acc");
11181 pic16_freeAsmop(right,NULL,ic,FALSE);
11182 /* now assign DPTR to result */
11183 pic16_aopOp(result,ic,FALSE);
11184 size = AOP_SIZE(result);
11186 pic16_emitcode ("pop","acc");
11187 pic16_aopPut(AOP(result),"a",--offset);
11189 pic16_freeAsmop(result,NULL,ic,FALSE);
11194 /*-----------------------------------------------------------------*/
11195 /* genAssign - generate code for assignment */
11196 /*-----------------------------------------------------------------*/
11197 static void genAssign (iCode *ic)
11199 operand *result, *right;
11200 int size, offset,know_W;
11201 unsigned long lit = 0L;
11203 result = IC_RESULT(ic);
11204 right = IC_RIGHT(ic) ;
11206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11208 /* if they are the same */
11209 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
11212 /* reversed order operands are aopOp'ed so that result operand
11213 * is effective in case right is a stack symbol. This maneauver
11214 * allows to use the _G.resDirect flag later */
11215 pic16_aopOp(result,ic,TRUE);
11216 pic16_aopOp(right,ic,FALSE);
11218 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11220 /* if they are the same registers */
11221 if (pic16_sameRegs(AOP(right),AOP(result)))
11224 /* if the result is a bit */
11225 if (AOP_TYPE(result) == AOP_CRY) {
11226 /* if the right size is a literal then
11227 we know what the value is */
11228 if (AOP_TYPE(right) == AOP_LIT) {
11230 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11231 pic16_popGet(AOP(result),0));
11233 if (((int) operandLitValue(right)))
11234 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11235 AOP(result)->aopu.aop_dir,
11236 AOP(result)->aopu.aop_dir);
11238 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11239 AOP(result)->aopu.aop_dir,
11240 AOP(result)->aopu.aop_dir);
11244 /* the right is also a bit variable */
11245 if (AOP_TYPE(right) == AOP_CRY) {
11246 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11247 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11248 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11250 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
11251 AOP(result)->aopu.aop_dir,
11252 AOP(result)->aopu.aop_dir);
11253 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
11254 AOP(right)->aopu.aop_dir,
11255 AOP(right)->aopu.aop_dir);
11256 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
11257 AOP(result)->aopu.aop_dir,
11258 AOP(result)->aopu.aop_dir);
11262 /* we need to or */
11263 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11264 pic16_toBoolean(right);
11266 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11267 //pic16_aopPut(AOP(result),"a",0);
11271 /* bit variables done */
11273 size = AOP_SIZE(result);
11276 if(AOP_TYPE(right) == AOP_LIT) {
11277 if(!IS_FLOAT(operandType( right )))
11278 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11281 unsigned long lit_int;
11285 /* take care if literal is a float */
11286 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
11287 lit = info.lit_int;
11291 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
11292 // sizeof(unsigned long int), sizeof(float));
11294 if(AOP_TYPE(right) != AOP_LIT
11295 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
11296 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
11297 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
11299 // set up table pointer
11300 if( (AOP_TYPE(right) == AOP_PCODE)
11301 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
11302 || (AOP(right)->aopu.pcop->type == PO_DIR)))
11304 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
11305 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
11306 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11307 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
11308 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11309 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
11310 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11312 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
11313 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
11314 pic16_popCopyReg(&pic16_pc_tblptrl)));
11315 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
11316 pic16_popCopyReg(&pic16_pc_tblptrh)));
11317 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
11318 pic16_popCopyReg(&pic16_pc_tblptru)));
11321 size = min(AOP_SIZE(right), AOP_SIZE(result));
11323 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11324 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
11325 pic16_popGet(AOP(result),offset)));
11329 if(AOP_SIZE(result) > AOP_SIZE(right)) {
11330 size = AOP_SIZE(result) - AOP_SIZE(right);
11332 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
11342 /* VR - What is this?! */
11343 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
11344 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11345 if(aopIdx(AOP(result),0) == 4) {
11347 /* this is a workaround to save value of right into wreg too,
11348 * value of wreg is going to be used later */
11349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11350 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11351 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11355 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
11361 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
11362 if(AOP_TYPE(right) == AOP_LIT) {
11364 if(know_W != (lit&0xff))
11365 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
11367 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11369 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11373 } else if (AOP_TYPE(right) == AOP_CRY) {
11374 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11376 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
11377 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11379 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
11380 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11385 if(!_G.resDirect) /* use this aopForSym feature */
11386 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11393 pic16_freeAsmop (right,NULL,ic,FALSE);
11394 pic16_freeAsmop (result,NULL,ic,TRUE);
11397 /*-----------------------------------------------------------------*/
11398 /* genJumpTab - generates code for jump table */
11399 /*-----------------------------------------------------------------*/
11400 static void genJumpTab (iCode *ic)
11405 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11407 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11408 /* get the condition into accumulator */
11409 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11411 /* multiply by three */
11412 pic16_emitcode("add","a,acc");
11413 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11415 jtab = newiTempLabel(NULL);
11416 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11417 pic16_emitcode("jmp","@a+dptr");
11418 pic16_emitcode("","%05d_DS_:",jtab->key+100);
11420 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11421 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11423 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11424 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11425 pic16_emitpLabel(jtab->key);
11427 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11429 /* now generate the jump labels */
11430 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11431 jtab = setNextItem(IC_JTLABELS(ic))) {
11432 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11433 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11439 /*-----------------------------------------------------------------*/
11440 /* genMixedOperation - gen code for operators between mixed types */
11441 /*-----------------------------------------------------------------*/
11443 TSD - Written for the PIC port - but this unfortunately is buggy.
11444 This routine is good in that it is able to efficiently promote
11445 types to different (larger) sizes. Unfortunately, the temporary
11446 variables that are optimized out by this routine are sometimes
11447 used in other places. So until I know how to really parse the
11448 iCode tree, I'm going to not be using this routine :(.
11450 static int genMixedOperation (iCode *ic)
11453 operand *result = IC_RESULT(ic);
11454 sym_link *ctype = operandType(IC_LEFT(ic));
11455 operand *right = IC_RIGHT(ic);
11461 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11463 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11469 nextright = IC_RIGHT(nextic);
11470 nextleft = IC_LEFT(nextic);
11471 nextresult = IC_RESULT(nextic);
11473 pic16_aopOp(right,ic,FALSE);
11474 pic16_aopOp(result,ic,FALSE);
11475 pic16_aopOp(nextright, nextic, FALSE);
11476 pic16_aopOp(nextleft, nextic, FALSE);
11477 pic16_aopOp(nextresult, nextic, FALSE);
11479 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11481 operand *t = right;
11485 pic16_emitcode(";remove right +","");
11487 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11489 operand *t = right;
11493 pic16_emitcode(";remove left +","");
11497 big = AOP_SIZE(nextleft);
11498 small = AOP_SIZE(nextright);
11500 switch(nextic->op) {
11503 pic16_emitcode(";optimize a +","");
11504 /* if unsigned or not an integral type */
11505 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11506 pic16_emitcode(";add a bit to something","");
11509 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11511 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11512 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11513 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11515 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11523 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11524 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11525 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11528 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11530 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11531 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11532 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11533 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11534 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11537 pic16_emitcode("rlf","known_zero,w");
11544 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11545 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11546 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11548 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11558 pic16_freeAsmop(right,NULL,ic,TRUE);
11559 pic16_freeAsmop(result,NULL,ic,TRUE);
11560 pic16_freeAsmop(nextright,NULL,ic,TRUE);
11561 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11563 nextic->generated = 1;
11570 /*-----------------------------------------------------------------*/
11571 /* genCast - gen code for casting */
11572 /*-----------------------------------------------------------------*/
11573 static void genCast (iCode *ic)
11575 operand *result = IC_RESULT(ic);
11576 sym_link *ctype = operandType(IC_LEFT(ic));
11577 sym_link *rtype = operandType(IC_RIGHT(ic));
11578 operand *right = IC_RIGHT(ic);
11581 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11582 /* if they are equivalent then do nothing */
11583 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11586 pic16_aopOp(right,ic,FALSE) ;
11587 pic16_aopOp(result,ic,FALSE);
11589 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11591 /* if the result is a bit */
11592 if (AOP_TYPE(result) == AOP_CRY) {
11594 /* if the right size is a literal then
11595 * we know what the value is */
11596 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11598 if (AOP_TYPE(right) == AOP_LIT) {
11599 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11600 pic16_popGet(AOP(result),0));
11602 if (((int) operandLitValue(right)))
11603 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11604 AOP(result)->aopu.aop_dir,
11605 AOP(result)->aopu.aop_dir);
11607 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11608 AOP(result)->aopu.aop_dir,
11609 AOP(result)->aopu.aop_dir);
11613 /* the right is also a bit variable */
11614 if (AOP_TYPE(right) == AOP_CRY) {
11616 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11618 pic16_emitcode("clrc","");
11619 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11620 AOP(right)->aopu.aop_dir,
11621 AOP(right)->aopu.aop_dir);
11622 pic16_aopPut(AOP(result),"c",0);
11626 /* we need to or */
11627 if (AOP_TYPE(right) == AOP_REG) {
11628 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11629 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11630 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11632 pic16_toBoolean(right);
11633 pic16_aopPut(AOP(result),"a",0);
11637 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11640 size = AOP_SIZE(result);
11642 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11644 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11645 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11646 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11649 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11654 /* if they are the same size : or less */
11655 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11657 /* if they are in the same place */
11658 if (pic16_sameRegs(AOP(right),AOP(result)))
11661 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11663 if (IS_PTR_CONST(rtype))
11665 if (IS_CODEPTR(rtype))
11667 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11670 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11672 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11674 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11677 if(AOP_TYPE(right) == AOP_IMMD) {
11678 pCodeOp *pcop0, *pcop1, *pcop2;
11679 symbol *sym = OP_SYMBOL( right );
11681 size = AOP_SIZE(result);
11683 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11685 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11687 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11690 pic16_emitpcode(POC_MOVLW, pcop0);
11691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11692 pic16_emitpcode(POC_MOVLW, pcop1);
11693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11694 pic16_emitpcode(POC_MOVLW, pcop2);
11695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11698 pic16_emitpcode(POC_MOVLW, pcop0);
11699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11700 pic16_emitpcode(POC_MOVLW, pcop1);
11701 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11703 pic16_emitpcode(POC_MOVLW, pcop0);
11704 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11708 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11709 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11710 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11711 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11712 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11713 if(AOP_SIZE(result) <2)
11714 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11716 /* if they in different places then copy */
11717 size = AOP_SIZE(result);
11720 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11721 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11728 /* if the result is of type pointer */
11729 if (IS_PTR(ctype)) {
11731 sym_link *type = operandType(right);
11732 sym_link *etype = getSpec(type);
11734 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11736 /* pointer to generic pointer */
11737 if (IS_GENPTR(ctype)) {
11741 p_type = DCL_TYPE(type);
11743 /* we have to go by the storage class */
11744 p_type = PTR_TYPE(SPEC_OCLS(etype));
11746 /* if (SPEC_OCLS(etype)->codesp ) */
11747 /* p_type = CPOINTER ; */
11749 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11750 /* p_type = FPOINTER ; */
11752 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11753 /* p_type = PPOINTER; */
11755 /* if (SPEC_OCLS(etype) == idata ) */
11756 /* p_type = IPOINTER ; */
11758 /* p_type = POINTER ; */
11761 /* the first two bytes are known */
11762 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11763 size = GPTRSIZE - 1;
11766 if(offset < AOP_SIZE(right)) {
11767 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
11768 mov2f(AOP(result), AOP(right), offset);
11770 if ((AOP_TYPE(right) == AOP_PCODE) &&
11771 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11772 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11776 pic16_aopPut(AOP(result),
11777 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11782 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11785 /* the last byte depending on type */
11789 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
11790 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
11791 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11795 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
11799 pic16_emitcode(";BUG!? ","%d",__LINE__);
11803 pic16_emitcode(";BUG!? ","%d",__LINE__);
11808 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
11812 /* this should never happen */
11813 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11814 "got unknown pointer type");
11817 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11821 /* just copy the pointers */
11822 size = AOP_SIZE(result);
11825 pic16_aopPut(AOP(result),
11826 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11835 /* so we now know that the size of destination is greater
11836 than the size of the source.
11837 Now, if the next iCode is an operator then we might be
11838 able to optimize the operation without performing a cast.
11840 if(genMixedOperation(ic))
11843 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11845 /* we move to result for the size of source */
11846 size = AOP_SIZE(right);
11849 mov2f(AOP(result), AOP(right), offset);
11853 /* now depending on the sign of the destination */
11854 size = AOP_SIZE(result) - AOP_SIZE(right);
11855 /* if unsigned or not an integral type */
11856 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11858 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11860 /* we need to extend the sign :( */
11863 /* Save one instruction of casting char to int */
11864 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11865 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11866 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11868 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11871 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11873 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11875 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11878 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11883 pic16_freeAsmop(right,NULL,ic,TRUE);
11884 pic16_freeAsmop(result,NULL,ic,TRUE);
11888 /*-----------------------------------------------------------------*/
11889 /* genDjnz - generate decrement & jump if not zero instrucion */
11890 /*-----------------------------------------------------------------*/
11891 static int genDjnz (iCode *ic, iCode *ifx)
11893 symbol *lbl, *lbl1;
11894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11899 /* if the if condition has a false label
11900 then we cannot save */
11904 /* if the minus is not of the form
11906 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11907 !IS_OP_LITERAL(IC_RIGHT(ic)))
11910 if (operandLitValue(IC_RIGHT(ic)) != 1)
11913 /* if the size of this greater than one then no
11915 if (getSize(operandType(IC_RESULT(ic))) > 1)
11918 /* otherwise we can save BIG */
11919 lbl = newiTempLabel(NULL);
11920 lbl1= newiTempLabel(NULL);
11922 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11924 if (IS_AOP_PREG(IC_RESULT(ic))) {
11925 pic16_emitcode("dec","%s",
11926 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11927 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11928 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11932 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11933 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11935 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11936 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11940 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11941 ifx->generated = 1;
11945 /*-----------------------------------------------------------------*/
11946 /* genReceive - generate code for a receive iCode */
11947 /*-----------------------------------------------------------------*/
11948 static void genReceive (iCode *ic)
11950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11953 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11954 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11956 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11958 if (isOperandInFarSpace(IC_RESULT(ic))
11959 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
11960 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11962 int size = getSize(operandType(IC_RESULT(ic)));
11963 int offset = pic16_fReturnSizePic - size;
11967 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11968 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11972 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11974 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11975 size = AOP_SIZE(IC_RESULT(ic));
11978 pic16_emitcode ("pop","acc");
11979 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11982 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
11985 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11987 assignResultValue(IC_RESULT(ic), 0);
11990 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11993 /*-----------------------------------------------------------------*/
11994 /* genDummyRead - generate code for dummy read of volatiles */
11995 /*-----------------------------------------------------------------*/
11997 genDummyRead (iCode * ic)
11999 pic16_emitcode ("; genDummyRead","");
12000 pic16_emitcode ("; not implemented","");
12005 /*-----------------------------------------------------------------*/
12006 /* genpic16Code - generate code for pic16 based controllers */
12007 /*-----------------------------------------------------------------*/
12009 * At this point, ralloc.c has gone through the iCode and attempted
12010 * to optimize in a way suitable for a PIC. Now we've got to generate
12011 * PIC instructions that correspond to the iCode.
12013 * Once the instructions are generated, we'll pass through both the
12014 * peep hole optimizer and the pCode optimizer.
12015 *-----------------------------------------------------------------*/
12017 void genpic16Code (iCode *lic)
12022 lineHead = lineCurr = NULL;
12024 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12025 pic16_addpBlock(pb);
12028 /* if debug information required */
12029 if (options.debug && currFunc) {
12031 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
12036 for (ic = lic ; ic ; ic = ic->next ) {
12038 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
12039 if ( cln != ic->lineno ) {
12040 if ( options.debug ) {
12041 debugFile->writeCLine (ic);
12044 if(!options.noCcodeInAsm) {
12045 pic16_addpCode2pBlock(pb,
12046 pic16_newpCodeCSource(ic->lineno, ic->filename,
12047 printCLine(ic->filename, ic->lineno)));
12053 if(options.iCodeInAsm) {
12055 /* insert here code to print iCode as comment */
12056 l = Safe_strdup(printILine(ic));
12057 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
12060 /* if the result is marked as
12061 spilt and rematerializable or code for
12062 this has already been generated then
12064 if (resultRemat(ic) || ic->generated )
12067 /* depending on the operation */
12086 /* IPOP happens only when trying to restore a
12087 spilt live range, if there is an ifx statement
12088 following this pop then the if statement might
12089 be using some of the registers being popped which
12090 would destroy the contents of the register so
12091 we need to check for this condition and handle it */
12093 ic->next->op == IFX &&
12094 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
12095 genIfx (ic->next,ic);
12113 genEndFunction (ic);
12129 pic16_genPlus (ic) ;
12133 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
12134 pic16_genMinus (ic);
12150 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
12154 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
12161 /* note these two are xlated by algebraic equivalence
12162 during parsing SDCC.y */
12163 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12164 "got '>=' or '<=' shouldn't have come here");
12168 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
12180 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
12184 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
12188 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
12212 genRightShift (ic);
12215 case GET_VALUE_AT_ADDRESS:
12220 if (POINTER_SET(ic))
12247 addSet(&_G.sendSet,ic);
12248 /* create a reversed list of SEND iCodes */
12249 // addSetHead(&_G.sendSet, ic);
12252 case DUMMY_READ_VOLATILE:
12262 /* now we are ready to call the
12263 peep hole optimizer */
12264 if (!options.nopeep) {
12265 peepHole (&lineHead);
12267 /* now do the actual printing */
12268 printLine (lineHead, codeOutFile);
12271 DFPRINTF((stderr,"printing pBlock\n\n"));
12272 pic16_printpBlock(stdout,pb);