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,2005)
10 Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x))
67 /* If you change these, you also have to update the library files
68 * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
69 #define GPTR_TAG_DATA 0x80
70 #define GPTR_TAG_EEPROM 0x40
71 #define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */
73 /* Wrapper to execute `code' at most once. */
74 #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
76 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
77 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 void pic16_genMult8X8_8 (operand *, operand *,operand *);
79 void pic16_genMult16X16_16(operand *, operand *, operand *);
80 void pic16_genMult32X32_32(operand *, operand *, operand *);
81 pCode *pic16_AssembleLine(char *line, int peeps);
82 extern void pic16_printpBlock(FILE *of, pBlock *pb);
83 static asmop *newAsmop (short type);
84 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
85 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
86 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
87 static pCodeOp *pic16_popRegFromIdx(int rIdx);
89 //static int aopIdx (asmop *aop, int offset);
91 int pic16_labelOffset=0;
92 extern int pic16_debug_verbose;
93 #if !(USE_GENERIC_SIGNED_SHIFT)
94 static int optimized_for_speed = 0;
103 /* max_key keeps track of the largest label number used in
104 a function. This is then used to adjust the label offset
105 for the next function.
107 static int max_key=0;
108 static int GpsuedoStkPtr=0;
110 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
112 unsigned int pic16aopLiteral (value *val, int offset);
113 const char *pic16_AopType(short type);
114 static iCode *ifxForOp ( operand *op, iCode *ic );
116 void pic16_pushpCodeOp(pCodeOp *pcop);
117 void pic16_poppCodeOp(pCodeOp *pcop);
119 static bool is_LitOp(operand *op);
120 static bool is_LitAOp(asmop *aop);
123 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
125 /* set the following macro to 1 to enable passing the
126 * first byte of functions parameters via WREG */
127 #define USE_WREG_IN_FUNC_PARAMS 0
130 /* this is the down and dirty file with all kinds of
131 kludgy & hacky stuff. This is what it is all about
132 CODE GENERATION for a specific MCU . some of the
133 routines may be reusable, will have to see */
135 static char *zero = "#0x00";
136 static char *one = "#0x01";
137 //static char *spname = "sp";
141 * Function return value policy (MSB-->LSB):
143 * 16 bits -> PRODL:WREG
144 * 24 bits -> PRODH:PRODL:WREG
145 * 32 bits -> FSR0L:PRODH:PRODL:WREG
146 * >32 bits -> on stack, and FSR0 points to the beginning
151 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
152 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
153 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
154 static char **fReturn = fReturnpic16;
156 static char *accUse[] = {"WREG"};
158 //static short rbank = -1;
172 bitVect *fregsUsed; /* registers used in function */
174 set *sregsAllocSet; /* registers used to store stack variables */
175 int stack_lat; /* stack offset latency */
177 int useWreg; /* flag when WREG is used to pass function parameter */
180 extern int pic16_ptrRegReq ;
181 extern int pic16_nRegs;
182 extern FILE *codeOutFile;
183 //static void saverbank (int, iCode *,bool);
185 static lineNode *lineHead = NULL;
186 static lineNode *lineCurr = NULL;
188 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
189 0xE0, 0xC0, 0x80, 0x00};
190 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
191 0x07, 0x03, 0x01, 0x00};
195 /*-----------------------------------------------------------------*/
196 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
197 /* exponent of 2 is returned, otherwise -1 is */
199 /* note that this is similar to the function `powof2' in SDCCsymt */
203 /*-----------------------------------------------------------------*/
204 int pic16_my_powof2 (unsigned long num)
207 if( (num & (num-1)) == 0) {
220 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
222 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
224 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
226 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
227 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
228 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
229 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
230 ((result) ? AOP_SIZE(result) : 0));
233 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
236 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
238 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
239 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
240 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
241 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
242 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
243 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
247 void pic16_emitpcomment (char *fmt, ...)
250 char lb[INITIAL_INLINEASM];
251 unsigned char *lbp = lb;
256 vsprintf(lb+1,fmt,ap);
258 while (isspace(*lbp)) lbp++;
261 lineCurr = (lineCurr ?
262 connectLine(lineCurr,newLineNode(lb)) :
263 (lineHead = newLineNode(lb)));
264 lineCurr->isInline = _G.inLine;
265 lineCurr->isDebug = _G.debugLine;
267 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
270 // fprintf(stderr, "%s\n", lb);
273 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
276 char lb[INITIAL_INLINEASM];
277 unsigned char *lbp = lb;
279 if(!pic16_debug_verbose)
286 sprintf(lb,"%s\t",inst);
288 sprintf(lb,"%s",inst);
289 vsprintf(lb+(strlen(lb)),fmt,ap);
293 while (isspace(*lbp)) lbp++;
296 lineCurr = (lineCurr ?
297 connectLine(lineCurr,newLineNode(lb)) :
298 (lineHead = newLineNode(lb)));
299 lineCurr->isInline = _G.inLine;
300 lineCurr->isDebug = _G.debugLine;
302 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
305 // fprintf(stderr, "%s\n", lb);
310 void pic16_emitpLabel(int key)
312 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
315 void pic16_emitpLabelFORCE(int key)
317 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
320 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
321 * NEVER call pic16_emitpcode_real directly, please... */
322 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
326 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
328 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
331 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
334 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
336 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
339 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
342 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
348 #define pic16_emitcode DEBUGpic16_emitcode
350 /*-----------------------------------------------------------------*/
351 /* pic16_emitcode - writes the code into a file : for now it is simple */
352 /*-----------------------------------------------------------------*/
353 void pic16_emitcode (char *inst,char *fmt, ...)
356 char lb[INITIAL_INLINEASM];
357 unsigned char *lbp = lb;
363 sprintf(lb,"%s\t",inst);
365 sprintf(lb,"%s",inst);
366 vsprintf(lb+(strlen(lb)),fmt,ap);
370 while (isspace(*lbp)) lbp++;
373 lineCurr = (lineCurr ?
374 connectLine(lineCurr,newLineNode(lb)) :
375 (lineHead = newLineNode(lb)));
376 lineCurr->isInline = _G.inLine;
377 lineCurr->isDebug = _G.debugLine;
379 // VR fprintf(stderr, "lb = <%s>\n", lbp);
381 // if(pic16_debug_verbose)
382 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
389 /*-----------------------------------------------------------------*/
390 /* pic16_emitDebuggerSymbol - associate the current code location */
391 /* with a debugger symbol */
392 /*-----------------------------------------------------------------*/
394 pic16_emitDebuggerSymbol (char * debugSym)
397 pic16_emitcode (";", "%s ==.", debugSym);
402 /*-----------------------------------------------------------------*/
403 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
404 /*-----------------------------------------------------------------*/
405 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
407 // bool r0iu = FALSE , r1iu = FALSE;
408 // bool r0ou = FALSE , r1ou = FALSE;
409 bool fsr0iu = FALSE, fsr0ou;
410 bool fsr2iu = FALSE, fsr2ou;
412 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
415 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
416 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
418 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
419 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
421 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
422 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
423 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
426 if(!fsr0iu && !fsr0ou) {
427 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
428 (*aopp)->type = AOP_FSR0;
430 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
432 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
436 /* no usage of FSR2 */
437 if(!fsr2iu && !fsr2ou) {
438 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
439 (*aopp)->type = AOP_FSR2;
441 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
445 /* now we know they both have usage */
446 /* if fsr0 not used in this instruction */
448 if (!_G.fsr0Pushed) {
449 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
450 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
454 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
455 (*aopp)->type = AOP_FSR0;
457 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
459 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
463 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
468 /* the logic: if r0 & r1 used in the instruction
469 then we are in trouble otherwise */
471 /* first check if r0 & r1 are used by this
472 instruction, in which case we are in trouble */
473 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
474 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
479 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
480 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
482 /* if no usage of r0 then return it */
483 if (!r0iu && !r0ou) {
484 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
485 (*aopp)->type = AOP_R0;
487 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
490 /* if no usage of r1 then return it */
491 if (!r1iu && !r1ou) {
492 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
493 (*aopp)->type = AOP_R1;
495 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
498 /* now we know they both have usage */
499 /* if r0 not used in this instruction */
501 /* push it if not already pushed */
503 //pic16_emitcode ("push","%s",
504 // pic16_regWithIdx(R0_IDX)->dname);
508 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
509 (*aopp)->type = AOP_R0;
511 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
514 /* if r1 not used then */
517 /* push it if not already pushed */
519 //pic16_emitcode ("push","%s",
520 // pic16_regWithIdx(R1_IDX)->dname);
524 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
525 (*aopp)->type = AOP_R1;
526 return pic16_regWithIdx(R1_IDX);
530 /* I said end of world but not quite end of world yet */
531 /* if this is a result then we can push it on the stack*/
533 (*aopp)->type = AOP_STK;
537 /* other wise this is true end of the world */
538 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
539 "getFreePtr should never reach here");
544 /*-----------------------------------------------------------------*/
545 /* newAsmop - creates a new asmOp */
546 /*-----------------------------------------------------------------*/
547 static asmop *newAsmop (short type)
551 aop = Safe_calloc(1,sizeof(asmop));
556 static void genSetDPTR(int n)
560 pic16_emitcode(";", "Select standard DPTR");
561 pic16_emitcode("mov", "dps, #0x00");
565 pic16_emitcode(";", "Select alternate DPTR");
566 pic16_emitcode("mov", "dps, #0x01");
570 /*-----------------------------------------------------------------*/
571 /* resolveIfx - converts an iCode ifx into a form more useful for */
572 /* generating code */
573 /*-----------------------------------------------------------------*/
574 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
578 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
584 resIfx->condition = 1; /* assume that the ifx is true */
585 resIfx->generated = 0; /* indicate that the ifx has not been used */
588 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
591 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
592 __FUNCTION__,__LINE__,resIfx->lbl->key);
597 resIfx->lbl = IC_TRUE(ifx);
599 resIfx->lbl = IC_FALSE(ifx);
600 resIfx->condition = 0;
605 DEBUGpic16_emitcode("; +++","ifx true is non-null");
607 DEBUGpic16_emitcode("; +++","ifx true is null");
609 DEBUGpic16_emitcode("; +++","ifx false is non-null");
611 DEBUGpic16_emitcode("; +++","ifx false is null");
615 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
619 /*-----------------------------------------------------------------*/
620 /* pointerCode - returns the code for a pointer type */
621 /*-----------------------------------------------------------------*/
622 static int pointerCode (sym_link *etype)
625 return PTR_TYPE(SPEC_OCLS(etype));
630 /*-----------------------------------------------------------------*/
631 /* aopForSym - for a true symbol */
632 /*-----------------------------------------------------------------*/
633 static asmop *aopForSym (iCode *ic, operand *op, bool result)
635 symbol *sym=OP_SYMBOL(op);
637 memmap *space= SPEC_OCLS(sym->etype);
641 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
643 // sym = OP_SYMBOL(op);
645 /* if already has one */
647 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
652 /* if symbol was initially placed onStack then we must re-place it
653 * to direct memory, since pic16 does not have a specific stack */
655 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
663 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
665 sym->aop = aop = newAsmop (AOP_PAGED);
666 aop->aopu.aop_dir = sym->rname ;
667 aop->size = getSize(sym->type);
668 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
669 pic16_allocDirReg( IC_LEFT(ic) );
677 /* assign depending on the storage class */
678 /* if it is on the stack or indirectly addressable */
679 /* space we need to assign either r0 or r1 to it */
680 if (sym->onStack) // || sym->iaccess)
685 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
686 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
688 /* acquire a temporary register -- it is saved in function */
690 sym->aop = aop = newAsmop(AOP_STA);
691 aop->aopu.stk.stk = sym->stack;
692 aop->size = getSize(sym->type);
695 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
696 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
697 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
698 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
700 for(i=0;i<aop->size;i++)
701 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
702 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
704 if(1 && ic->op == SEND) {
706 /* if SEND do the send here */
709 for(i=0;i<aop->size;i++) {
710 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
711 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
716 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
719 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
721 // we do not need to load the value if it is to be defined...
722 if (result) return aop;
725 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
728 for(i=0;i<aop->size;i++) {
730 /* initialise for stack access via frame pointer */
731 // operands on stack are accessible via "FSR2 + index" with index
732 // starting at 2 for arguments and growing from 0 downwards for
733 // local variables (index == 0 is not assigned so we add one here)
735 int soffs = sym->stack;
741 if(1 && ic->op == SEND) {
742 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
743 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
744 pic16_popCopyReg( pic16_frame_plusw ),
745 pic16_popCopyReg(pic16_stack_postdec )));
747 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
748 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
749 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
755 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
762 /* now assign the address of the variable to
763 the pointer register */
764 if (aop->type != AOP_STK) {
768 pic16_emitcode("push","acc");
770 pic16_emitcode("mov","a,_bp");
771 pic16_emitcode("add","a,#0x%02x",
773 ((char)(sym->stack - _G.nRegsSaved )) :
774 ((char)sym->stack)) & 0xff);
775 pic16_emitcode("mov","%s,a",
776 aop->aopu.aop_ptr->name);
779 pic16_emitcode("pop","acc");
781 pic16_emitcode("mov","%s,#%s",
782 aop->aopu.aop_ptr->name,
784 aop->paged = space->paged;
786 aop->aopu.aop_stk = sym->stack;
794 if (sym->onStack && options.stack10bit)
796 /* It's on the 10 bit stack, which is located in
800 //DEBUGpic16_emitcode(";","%d",__LINE__);
803 pic16_emitcode("push","acc");
805 pic16_emitcode("mov","a,_bp");
806 pic16_emitcode("add","a,#0x%02x",
808 ((char)(sym->stack - _G.nRegsSaved )) :
809 ((char)sym->stack)) & 0xff);
812 pic16_emitcode ("mov","dpx1,#0x40");
813 pic16_emitcode ("mov","dph1,#0x00");
814 pic16_emitcode ("mov","dpl1, a");
818 pic16_emitcode("pop","acc");
820 sym->aop = aop = newAsmop(AOP_DPTR2);
821 aop->size = getSize(sym->type);
827 /* special case for a function */
828 if (IS_FUNC(sym->type)) {
829 sym->aop = aop = newAsmop(AOP_PCODE);
830 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
831 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
832 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
833 PCOI(aop->aopu.pcop)->index = 0;
834 aop->size = FPTRSIZE;
835 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
842 //DEBUGpic16_emitcode(";","%d",__LINE__);
843 /* if in bit space */
844 if (IN_BITSPACE(space)) {
845 sym->aop = aop = newAsmop (AOP_CRY);
846 aop->aopu.aop_dir = sym->rname ;
847 aop->size = getSize(sym->type);
848 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851 /* if it is in direct space */
852 if (IN_DIRSPACE(space)) {
853 sym->aop = aop = newAsmop (AOP_DIR);
854 aop->aopu.aop_dir = sym->rname ;
855 aop->size = getSize(sym->type);
856 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
857 pic16_allocDirReg( IC_LEFT(ic) );
862 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
863 sym->aop = aop = newAsmop (AOP_DIR);
864 aop->aopu.aop_dir = sym->rname ;
865 aop->size = getSize(sym->type);
866 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
867 pic16_allocDirReg( IC_LEFT(ic) );
872 /* only remaining is far space */
873 sym->aop = aop = newAsmop(AOP_PCODE);
875 /* change the next if to 1 to revert to good old immediate code */
876 if(IN_CODESPACE(space)) {
877 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
878 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
879 PCOI(aop->aopu.pcop)->index = 0;
881 /* try to allocate via direct register */
882 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
883 // aop->size = getSize( sym->type );
886 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
887 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
890 if(!pic16_allocDirReg (IC_LEFT(ic)))
894 if(IN_DIRSPACE( space ))
896 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
897 aop->size = FPTRSIZE;
898 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
899 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
900 else if(sym->onStack) {
903 if(SPEC_SCLS(sym->etype) == S_PDATA) {
904 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
905 aop->size = FPTRSIZE;
910 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
912 /* if it is in code space */
913 if (IN_CODESPACE(space))
919 /*-----------------------------------------------------------------*/
920 /* aopForRemat - rematerialzes an object */
921 /*-----------------------------------------------------------------*/
922 static asmop *aopForRemat (operand *op) // x symbol *sym)
924 symbol *sym = OP_SYMBOL(op);
926 iCode *ic = NULL, *oldic;
927 asmop *aop = newAsmop(AOP_PCODE);
934 ic = sym->rematiCode;
936 if(IS_OP_POINTER(op)) {
937 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
943 // pic16_emitpcomment("ic: %s\n", printILine(ic));
946 val += (int) operandLitValue(IC_RIGHT(ic));
947 } else if (ic->op == '-') {
948 val -= (int) operandLitValue(IC_RIGHT(ic));
952 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
955 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
958 if(!op->isaddr)viaimmd++; else viaimmd=0;
960 /* set the following if to 1 to revert to good old immediate code */
961 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
964 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
966 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
969 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
971 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
974 PCOI(aop->aopu.pcop)->index = val;
976 aop->size = getSize( sym->type );
978 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
980 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
981 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
983 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
987 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
988 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
990 val, IS_PTR_CONST(operandType(op)));
992 val, IS_CODEPTR(operandType(op)));
995 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
997 pic16_allocDirReg (IC_LEFT(ic));
999 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1006 static int aopIdx (asmop *aop, int offset)
1011 if(aop->type != AOP_REG)
1014 return aop->aopu.aop_reg[offset]->rIdx;
1019 /*-----------------------------------------------------------------*/
1020 /* regsInCommon - two operands have some registers in common */
1021 /*-----------------------------------------------------------------*/
1022 static bool regsInCommon (operand *op1, operand *op2)
1024 symbol *sym1, *sym2;
1027 /* if they have registers in common */
1028 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1031 sym1 = OP_SYMBOL(op1);
1032 sym2 = OP_SYMBOL(op2);
1034 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1037 for (i = 0 ; i < sym1->nRegs ; i++) {
1042 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1046 if (sym2->regs[j] == sym1->regs[i])
1054 /*-----------------------------------------------------------------*/
1055 /* operandsEqu - equivalent */
1056 /*-----------------------------------------------------------------*/
1057 static bool operandsEqu ( operand *op1, operand *op2)
1059 symbol *sym1, *sym2;
1061 /* if they not symbols */
1062 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1065 sym1 = OP_SYMBOL(op1);
1066 sym2 = OP_SYMBOL(op2);
1068 /* if both are itemps & one is spilt
1069 and the other is not then false */
1070 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1071 sym1->isspilt != sym2->isspilt )
1074 /* if they are the same */
1078 if (sym1->rname[0] && sym2->rname[0]
1079 && strcmp (sym1->rname, sym2->rname) == 0)
1083 /* if left is a tmp & right is not */
1084 if (IS_ITEMP(op1) &&
1087 (sym1->usl.spillLoc == sym2))
1090 if (IS_ITEMP(op2) &&
1094 (sym2->usl.spillLoc == sym1))
1100 /*-----------------------------------------------------------------*/
1101 /* pic16_sameRegs - two asmops have the same registers */
1102 /*-----------------------------------------------------------------*/
1103 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1110 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1111 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1113 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1115 if (aop1->type != AOP_REG ||
1116 aop2->type != AOP_REG )
1119 /* This is a bit too restrictive if one is a subset of the other...
1120 if (aop1->size != aop2->size )
1124 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1125 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1127 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1128 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1135 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1137 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1138 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1140 if(aop1 == aop2)return TRUE;
1141 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1143 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1149 /*-----------------------------------------------------------------*/
1150 /* pic16_aopOp - allocates an asmop for an operand : */
1151 /*-----------------------------------------------------------------*/
1152 void pic16_aopOp (operand *op, iCode *ic, bool result)
1161 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1163 /* if this a literal */
1164 if (IS_OP_LITERAL(op)) {
1165 op->aop = aop = newAsmop(AOP_LIT);
1166 aop->aopu.aop_lit = op->operand.valOperand;
1167 aop->size = getSize(operandType(op));
1172 sym_link *type = operandType(op);
1174 if(IS_PTR_CONST(type))
1176 if(IS_CODEPTR(type))
1178 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1181 /* if already has a asmop then continue */
1185 /* if the underlying symbol has a aop */
1186 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1187 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1188 op->aop = OP_SYMBOL(op)->aop;
1192 /* if this is a true symbol */
1193 if (IS_TRUE_SYMOP(op)) {
1194 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1195 op->aop = aopForSym(ic, op, result);
1199 /* this is a temporary : this has
1205 e) can be a return use only */
1207 sym = OP_SYMBOL(op);
1209 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1210 /* if the type is a conditional */
1211 if (sym->regType == REG_CND) {
1212 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1217 /* if it is spilt then two situations
1219 b) has a spill location */
1220 if (sym->isspilt || sym->nRegs == 0) {
1222 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1223 DEBUGpic16_emitcode(";","%d",__LINE__);
1224 /* rematerialize it NOW */
1227 sym->aop = op->aop = aop = aopForRemat (op);
1228 // aop->size = getSize(sym->type);
1229 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1236 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1237 aop->size = getSize(sym->type);
1238 for ( i = 0 ; i < 1 ; i++ ) {
1239 aop->aopu.aop_str[i] = accUse[i];
1240 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1242 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1243 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1251 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1252 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1253 //pic16_allocDirReg (IC_LEFT(ic));
1254 aop->size = getSize(sym->type);
1259 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1260 aop->size = getSize(sym->type);
1261 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1262 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1264 DEBUGpic16_emitcode(";","%d",__LINE__);
1268 /* else spill location */
1269 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1270 /* force a new aop if sizes differ */
1271 sym->usl.spillLoc->aop = NULL;
1275 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1276 __FUNCTION__,__LINE__,
1277 sym->usl.spillLoc->rname,
1278 sym->rname, sym->usl.spillLoc->offset);
1281 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1282 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1283 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1284 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1286 sym->usl.spillLoc->offset, op);
1288 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1289 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1290 assert (getSize(sym->type) <= 1);
1291 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1293 aop->size = getSize(sym->type);
1299 sym_link *type = operandType(op);
1301 if(IS_PTR_CONST(type))
1303 if(IS_CODEPTR(type))
1305 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1308 /* must be in a register */
1309 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1310 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1311 aop->size = sym->nRegs;
1312 for ( i = 0 ; i < sym->nRegs ;i++)
1313 aop->aopu.aop_reg[i] = sym->regs[i];
1316 /*-----------------------------------------------------------------*/
1317 /* pic16_freeAsmop - free up the asmop given to an operand */
1318 /*----------------------------------------------------------------*/
1319 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1336 /* depending on the asmop type only three cases need work AOP_RO
1337 , AOP_R1 && AOP_STK */
1339 switch (aop->type) {
1341 if (_G.fsr0Pushed ) {
1343 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1344 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1345 // pic16_emitcode ("pop","ar0");
1349 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1353 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1359 pic16_emitcode ("pop","ar0");
1363 bitVectUnSetBit(ic->rUsed,R0_IDX);
1369 pic16_emitcode ("pop","ar1");
1373 bitVectUnSetBit(ic->rUsed,R1_IDX);
1380 /* we must store the result on stack */
1381 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1382 // operands on stack are accessible via "FSR2 + index" with index
1383 // starting at 2 for arguments and growing from 0 downwards for
1384 // local variables (index == 0 is not assigned so we add one here)
1385 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1390 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1391 for(i=0;i<aop->size;i++) {
1392 /* initialise for stack access via frame pointer */
1393 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1394 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1395 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1398 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1402 for(i=0;i<aop->size;i++) {
1403 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1405 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1406 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1417 int stk = aop->aopu.aop_stk + aop->size;
1418 bitVectUnSetBit(ic->rUsed,R0_IDX);
1419 bitVectUnSetBit(ic->rUsed,R1_IDX);
1421 getFreePtr(ic,&aop,FALSE);
1423 if (options.stack10bit)
1425 /* I'm not sure what to do here yet... */
1428 "*** Warning: probably generating bad code for "
1429 "10 bit stack mode.\n");
1433 pic16_emitcode ("mov","a,_bp");
1434 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1435 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1437 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1441 pic16_emitcode("pop","acc");
1442 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1444 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1447 pic16_freeAsmop(op,NULL,ic,TRUE);
1449 pic16_emitcode("pop","ar0");
1454 pic16_emitcode("pop","ar1");
1464 /* all other cases just dealloc */
1468 OP_SYMBOL(op)->aop = NULL;
1469 /* if the symbol has a spill */
1471 SPIL_LOC(op)->aop = NULL;
1476 /*-----------------------------------------------------------------*/
1477 /* pic16_aopGet - for fetching value of the aop */
1478 /*-----------------------------------------------------------------*/
1479 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1484 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1486 /* offset is greater than size then zero */
1487 if (offset > (aop->size - 1) &&
1488 aop->type != AOP_LIT)
1491 /* depending on type */
1492 switch (aop->type) {
1496 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1497 rs = Safe_calloc(1, strlen(s)+1);
1502 /* if we need to increment it */
1503 while (offset > aop->coff)
1505 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1509 while (offset < aop->coff)
1511 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1517 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1518 return (dname ? "acc" : "a");
1520 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1521 rs = Safe_calloc (1, strlen (s) + 1);
1529 sprintf (s,"%s",aop->aopu.aop_immd);
1532 sprintf(s,"(%s >> %d)",
1537 aop->aopu.aop_immd);
1538 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1539 rs = Safe_calloc(1,strlen(s)+1);
1545 sprintf(s,"(%s + %d)",
1548 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1550 sprintf(s,"%s",aop->aopu.aop_dir);
1551 rs = Safe_calloc(1,strlen(s)+1);
1557 // return aop->aopu.aop_reg[offset]->dname;
1559 return aop->aopu.aop_reg[offset]->name;
1562 //pic16_emitcode(";","%d",__LINE__);
1563 return aop->aopu.aop_dir;
1566 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1567 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1569 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1570 rs = Safe_strdup("WREG");
1574 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1575 rs = Safe_calloc(1,strlen(s)+1);
1580 aop->coff = offset ;
1582 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1585 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1586 aop->type = AOP_ACC;
1587 return Safe_strdup("WREG");
1589 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1591 return aop->aopu.aop_str[offset];
1595 pCodeOp *pcop = aop->aopu.pcop;
1596 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1598 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1599 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1601 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1603 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1606 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1609 rs = Safe_calloc(1,strlen(s)+1);
1615 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1617 sprintf(s,"(%s + %d)",
1621 sprintf(s,"%s",aop->aopu.aop_dir);
1622 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1623 rs = Safe_calloc(1,strlen(s)+1);
1629 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1633 // pCodeOp *pcop = aop->aop
1638 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1639 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1640 "aopget got unsupported aop->type");
1646 /* lock has the following meaning: When allocating temporary registers
1647 * for stack variables storage, the value of the temporary register is
1648 * saved on stack. Its value is restored at the end. This procedure is
1649 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1650 * a possibility that before a call to pic16_aopOp, a temporary register
1651 * is allocated for a while and it is freed after some time, this will
1652 * mess the stack and values will not be restored properly. So use lock=1
1653 * to allocate temporary registers used internally by the programmer, and
1654 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1655 * to inform the compiler developer about a possible bug. This is an internal
1656 * feature for developing the compiler -- VR */
1658 int _TempReg_lock = 0;
1659 /*-----------------------------------------------------------------*/
1660 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGetTempReg(int lock)
1667 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1669 // werror(W_POSSBUG2, __FILE__, __LINE__);
1672 _TempReg_lock += lock;
1677 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1678 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1679 PCOR(pcop)->r->wasUsed=1;
1680 PCOR(pcop)->r->isFree=0;
1682 /* push value on stack */
1683 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1693 /* is not part of f, but don't save if */
1695 /*-----------------------------------------------------------------*/
1696 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1702 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1705 // werror(W_POSSBUG2, __FILE__, __LINE__);
1708 _TempReg_lock += lock;
1713 i = bitVectFirstBit(f);
1716 /* bypass registers that are used by function */
1717 if(!bitVectBitValue(f, i)) {
1719 /* bypass registers that are already allocated for stack access */
1720 if(!bitVectBitValue(v, i)) {
1722 // debugf("getting register rIdx = %d\n", i);
1723 /* ok, get the operand */
1724 pcop = pic16_newpCodeOpReg( i );
1726 /* should never by NULL */
1727 assert( pcop != NULL );
1731 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1734 PCOR(pcop)->r->wasUsed=1;
1735 PCOR(pcop)->r->isFree=0;
1741 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1743 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1744 /* already used in previous steps, break */
1751 /* caller takes care of the following */
1752 // bitVectSetBit(v, i);
1755 /* push value on stack */
1756 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1757 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1773 /*-----------------------------------------------------------------*/
1774 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1775 /*-----------------------------------------------------------------*/
1776 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1780 _TempReg_lock -= lock;
1782 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1783 PCOR(pcop)->r->isFree = 1;
1785 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popGetLabel(unsigned int key)
1794 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1799 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1802 /*-----------------------------------------------------------------*/
1803 /* pic16_popCopyReg - copy a pcode operator */
1804 /*-----------------------------------------------------------------*/
1805 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1809 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1810 memcpy (pcor, pc, sizeof (pCodeOpReg));
1811 pcor->r->wasUsed = 1;
1813 //pcor->pcop.type = pc->pcop.type;
1815 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1816 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1818 pcor->pcop.name = NULL;
1821 //pcor->rIdx = pc->rIdx;
1822 //pcor->r->wasUsed=1;
1823 //pcor->instance = pc->instance;
1825 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popGetLit - asm operator to pcode operator conversion */
1832 /*-----------------------------------------------------------------*/
1833 pCodeOp *pic16_popGetLit(int lit)
1835 return pic16_newpCodeOpLit(lit);
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1840 /*-----------------------------------------------------------------*/
1841 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1843 return pic16_newpCodeOpLit2(lit, arg2);
1847 /*-----------------------------------------------------------------*/
1848 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1849 /*-----------------------------------------------------------------*/
1850 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1852 return pic16_newpCodeOpImmd(name, offset,index, 0);
1856 /*-----------------------------------------------------------------*/
1857 /* pic16_popGet - asm operator to pcode operator conversion */
1858 /*-----------------------------------------------------------------*/
1859 pCodeOp *pic16_popGetWithString(char *str)
1865 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1869 pcop = pic16_newpCodeOp(str,PO_STR);
1874 /*-----------------------------------------------------------------*/
1875 /* pic16_popRegFromString - */
1876 /*-----------------------------------------------------------------*/
1877 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1880 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1881 pcop->type = PO_DIR;
1883 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1884 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1889 pcop->name = Safe_calloc(1,strlen(str)+1);
1890 strcpy(pcop->name,str);
1892 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1894 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1896 /* make sure that register doesn't exist,
1897 * and operand isn't NULL
1898 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1899 if((PCOR(pcop)->r == NULL)
1901 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1902 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1903 // __FUNCTION__, __LINE__, str, size, offset);
1905 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1906 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1909 PCOR(pcop)->instance = offset;
1914 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1918 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1920 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1921 PCOR(pcop)->rIdx = rIdx;
1922 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1924 PCOR(pcop)->r->isFree = 0;
1925 PCOR(pcop)->r->wasUsed = 1;
1927 pcop->type = PCOR(pcop)->r->pc_type;
1932 /*---------------------------------------------------------------------------------*/
1933 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1935 /*---------------------------------------------------------------------------------*/
1936 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1941 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1943 /* comment the following check, so errors to throw up */
1944 // if(!pcop2)return NULL;
1946 temp = pic16_popGet(aop_dst, offset);
1947 pcop2->pcop2 = temp;
1954 /*--------------------------------------------------------------------------------.-*/
1955 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1956 /* VR 030601 , adapted by Hans Dorn */
1957 /*--------------------------------------------------------------------------------.-*/
1958 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1962 pcop2 = (pCodeOpReg2 *)src;
1970 /*---------------------------------------------------------------------------------*/
1971 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1972 /* movff instruction */
1973 /*---------------------------------------------------------------------------------*/
1974 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1979 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1980 pcop2->pcop2 = pic16_popCopyReg(dst);
1982 /* the pCodeOp may be already allocated */
1983 pcop2 = (pCodeOpReg2 *)(src);
1984 pcop2->pcop2 = (pCodeOp *)(dst);
1991 /*-----------------------------------------------------------------*/
1992 /* pic16_popGet - asm operator to pcode operator conversion */
1993 /*-----------------------------------------------------------------*/
1994 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1996 //char *s = buffer ;
2001 /* offset is greater than
2004 // if (offset > (aop->size - 1) &&
2005 // aop->type != AOP_LIT)
2006 // return NULL; //zero;
2008 /* depending on type */
2009 switch (aop->type) {
2015 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2016 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2023 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2024 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2025 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2026 PCOR(pcop)->r->wasUsed = 1;
2027 PCOR(pcop)->r->isFree = 0;
2029 PCOR(pcop)->instance = offset;
2030 pcop->type = PCOR(pcop)->r->pc_type;
2034 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2035 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2038 /* pCodeOp is already allocated from aopForSym */
2039 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2040 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2046 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2048 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2050 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2052 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2053 PCOR(pcop)->rIdx = rIdx;
2054 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2055 PCOR(pcop)->r->wasUsed=1;
2056 PCOR(pcop)->r->isFree=0;
2058 PCOR(pcop)->instance = offset;
2059 pcop->type = PCOR(pcop)->r->pc_type;
2060 // rs = aop->aopu.aop_reg[offset]->name;
2061 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2065 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2066 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2072 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2073 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2077 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2078 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2084 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2085 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2087 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2089 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2090 // pcop->type = PO_GPR_REGISTER;
2091 PCOR(pcop)->rIdx = rIdx;
2092 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2093 PCOR(pcop)->r->wasUsed=1;
2094 PCOR(pcop)->r->isFree=0;
2096 PCOR(pcop)->instance = offset;
2097 pcop->type = PCOR(pcop)->r->pc_type;
2099 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2100 rs = aop->aopu.aop_reg[offset]->name;
2101 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2106 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2108 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2109 PCOR(pcop)->instance = offset;
2110 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2111 //if(PCOR(pcop)->r == NULL)
2112 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2116 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2117 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2120 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2121 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2124 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2125 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2126 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2127 pcop->type = PCOR(pcop)->r->pc_type;
2128 pcop->name = PCOR(pcop)->r->name;
2134 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2136 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2137 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2138 switch( aop->aopu.pcop->type ) {
2139 case PO_DIR: PCOR(pcop)->instance += offset; break;
2140 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2145 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2146 assert( 0 ); /* should never reach here */;
2151 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2152 "pic16_popGet got unsupported aop->type");
2155 /*-----------------------------------------------------------------*/
2156 /* pic16_aopPut - puts a string for a aop */
2157 /*-----------------------------------------------------------------*/
2158 void pic16_aopPut (asmop *aop, char *s, int offset)
2165 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2167 if (aop->size && offset > ( aop->size - 1)) {
2168 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2169 "pic16_aopPut got offset > aop->size");
2173 /* will assign value to value */
2174 /* depending on where it is ofcourse */
2175 switch (aop->type) {
2178 sprintf(d,"(%s + %d)",
2179 aop->aopu.aop_dir,offset);
2180 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2183 sprintf(d,"%s",aop->aopu.aop_dir);
2186 DEBUGpic16_emitcode(";","%d",__LINE__);
2188 pic16_emitcode("movf","%s,w",s);
2189 pic16_emitcode("movwf","%s",d);
2192 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2193 if(offset >= aop->size) {
2194 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2197 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2200 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2207 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2208 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2211 strcmp(s,"r0") == 0 ||
2212 strcmp(s,"r1") == 0 ||
2213 strcmp(s,"r2") == 0 ||
2214 strcmp(s,"r3") == 0 ||
2215 strcmp(s,"r4") == 0 ||
2216 strcmp(s,"r5") == 0 ||
2217 strcmp(s,"r6") == 0 ||
2218 strcmp(s,"r7") == 0 )
2219 pic16_emitcode("mov","%s,%s ; %d",
2220 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2224 if(strcmp(s,"W")==0 )
2225 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2227 pic16_emitcode("movwf","%s",
2228 aop->aopu.aop_reg[offset]->name);
2230 if(strcmp(s,zero)==0) {
2231 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2233 } else if(strcmp(s,"W")==0) {
2234 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2235 pcop->type = PO_GPR_REGISTER;
2237 PCOR(pcop)->rIdx = -1;
2238 PCOR(pcop)->r = NULL;
2240 DEBUGpic16_emitcode(";","%d",__LINE__);
2241 pcop->name = Safe_strdup(s);
2242 pic16_emitpcode(POC_MOVFW,pcop);
2243 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2244 } else if(strcmp(s,one)==0) {
2245 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2246 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2248 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2256 if (aop->type == AOP_DPTR2)
2262 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2263 "pic16_aopPut writting to code space");
2267 while (offset > aop->coff) {
2269 pic16_emitcode ("inc","dptr");
2272 while (offset < aop->coff) {
2274 pic16_emitcode("lcall","__decdptr");
2279 /* if not in accumulater */
2282 pic16_emitcode ("movx","@dptr,a");
2284 if (aop->type == AOP_DPTR2)
2292 while (offset > aop->coff) {
2294 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2296 while (offset < aop->coff) {
2298 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2304 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2309 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2311 if (strcmp(s,"r0") == 0 ||
2312 strcmp(s,"r1") == 0 ||
2313 strcmp(s,"r2") == 0 ||
2314 strcmp(s,"r3") == 0 ||
2315 strcmp(s,"r4") == 0 ||
2316 strcmp(s,"r5") == 0 ||
2317 strcmp(s,"r6") == 0 ||
2318 strcmp(s,"r7") == 0 ) {
2320 sprintf(buffer,"a%s",s);
2321 pic16_emitcode("mov","@%s,%s",
2322 aop->aopu.aop_ptr->name,buffer);
2324 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2329 if (strcmp(s,"a") == 0)
2330 pic16_emitcode("push","acc");
2332 pic16_emitcode("push","%s",s);
2337 /* if bit variable */
2338 if (!aop->aopu.aop_dir) {
2339 pic16_emitcode("clr","a");
2340 pic16_emitcode("rlc","a");
2343 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2346 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2349 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2351 lbl = newiTempLabel(NULL);
2353 if (strcmp(s,"a")) {
2356 pic16_emitcode("clr","c");
2357 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2358 pic16_emitcode("cpl","c");
2359 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2360 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2367 if (strcmp(aop->aopu.aop_str[offset],s))
2368 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2373 if (!offset && (strcmp(s,"acc") == 0))
2376 if (strcmp(aop->aopu.aop_str[offset],s))
2377 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2381 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2382 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2383 // "pic16_aopPut got unsupported aop->type");
2389 /*-----------------------------------------------------------------*/
2390 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2391 /*-----------------------------------------------------------------*/
2392 void pic16_mov2w (asmop *aop, int offset)
2394 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2397 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2399 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2402 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2404 if(is_LitAOp(src)) {
2405 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2406 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2408 if(pic16_sameRegsOfs(src, dst, offset))return;
2409 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2410 pic16_popGet(dst, offset)));
2414 static void pic16_movLit2f(pCodeOp *pc, int lit)
2416 if (0 == (lit & 0x00ff))
2418 pic16_emitpcode (POC_CLRF, pc);
2419 } else if (0xff == (lit & 0x00ff))
2421 pic16_emitpcode (POC_SETF, pc);
2423 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2424 if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2428 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2430 if(is_LitAOp(src)) {
2431 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2432 pic16_emitpcode(POC_MOVWF, dst);
2434 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2438 void pic16_testStackOverflow(void)
2440 #define GSTACK_TEST_NAME "_gstack_test"
2442 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2447 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2448 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2449 // strcpy(sym->rname, GSTACK_TEST_NAME);
2450 checkAddSym(&externs, sym);
2455 /* push pcop into stack */
2456 void pic16_pushpCodeOp(pCodeOp *pcop)
2458 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2460 if(pic16_options.gstack)
2461 pic16_testStackOverflow();
2465 /* pop pcop from stack */
2466 void pic16_poppCodeOp(pCodeOp *pcop)
2468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2469 if(pic16_options.gstack)
2470 pic16_testStackOverflow();
2474 /*-----------------------------------------------------------------*/
2475 /* pushw - pushes wreg to stack */
2476 /*-----------------------------------------------------------------*/
2479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2480 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2481 if(pic16_options.gstack)
2482 pic16_testStackOverflow();
2486 /*-----------------------------------------------------------------*/
2487 /* pushaop - pushes aop to stack */
2488 /*-----------------------------------------------------------------*/
2489 void pushaop(asmop *aop, int offset)
2491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2493 if(is_LitAOp(aop)) {
2494 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2495 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2497 pic16_emitpcode(POC_MOVFF,
2498 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2501 if(pic16_options.gstack)
2502 pic16_testStackOverflow();
2505 /*-----------------------------------------------------------------*/
2506 /* popaop - pops aop from stack */
2507 /*-----------------------------------------------------------------*/
2508 void popaop(asmop *aop, int offset)
2510 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2511 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2512 if(pic16_options.gstack)
2513 pic16_testStackOverflow();
2516 void popaopidx(asmop *aop, int offset, int index)
2520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2522 if(STACK_MODEL_LARGE)ofs++;
2524 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2525 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2526 if(pic16_options.gstack)
2527 pic16_testStackOverflow();
2530 #if !(USE_GENERIC_SIGNED_SHIFT)
2531 /*-----------------------------------------------------------------*/
2532 /* reAdjustPreg - points a register back to where it should */
2533 /*-----------------------------------------------------------------*/
2534 static void reAdjustPreg (asmop *aop)
2538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2540 if ((size = aop->size) <= 1)
2543 switch (aop->type) {
2547 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2551 if (aop->type == AOP_DPTR2)
2557 pic16_emitcode("lcall","__decdptr");
2560 if (aop->type == AOP_DPTR2)
2572 /*-----------------------------------------------------------------*/
2573 /* opIsGptr: returns non-zero if the passed operand is */
2574 /* a generic pointer type. */
2575 /*-----------------------------------------------------------------*/
2576 static int opIsGptr(operand *op)
2578 sym_link *type = operandType(op);
2580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2581 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_getDataSize - get the operand data size */
2591 /*-----------------------------------------------------------------*/
2592 int pic16_getDataSize(operand *op)
2594 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2597 return AOP_SIZE(op);
2599 // tsd- in the pic port, the genptr size is 1, so this code here
2600 // fails. ( in the 8051 port, the size was 4).
2603 size = AOP_SIZE(op);
2604 if (size == GPTRSIZE)
2606 sym_link *type = operandType(op);
2607 if (IS_GENPTR(type))
2609 /* generic pointer; arithmetic operations
2610 * should ignore the high byte (pointer type).
2613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2620 /*-----------------------------------------------------------------*/
2621 /* pic16_outAcc - output Acc */
2622 /*-----------------------------------------------------------------*/
2623 void pic16_outAcc(operand *result)
2626 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2627 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2630 size = pic16_getDataSize(result);
2632 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2635 /* unsigned or positive */
2637 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2642 /*-----------------------------------------------------------------*/
2643 /* pic16_outBitC - output a bit C */
2644 /* Move to result the value of Carry flag -- VR */
2645 /*-----------------------------------------------------------------*/
2646 void pic16_outBitC(operand *result)
2650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2652 /* if the result is bit */
2653 if (AOP_TYPE(result) == AOP_CRY) {
2654 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2655 pic16_aopPut(AOP(result),"c",0);
2658 i = AOP_SIZE(result);
2660 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2662 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2666 /*-----------------------------------------------------------------*/
2667 /* pic16_outBitOp - output a bit from Op */
2668 /* Move to result the value of set/clr op -- VR */
2669 /*-----------------------------------------------------------------*/
2670 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2674 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2676 /* if the result is bit */
2677 if (AOP_TYPE(result) == AOP_CRY) {
2678 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2679 pic16_aopPut(AOP(result),"c",0);
2682 i = AOP_SIZE(result);
2684 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2686 pic16_emitpcode(POC_RRCF, pcop);
2687 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2691 /*-----------------------------------------------------------------*/
2692 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2693 /*-----------------------------------------------------------------*/
2694 void pic16_toBoolean(operand *oper)
2696 int size = AOP_SIZE(oper) - 1;
2699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2701 if ( AOP_TYPE(oper) != AOP_ACC) {
2702 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2705 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2709 /*-----------------------------------------------------------------*/
2710 /* genUminusFloat - unary minus for floating points */
2711 /*-----------------------------------------------------------------*/
2712 static void genUminusFloat(operand *op,operand *result)
2714 int size ,offset =0 ;
2717 /* for this we just need to flip the
2718 first it then copy the rest in place */
2719 size = AOP_SIZE(op);
2720 assert( size == AOP_SIZE(result) );
2723 pic16_mov2f(AOP(result), AOP(op), offset);
2727 /* toggle the MSB's highest bit */
2728 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2731 /*-----------------------------------------------------------------*/
2732 /* genUminus - unary minus code generation */
2733 /*-----------------------------------------------------------------*/
2734 static void genUminus (iCode *ic)
2737 sym_link *optype, *rtype;
2744 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2745 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2747 /* if both in bit space then special case */
2748 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2749 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2751 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2752 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2753 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2757 optype = operandType(IC_LEFT(ic));
2758 rtype = operandType(IC_RESULT(ic));
2761 /* if float then do float stuff */
2762 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2763 if(IS_FIXED(optype))
2764 debugf("implement fixed16x16 type\n", 0);
2766 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2770 /* otherwise subtract from zero by taking the 2's complement */
2771 size = AOP_SIZE(IC_LEFT(ic));
2772 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2773 label = newiTempLabel ( NULL );
2775 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2776 for (i=size-1; i > 0; i--) {
2777 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2779 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2780 for (i=1; i < size; i++) {
2781 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2782 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2785 for (i=size-1; i >= 0; i--) {
2786 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2787 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2790 for (i=0; i < size-2; i++) {
2791 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2792 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2794 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2796 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2799 pic16_emitpLabel (label->key);
2802 /* release the aops */
2803 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2804 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2808 /*-----------------------------------------------------------------*/
2809 /* saveRegisters - will look for a call and save the registers */
2810 /*-----------------------------------------------------------------*/
2811 static void saveRegisters(iCode *lic)
2818 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2820 for (ic = lic ; ic ; ic = ic->next)
2821 if (ic->op == CALL || ic->op == PCALL)
2825 fprintf(stderr,"found parameter push with no function call\n");
2829 /* if the registers have been saved already then
2831 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2834 /* find the registers in use at this time
2835 and push them away to safety */
2836 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2840 if (options.useXstack) {
2841 if (bitVectBitValue(rsave,R0_IDX))
2842 pic16_emitcode("mov","b,r0");
2843 pic16_emitcode("mov","r0,%s",spname);
2844 for (i = 0 ; i < pic16_nRegs ; i++) {
2845 if (bitVectBitValue(rsave,i)) {
2847 pic16_emitcode("mov","a,b");
2849 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2850 pic16_emitcode("movx","@r0,a");
2851 pic16_emitcode("inc","r0");
2854 pic16_emitcode("mov","%s,r0",spname);
2855 if (bitVectBitValue(rsave,R0_IDX))
2856 pic16_emitcode("mov","r0,b");
2858 //for (i = 0 ; i < pic16_nRegs ; i++) {
2859 // if (bitVectBitValue(rsave,i))
2860 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2863 dtype = operandType(IC_LEFT(ic));
2864 if (currFunc && dtype &&
2865 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2866 IFFUNC_ISISR(currFunc->type) &&
2869 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2872 /*-----------------------------------------------------------------*/
2873 /* unsaveRegisters - pop the pushed registers */
2874 /*-----------------------------------------------------------------*/
2875 static void unsaveRegisters (iCode *ic)
2880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2881 /* find the registers in use at this time
2882 and push them away to safety */
2883 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2886 if (options.useXstack) {
2887 pic16_emitcode("mov","r0,%s",spname);
2888 for (i = pic16_nRegs ; i >= 0 ; i--) {
2889 if (bitVectBitValue(rsave,i)) {
2890 pic16_emitcode("dec","r0");
2891 pic16_emitcode("movx","a,@r0");
2893 pic16_emitcode("mov","b,a");
2895 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2899 pic16_emitcode("mov","%s,r0",spname);
2900 if (bitVectBitValue(rsave,R0_IDX))
2901 pic16_emitcode("mov","r0,b");
2903 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2904 // if (bitVectBitValue(rsave,i))
2905 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2912 /*-----------------------------------------------------------------*/
2914 /*-----------------------------------------------------------------*/
2915 static void pushSide(operand * oper, int size)
2918 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2920 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2921 if (AOP_TYPE(oper) != AOP_REG &&
2922 AOP_TYPE(oper) != AOP_DIR &&
2924 pic16_emitcode("mov","a,%s",l);
2925 pic16_emitcode("push","acc");
2927 pic16_emitcode("push","%s",l);
2932 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2934 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2935 pic16_emitpcode(POC_MOVFW, src);
2936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2938 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2939 src, pic16_popGet(AOP(op), offset)));
2944 /*-----------------------------------------------------------------*/
2945 /* assignResultValue - assign results to oper, rescall==1 is */
2946 /* called from genCall() or genPcall() */
2947 /*-----------------------------------------------------------------*/
2948 static void assignResultValue(operand * oper, int rescall)
2950 int size = AOP_SIZE(oper);
2954 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2955 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2958 /* assign result from a call/pcall function() */
2960 /* function results are stored in a special order,
2961 * see top of file with Function return policy, or manual */
2964 /* 8-bits, result in WREG */
2965 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2968 /* 16-bits, result in PRODL:WREG */
2969 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2973 /* 24-bits, result in PRODH:PRODL:WREG */
2974 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2978 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2979 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2983 /* >32-bits, result on stack, and FSR0 points to beginning.
2984 * Fix stack when done */
2986 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2988 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2989 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2991 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2996 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2997 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2998 if(STACK_MODEL_LARGE) {
3000 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3004 int areg = 0; /* matching argument register */
3006 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3007 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3010 /* its called from genReceive (probably) -- VR */
3011 /* I hope this code will not be called from somewhere else in the future!
3012 * We manually set the pseudo stack pointer in genReceive. - dw
3014 if(!GpsuedoStkPtr && _G.useWreg) {
3015 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3017 /* The last byte in the assignment is in W */
3018 if(areg <= GpsuedoStkPtr) {
3020 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3022 // debugf("receive from WREG\n", 0);
3024 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3027 _G.stack_lat = AOP_SIZE(oper)-1;
3032 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3033 // debugf("receive from STACK\n", 0);
3040 /*-----------------------------------------------------------------*/
3041 /* genIpush - generate code for pushing this gets a little complex */
3042 /*-----------------------------------------------------------------*/
3043 static void genIpush (iCode *ic)
3045 // int size, offset=0;
3048 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3051 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3053 /* send to stack as normal */
3054 addSet(&_G.sendSet,ic);
3055 // addSetHead(&_G.sendSet,ic);
3056 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3061 int size, offset = 0 ;
3065 /* if this is not a parm push : ie. it is spill push
3066 and spill push is always done on the local stack */
3067 if (!ic->parmPush) {
3069 /* and the item is spilt then do nothing */
3070 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3073 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3074 size = AOP_SIZE(IC_LEFT(ic));
3075 /* push it on the stack */
3077 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3082 pic16_emitcode("push","%s",l);
3087 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3091 /*-----------------------------------------------------------------*/
3092 /* genIpop - recover the registers: can happen only for spilling */
3093 /*-----------------------------------------------------------------*/
3094 static void genIpop (iCode *ic)
3097 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3102 /* if the temp was not pushed then */
3103 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3106 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3107 size = AOP_SIZE(IC_LEFT(ic));
3110 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3113 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3118 /*-----------------------------------------------------------------*/
3119 /* unsaverbank - restores the resgister bank from stack */
3120 /*-----------------------------------------------------------------*/
3121 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3123 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3129 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3131 if (options.useXstack) {
3133 r = getFreePtr(ic,&aop,FALSE);
3136 pic16_emitcode("mov","%s,_spx",r->name);
3137 pic16_emitcode("movx","a,@%s",r->name);
3138 pic16_emitcode("mov","psw,a");
3139 pic16_emitcode("dec","%s",r->name);
3142 pic16_emitcode ("pop","psw");
3145 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3146 if (options.useXstack) {
3147 pic16_emitcode("movx","a,@%s",r->name);
3148 //pic16_emitcode("mov","(%s+%d),a",
3149 // regspic16[i].base,8*bank+regspic16[i].offset);
3150 pic16_emitcode("dec","%s",r->name);
3153 pic16_emitcode("pop",""); //"(%s+%d)",
3154 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3157 if (options.useXstack) {
3159 pic16_emitcode("mov","_spx,%s",r->name);
3160 pic16_freeAsmop(NULL,aop,ic,TRUE);
3166 /*-----------------------------------------------------------------*/
3167 /* saverbank - saves an entire register bank on the stack */
3168 /*-----------------------------------------------------------------*/
3169 static void saverbank (int bank, iCode *ic, bool pushPsw)
3171 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3178 if (options.useXstack) {
3181 r = getFreePtr(ic,&aop,FALSE);
3182 pic16_emitcode("mov","%s,_spx",r->name);
3186 for (i = 0 ; i < pic16_nRegs ;i++) {
3187 if (options.useXstack) {
3188 pic16_emitcode("inc","%s",r->name);
3189 //pic16_emitcode("mov","a,(%s+%d)",
3190 // regspic16[i].base,8*bank+regspic16[i].offset);
3191 pic16_emitcode("movx","@%s,a",r->name);
3193 pic16_emitcode("push","");// "(%s+%d)",
3194 //regspic16[i].base,8*bank+regspic16[i].offset);
3198 if (options.useXstack) {
3199 pic16_emitcode("mov","a,psw");
3200 pic16_emitcode("movx","@%s,a",r->name);
3201 pic16_emitcode("inc","%s",r->name);
3202 pic16_emitcode("mov","_spx,%s",r->name);
3203 pic16_freeAsmop (NULL,aop,ic,TRUE);
3206 pic16_emitcode("push","psw");
3208 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3216 static int wparamCmp(void *p1, void *p2)
3218 return (!strcmp((char *)p1, (char *)p2));
3221 int inWparamList(char *s)
3223 return isinSetWith(wparamList, s, wparamCmp);
3227 /*-----------------------------------------------------------------*/
3228 /* genCall - generates a call statement */
3229 /*-----------------------------------------------------------------*/
3230 static void genCall (iCode *ic)
3240 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3241 /* if caller saves & we have not saved then */
3242 // if (!ic->regsSaved)
3243 // saveRegisters(ic);
3245 /* initialise stackParms for IPUSH pushes */
3246 // stackParms = psuedoStkPtr;
3247 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3248 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3249 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3252 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3255 /* if send set is not empty the assign */
3258 int psuedoStkPtr=-1;
3259 int firstTimeThruLoop = 1;
3262 /* reverse sendSet if function is not reentrant */
3263 if(!IFFUNC_ISREENT(ftype))
3264 _G.sendSet = reverseSet(_G.sendSet);
3266 /* First figure how many parameters are getting passed */
3270 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3274 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3275 size = AOP_SIZE(IC_LEFT(sic));
3279 /* pass the last byte through WREG */
3283 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3284 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3285 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3287 if(!firstTimeThruLoop) {
3288 /* If this is not the first time we've been through the loop
3289 * then we need to save the parameter in a temporary
3290 * register. The last byte of the last parameter is
3294 // --psuedoStkPtr; // sanity check
3298 firstTimeThruLoop=0;
3300 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3305 /* all arguments are passed via stack */
3309 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3310 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3311 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3313 // pushaop(AOP(IC_LEFT(sic)), size);
3314 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3321 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3325 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3326 pushw(); /* save last parameter to stack if functions has varargs */
3330 } else use_wreg = 0;
3332 _G.stackRegSet = _G.sendSet;
3337 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3341 /* if we need to assign a result value */
3342 if ((IS_ITEMP(IC_RESULT(ic))
3343 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3344 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3345 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3348 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3351 assignResultValue(IC_RESULT(ic), 1);
3353 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3354 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3356 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3359 if(!stackParms && ic->parmBytes) {
3360 stackParms = ic->parmBytes;
3363 stackParms -= use_wreg;
3366 if(stackParms == 1) {
3367 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3369 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3370 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3372 if(STACK_MODEL_LARGE) {
3374 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3379 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3382 /* adjust the stack for parameters if required */
3383 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3386 /* if register bank was saved then pop them */
3388 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3390 /* if we hade saved some registers then unsave them */
3391 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3392 unsaveRegisters (ic);
3398 /*-----------------------------------------------------------------*/
3399 /* genPcall - generates a call by pointer statement */
3400 /* new version, created from genCall - HJD */
3401 /*-----------------------------------------------------------------*/
3402 static void genPcall (iCode *ic)
3404 sym_link *ftype, *fntype;
3406 symbol *retlbl = newiTempLabel(NULL);
3407 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3411 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3412 fntype = operandType( IC_LEFT(ic) )->next;
3414 /* if send set is not empty the assign */
3417 int psuedoStkPtr=-1;
3419 /* reverse sendSet if function is not reentrant */
3420 if(!IFFUNC_ISREENT(fntype))
3421 _G.sendSet = reverseSet(_G.sendSet);
3425 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3428 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3429 size = AOP_SIZE(IC_LEFT(sic));
3432 /* all parameters are passed via stack, since WREG is clobbered
3433 * by the calling sequence */
3435 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3436 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3437 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3439 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3443 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3446 _G.stackRegSet = _G.sendSet;
3450 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3452 // push return address
3453 // push $ on return stack, then replace with retlbl
3455 /* Thanks to Thorsten Klose for pointing out that the following
3456 * snippet should be interrupt safe */
3457 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3458 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3460 pic16_emitpcodeNULLop(POC_PUSH);
3462 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3463 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3464 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3465 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3466 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3467 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3470 /* restore interrupt control register */
3471 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3472 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3474 /* make the call by writing the pointer into pc */
3475 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3476 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3478 // note: MOVFF to PCL not allowed
3479 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3480 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3483 /* return address is here: (X) */
3484 pic16_emitpLabelFORCE(retlbl->key);
3486 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3489 /* if we need assign a result value */
3490 if ((IS_ITEMP(IC_RESULT(ic))
3491 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3492 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3493 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3496 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3499 assignResultValue(IC_RESULT(ic), 1);
3501 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3502 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3504 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3507 // stackParms -= use_wreg;
3510 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3511 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3512 if(STACK_MODEL_LARGE) {
3514 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3519 /*-----------------------------------------------------------------*/
3520 /* resultRemat - result is rematerializable */
3521 /*-----------------------------------------------------------------*/
3522 static int resultRemat (iCode *ic)
3524 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3525 if (SKIP_IC(ic) || ic->op == IFX)
3528 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3529 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3530 if (sym->remat && !POINTER_SET(ic))
3537 #if defined(__BORLANDC__) || defined(_MSC_VER)
3538 #define STRCASECMP stricmp
3540 #define STRCASECMP strcasecmp
3544 /*-----------------------------------------------------------------*/
3545 /* inExcludeList - return 1 if the string is in exclude Reg list */
3546 /*-----------------------------------------------------------------*/
3547 static bool inExcludeList(char *s)
3549 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3553 if (options.excludeRegs[i] &&
3554 STRCASECMP(options.excludeRegs[i],"none") == 0)
3557 for ( i = 0 ; options.excludeRegs[i]; i++) {
3558 if (options.excludeRegs[i] &&
3559 STRCASECMP(s,options.excludeRegs[i]) == 0)
3566 /*-----------------------------------------------------------------*/
3567 /* genFunction - generated code for function entry */
3568 /*-----------------------------------------------------------------*/
3569 static void genFunction (iCode *ic)
3575 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3577 pic16_labelOffset += (max_key+4);
3582 ftype = operandType(IC_LEFT(ic));
3583 sym = OP_SYMBOL(IC_LEFT(ic));
3585 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3586 /* create an absolute section at the interrupt vector:
3587 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3592 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3594 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3595 sprintf(asymname, "ivec_%s", sym->name);
3597 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3599 /* when an interrupt is declared as naked, do not emit the special
3600 * wrapper segment at vector address. The user should take care for
3601 * this instead. -- VR */
3603 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3604 asym = newSymbol(asymname, 0);
3605 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3606 pic16_addpBlock( apb );
3608 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3609 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3610 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3611 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3612 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3614 /* mark the end of this tiny function */
3615 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3617 sprintf(asymname, "%s", sym->rname);
3623 abSym = Safe_calloc(1, sizeof(absSym));
3624 strcpy(abSym->name, asymname);
3626 switch( FUNC_INTNO(sym->type) ) {
3627 case 0: abSym->address = 0x000000; break;
3628 case 1: abSym->address = 0x000008; break;
3629 case 2: abSym->address = 0x000018; break;
3632 // fprintf(stderr, "no interrupt number is given\n");
3633 abSym->address = -1; break;
3636 /* relocate interrupt vectors if needed */
3637 if(abSym->address != -1)
3638 abSym->address += pic16_options.ivt_loc;
3640 addSet(&absSymSet, abSym);
3644 /* create the function header */
3645 pic16_emitcode(";","-----------------------------------------");
3646 pic16_emitcode(";"," function %s",sym->name);
3647 pic16_emitcode(";","-----------------------------------------");
3649 pic16_emitcode("","%s:",sym->rname);
3650 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3655 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3656 if(!strcmp(ab->name, sym->rname)) {
3657 pic16_pBlockConvert2Absolute(pb);
3663 if(IFFUNC_ISNAKED(ftype)) {
3664 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3668 /* if critical function then turn interrupts off */
3669 if (IFFUNC_ISCRITICAL(ftype)) {
3670 //pic16_emitcode("clr","ea");
3673 currFunc = sym; /* update the currFunc symbol */
3674 _G.fregsUsed = sym->regsUsed;
3675 _G.sregsAlloc = newBitVect(128);
3678 /* if this is an interrupt service routine then
3679 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3680 if (IFFUNC_ISISR(sym->type)) {
3681 _G.usefastretfie = 1; /* use shadow registers by default */
3683 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3684 if(!FUNC_ISSHADOWREGS(sym->type)) {
3685 /* do not save WREG,STATUS,BSR for high priority interrupts
3686 * because they are stored in the hardware shadow registers already */
3687 _G.usefastretfie = 0;
3688 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3689 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3690 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3693 /* these should really be optimized somehow, because not all
3694 * interrupt handlers modify them */
3695 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3696 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3697 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3698 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3700 // pic16_pBlockConvert2ISR(pb);
3703 /* emit code to setup stack frame if user enabled,
3704 * and function is not main() */
3706 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3707 if(strcmp(sym->name, "main")) {
3709 || !options.ommitFramePtr
3711 || IFFUNC_ARGS(sym->type)
3712 || FUNC_HASSTACKPARM(sym->etype)
3714 /* setup the stack frame */
3715 if(STACK_MODEL_LARGE)
3716 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3717 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3719 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3720 if(STACK_MODEL_LARGE)
3721 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3725 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3728 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3730 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3731 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3733 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3736 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3737 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3744 /* if callee-save to be used for this function
3745 * then save the registers being used in this function */
3746 // if (IFFUNC_CALLEESAVES(sym->type))
3750 /* if any registers used */
3751 if (sym->regsUsed) {
3752 /* save the registers used */
3753 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3754 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3755 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3756 if (bitVectBitValue(sym->regsUsed,i)) {
3757 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3760 if(!pic16_regWithIdx(i)->wasUsed) {
3761 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3762 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3763 pic16_regWithIdx(i)->wasUsed = 1;
3767 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3771 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3772 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3775 /*-----------------------------------------------------------------*/
3776 /* genEndFunction - generates epilogue for functions */
3777 /*-----------------------------------------------------------------*/
3778 static void genEndFunction (iCode *ic)
3780 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3784 if(IFFUNC_ISNAKED(sym->type)) {
3785 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3791 /* add code for ISCRITICAL */
3792 if(IFFUNC_ISCRITICAL(sym->type)) {
3793 /* if critical function, turn on interrupts */
3795 /* TODO: add code here -- VR */
3798 // sym->regsUsed = _G.fregsUsed;
3800 /* now we need to restore the registers */
3801 /* if any registers used */
3803 /* first restore registers that might be used for stack access */
3804 if(_G.sregsAllocSet) {
3807 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3808 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3809 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3813 if (sym->regsUsed) {
3816 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3817 /* restore registers used */
3818 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3819 for ( i = sym->regsUsed->size; i >= 0; i--) {
3820 if (bitVectBitValue(sym->regsUsed,i)) {
3821 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3825 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3830 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3832 if (sym->stack == 1) {
3833 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3834 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3836 // we have to add more than one...
3837 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3838 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3839 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3841 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3842 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3843 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3847 if(strcmp(sym->name, "main")) {
3849 || !options.ommitFramePtr
3851 || IFFUNC_ARGS(sym->type)
3852 || FUNC_HASSTACKPARM(sym->etype)
3854 /* restore stack frame */
3855 if(STACK_MODEL_LARGE)
3856 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3857 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3863 if (IFFUNC_ISISR(sym->type)) {
3864 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3865 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3866 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3867 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3869 if(!FUNC_ISSHADOWREGS(sym->type)) {
3870 /* do not restore interrupt vector for WREG,STATUS,BSR
3871 * for high priority interrupt, see genFunction */
3872 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3873 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3874 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3876 // _G.interruptvector = 0; /* sanity check */
3879 /* if debug then send end of function */
3880 /* if (options.debug && currFunc) */
3882 debugFile->writeEndFunction (currFunc, ic, 1);
3885 if(_G.usefastretfie)
3886 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3888 pic16_emitpcodeNULLop(POC_RETFIE);
3890 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3892 _G.usefastretfie = 0;
3896 if (IFFUNC_ISCRITICAL(sym->type)) {
3897 pic16_emitcode("setb","ea");
3900 /* if debug then send end of function */
3902 debugFile->writeEndFunction (currFunc, ic, 1);
3905 /* insert code to restore stack frame, if user enabled it
3906 * and function is not main() */
3909 pic16_emitpcodeNULLop(POC_RETURN);
3911 /* Mark the end of a function */
3912 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3916 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3918 unsigned long lit=1;
3923 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3924 if(AOP_TYPE(op) == AOP_LIT) {
3925 if(!IS_FLOAT(operandType( op ))) {
3926 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3929 unsigned long lit_int;
3933 /* take care if literal is a float */
3934 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3940 pic16_movLit2f(dest, lit);
3942 if(dest->type == PO_WREG && (offset == 0)) {
3943 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3946 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3950 /*-----------------------------------------------------------------*/
3951 /* genRet - generate code for return statement */
3952 /*-----------------------------------------------------------------*/
3953 static void genRet (iCode *ic)
3959 /* if we have no return value then
3960 * just generate the "ret" */
3965 /* we have something to return then
3966 * move the return value into place */
3967 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3968 size = AOP_SIZE(IC_LEFT(ic));
3972 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3975 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3978 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3980 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3983 /* >32-bits, setup stack and FSR0 */
3985 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3986 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3988 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3990 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3995 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3996 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3998 if(STACK_MODEL_LARGE) {
3999 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4000 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4002 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4007 /* old code, left here for reference -- VR */
4011 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4013 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4014 pic16_emitpcomment("push %s",l);
4017 DEBUGpic16_emitcode(";", "%d", __LINE__);
4018 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4019 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4021 if (strcmp(fReturn[offset],l)) {
4022 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4023 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4024 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4026 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4030 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4040 if (strcmp(fReturn[pushed],"a"))
4041 pic16_emitcode("pop",fReturn[pushed]);
4043 pic16_emitcode("pop","acc");
4049 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4052 /* generate a jump to the return label
4053 * if the next is not the return statement */
4054 if (!(ic->next && ic->next->op == LABEL
4055 && IC_LABEL(ic->next) == returnLabel)) {
4057 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4058 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4062 /*-----------------------------------------------------------------*/
4063 /* genLabel - generates a label */
4064 /*-----------------------------------------------------------------*/
4065 static void genLabel (iCode *ic)
4069 /* special case never generate */
4070 if (IC_LABEL(ic) == entryLabel)
4073 pic16_emitpLabel(IC_LABEL(ic)->key);
4074 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4077 /*-----------------------------------------------------------------*/
4078 /* genGoto - generates a goto */
4079 /*-----------------------------------------------------------------*/
4081 static void genGoto (iCode *ic)
4084 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4085 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4089 /*-----------------------------------------------------------------*/
4090 /* genMultbits :- multiplication of bits */
4091 /*-----------------------------------------------------------------*/
4092 static void genMultbits (operand *left,
4098 if(!pic16_sameRegs(AOP(result),AOP(right)))
4099 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4101 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4102 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4103 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4108 /*-----------------------------------------------------------------*/
4109 /* genMultOneByte : 8 bit multiplication & division */
4110 /*-----------------------------------------------------------------*/
4111 static void genMultOneByte (operand *left,
4117 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4118 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4120 /* (if two literals, the value is computed before) */
4121 /* if one literal, literal on the right */
4122 if (AOP_TYPE(left) == AOP_LIT){
4128 /* size is already checked in genMult == 1 */
4129 // size = AOP_SIZE(result);
4131 if (AOP_TYPE(right) == AOP_LIT){
4132 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4133 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4134 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4135 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4137 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4138 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4139 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4140 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4143 pic16_genMult8X8_8 (left, right,result);
4146 /*-----------------------------------------------------------------*/
4147 /* genMultOneWord : 16 bit multiplication */
4148 /*-----------------------------------------------------------------*/
4149 static void genMultOneWord (operand *left,
4154 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4155 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4157 /* (if two literals, the value is computed before)
4158 * if one literal, literal on the right */
4159 if (AOP_TYPE(left) == AOP_LIT){
4165 /* size is checked already == 2 */
4166 // size = AOP_SIZE(result);
4168 if (AOP_TYPE(right) == AOP_LIT) {
4169 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4170 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4171 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4172 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4174 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4175 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4176 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4177 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4180 pic16_genMult16X16_16(left, right,result);
4183 /*-----------------------------------------------------------------*/
4184 /* genMultOneLong : 32 bit multiplication */
4185 /*-----------------------------------------------------------------*/
4186 static void genMultOneLong (operand *left,
4191 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4192 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4194 /* (if two literals, the value is computed before)
4195 * if one literal, literal on the right */
4196 if (AOP_TYPE(left) == AOP_LIT){
4202 /* size is checked already == 4 */
4203 // size = AOP_SIZE(result);
4205 if (AOP_TYPE(right) == AOP_LIT) {
4206 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4207 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4211 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4212 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4213 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4214 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4217 pic16_genMult32X32_32(left, right,result);
4222 /*-----------------------------------------------------------------*/
4223 /* genMult - generates code for multiplication */
4224 /*-----------------------------------------------------------------*/
4225 static void genMult (iCode *ic)
4227 operand *left = IC_LEFT(ic);
4228 operand *right = IC_RIGHT(ic);
4229 operand *result= IC_RESULT(ic);
4232 /* assign the amsops */
4233 pic16_aopOp (left,ic,FALSE);
4234 pic16_aopOp (right,ic,FALSE);
4235 pic16_aopOp (result,ic,TRUE);
4237 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4239 /* special cases first *
4241 if (AOP_TYPE(left) == AOP_CRY
4242 && AOP_TYPE(right)== AOP_CRY) {
4243 genMultbits(left,right,result);
4247 /* if both are of size == 1 */
4248 if(AOP_SIZE(left) == 1
4249 && AOP_SIZE(right) == 1) {
4250 genMultOneByte(left,right,result);
4254 /* if both are of size == 2 */
4255 if(AOP_SIZE(left) == 2
4256 && AOP_SIZE(right) == 2) {
4257 genMultOneWord(left, right, result);
4261 /* if both are of size == 4 */
4262 if(AOP_SIZE(left) == 4
4263 && AOP_SIZE(right) == 4) {
4264 genMultOneLong(left, right, result);
4268 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4271 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4272 /* should have been converted to function call */
4276 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4277 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278 pic16_freeAsmop(result,NULL,ic,TRUE);
4281 /*-----------------------------------------------------------------*/
4282 /* genDivbits :- division of bits */
4283 /*-----------------------------------------------------------------*/
4284 static void genDivbits (operand *left,
4291 /* the result must be bit */
4292 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4293 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4297 pic16_emitcode("div","ab");
4298 pic16_emitcode("rrc","a");
4299 pic16_aopPut(AOP(result),"c",0);
4302 /*-----------------------------------------------------------------*/
4303 /* genDivOneByte : 8 bit division */
4304 /*-----------------------------------------------------------------*/
4305 static void genDivOneByte (operand *left,
4309 sym_link *opetype = operandType(result);
4314 /* result = divident / divisor
4315 * - divident may be a register or a literal,
4316 * - divisor may be a register or a literal,
4317 * so there are 3 cases (literal / literal is optimized
4318 * by the front-end) to handle.
4319 * In addition we must handle signed and unsigned, which
4320 * result in 6 final different cases -- VR */
4324 size = AOP_SIZE(result) - 1;
4326 /* signed or unsigned */
4327 if (SPEC_USIGN(opetype)) {
4328 pCodeOp *pct1, /* count */
4331 symbol *label1, *label2, *label3;;
4334 /* unsigned is easy */
4336 pct1 = pic16_popGetTempReg(1);
4337 pct2 = pic16_popGetTempReg(1);
4338 pct3 = pic16_popGetTempReg(1);
4340 label1 = newiTempLabel(NULL);
4341 label2 = newiTempLabel(NULL);
4342 label3 = newiTempLabel(NULL);
4344 /* the following algorithm is extracted from divuint.c */
4346 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4347 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4349 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4351 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4353 pic16_emitpLabel(label1->key);
4356 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4360 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4364 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4366 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4367 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4369 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4370 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4371 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4373 pic16_emitpLabel( label3->key );
4374 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4375 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4379 pic16_emitpLabel(label2->key);
4380 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4381 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4382 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4384 /* result is in wreg */
4385 if(AOP_TYPE(result) != AOP_ACC)
4386 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4388 pic16_popReleaseTempReg( pct3, 1);
4389 pic16_popReleaseTempReg( pct2, 1);
4390 pic16_popReleaseTempReg( pct1, 1);
4395 /* signed is a little bit more difficult */
4397 /* save the signs of the operands */
4398 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4400 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4401 pic16_emitcode("push","acc"); /* save it on the stack */
4403 /* now sign adjust for both left & right */
4404 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4406 lbl = newiTempLabel(NULL);
4407 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4408 pic16_emitcode("cpl","a");
4409 pic16_emitcode("inc","a");
4410 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4411 pic16_emitcode("mov","b,a");
4413 /* sign adjust left side */
4414 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4417 lbl = newiTempLabel(NULL);
4418 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4419 pic16_emitcode("cpl","a");
4420 pic16_emitcode("inc","a");
4421 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4423 /* now the division */
4424 pic16_emitcode("div","ab");
4425 /* we are interested in the lower order
4427 pic16_emitcode("mov","b,a");
4428 lbl = newiTempLabel(NULL);
4429 pic16_emitcode("pop","acc");
4430 /* if there was an over flow we don't
4431 adjust the sign of the result */
4432 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4433 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4435 pic16_emitcode("clr","a");
4436 pic16_emitcode("subb","a,b");
4437 pic16_emitcode("mov","b,a");
4438 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4440 /* now we are done */
4441 pic16_aopPut(AOP(result),"b",0);
4443 pic16_emitcode("mov","c,b.7");
4444 pic16_emitcode("subb","a,acc");
4447 pic16_aopPut(AOP(result),"a",offset++);
4451 /*-----------------------------------------------------------------*/
4452 /* genDiv - generates code for division */
4453 /*-----------------------------------------------------------------*/
4454 static void genDiv (iCode *ic)
4456 operand *left = IC_LEFT(ic);
4457 operand *right = IC_RIGHT(ic);
4458 operand *result= IC_RESULT(ic);
4461 /* Division is a very lengthy algorithm, so it is better
4462 * to call support routines than inlining algorithm.
4463 * Division functions written here just in case someone
4464 * wants to inline and not use the support libraries -- VR */
4468 /* assign the amsops */
4469 pic16_aopOp (left,ic,FALSE);
4470 pic16_aopOp (right,ic,FALSE);
4471 pic16_aopOp (result,ic,TRUE);
4473 /* special cases first */
4475 if (AOP_TYPE(left) == AOP_CRY &&
4476 AOP_TYPE(right)== AOP_CRY) {
4477 genDivbits(left,right,result);
4481 /* if both are of size == 1 */
4482 if (AOP_SIZE(left) == 1 &&
4483 AOP_SIZE(right) == 1 ) {
4484 genDivOneByte(left,right,result);
4488 /* should have been converted to function call */
4491 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493 pic16_freeAsmop(result,NULL,ic,TRUE);
4496 /*-----------------------------------------------------------------*/
4497 /* genModbits :- modulus of bits */
4498 /*-----------------------------------------------------------------*/
4499 static void genModbits (operand *left,
4507 werror(W_POSSBUG2, __FILE__, __LINE__);
4508 /* the result must be bit */
4509 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4510 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4514 pic16_emitcode("div","ab");
4515 pic16_emitcode("mov","a,b");
4516 pic16_emitcode("rrc","a");
4517 pic16_aopPut(AOP(result),"c",0);
4520 /*-----------------------------------------------------------------*/
4521 /* genModOneByte : 8 bit modulus */
4522 /*-----------------------------------------------------------------*/
4523 static void genModOneByte (operand *left,
4527 sym_link *opetype = operandType(result);
4532 werror(W_POSSBUG2, __FILE__, __LINE__);
4534 /* signed or unsigned */
4535 if (SPEC_USIGN(opetype)) {
4536 /* unsigned is easy */
4537 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4538 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4540 pic16_emitcode("div","ab");
4541 pic16_aopPut(AOP(result),"b",0);
4545 /* signed is a little bit more difficult */
4547 /* save the signs of the operands */
4548 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4551 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4552 pic16_emitcode("push","acc"); /* save it on the stack */
4554 /* now sign adjust for both left & right */
4555 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4558 lbl = newiTempLabel(NULL);
4559 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4560 pic16_emitcode("cpl","a");
4561 pic16_emitcode("inc","a");
4562 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4563 pic16_emitcode("mov","b,a");
4565 /* sign adjust left side */
4566 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4569 lbl = newiTempLabel(NULL);
4570 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4571 pic16_emitcode("cpl","a");
4572 pic16_emitcode("inc","a");
4573 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4575 /* now the multiplication */
4576 pic16_emitcode("div","ab");
4577 /* we are interested in the lower order
4579 lbl = newiTempLabel(NULL);
4580 pic16_emitcode("pop","acc");
4581 /* if there was an over flow we don't
4582 adjust the sign of the result */
4583 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4584 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4586 pic16_emitcode("clr","a");
4587 pic16_emitcode("subb","a,b");
4588 pic16_emitcode("mov","b,a");
4589 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4591 /* now we are done */
4592 pic16_aopPut(AOP(result),"b",0);
4596 /*-----------------------------------------------------------------*/
4597 /* genMod - generates code for division */
4598 /*-----------------------------------------------------------------*/
4599 static void genMod (iCode *ic)
4601 operand *left = IC_LEFT(ic);
4602 operand *right = IC_RIGHT(ic);
4603 operand *result= IC_RESULT(ic);
4607 /* assign the amsops */
4608 pic16_aopOp (left,ic,FALSE);
4609 pic16_aopOp (right,ic,FALSE);
4610 pic16_aopOp (result,ic,TRUE);
4612 /* special cases first */
4614 if (AOP_TYPE(left) == AOP_CRY &&
4615 AOP_TYPE(right)== AOP_CRY) {
4616 genModbits(left,right,result);
4620 /* if both are of size == 1 */
4621 if (AOP_SIZE(left) == 1 &&
4622 AOP_SIZE(right) == 1 ) {
4623 genModOneByte(left,right,result);
4627 /* should have been converted to function call */
4631 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4632 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4633 pic16_freeAsmop(result,NULL,ic,TRUE);
4636 /*-----------------------------------------------------------------*/
4637 /* genIfxJump :- will create a jump depending on the ifx */
4638 /*-----------------------------------------------------------------*/
4640 note: May need to add parameter to indicate when a variable is in bit space.
4642 static void genIfxJump (iCode *ic, char *jval)
4646 /* if true label then we jump if condition
4648 if ( IC_TRUE(ic) ) {
4650 if(strcmp(jval,"a") == 0)
4652 else if (strcmp(jval,"c") == 0)
4655 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4656 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4659 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4660 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4664 /* false label is present */
4665 if(strcmp(jval,"a") == 0)
4667 else if (strcmp(jval,"c") == 0)
4670 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4671 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4674 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4675 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4680 /* mark the icode as generated */
4684 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4688 /* if true label then we jump if condition
4690 if ( IC_TRUE(ic) ) {
4691 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4692 pic16_emitpcode(POC_BTFSC, jop);
4694 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4695 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4698 /* false label is present */
4699 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4700 pic16_emitpcode(POC_BTFSS, jop);
4702 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4703 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4707 /* mark the icode as generated */
4714 /*-----------------------------------------------------------------*/
4716 /*-----------------------------------------------------------------*/
4717 static void genSkip(iCode *ifx,int status_bit)
4719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4723 if ( IC_TRUE(ifx) ) {
4724 switch(status_bit) {
4739 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4740 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4744 switch(status_bit) {
4758 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4759 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4766 /*-----------------------------------------------------------------*/
4768 /*-----------------------------------------------------------------*/
4769 static void genSkipc(resolvedIfx *rifx)
4771 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4781 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4782 rifx->generated = 1;
4785 #if !(USE_SIMPLE_GENCMP)
4786 /*-----------------------------------------------------------------*/
4788 /*-----------------------------------------------------------------*/
4789 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4791 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4796 if( (rifx->condition ^ invert_condition) & 1)
4801 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4802 rifx->generated = 1;
4807 /*-----------------------------------------------------------------*/
4809 /*-----------------------------------------------------------------*/
4810 static void genSkipz(iCode *ifx, int condition)
4821 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4823 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4826 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4828 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4833 #if !(USE_SIMPLE_GENCMP)
4834 /*-----------------------------------------------------------------*/
4836 /*-----------------------------------------------------------------*/
4837 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4843 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4845 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4848 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4849 rifx->generated = 1;
4854 /*-----------------------------------------------------------------*/
4855 /* genChkZeroes :- greater or less than comparison */
4856 /* For each byte in a literal that is zero, inclusive or the */
4857 /* the corresponding byte in the operand with W */
4858 /* returns true if any of the bytes are zero */
4859 /*-----------------------------------------------------------------*/
4860 static int genChkZeroes(operand *op, int lit, int size)
4867 i = (lit >> (size*8)) & 0xff;
4871 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4873 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4883 /*-----------------------------------------------------------------*/
4884 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4885 /* aop (if it's NOT a literal) or from lit (if */
4886 /* aop is a literal) */
4887 /*-----------------------------------------------------------------*/
4888 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4889 if (aop->type == AOP_LIT) {
4890 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4892 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4896 /*-----------------------------------------------------------------*/
4897 /* genCmp :- greater or less than comparison */
4898 /*-----------------------------------------------------------------*/
4900 #if USE_SIMPLE_GENCMP /* { */
4902 /* genCmp performs a left < right comparison, stores
4903 * the outcome in result (if != NULL) and generates
4904 * control flow code for the ifx (if != NULL).
4906 * This version leaves in sequences like
4907 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4908 * which should be optmized by the peephole
4909 * optimizer - RN 2005-01-01 */
4910 static void genCmp (operand *left,operand *right,
4911 operand *result, iCode *ifx, int sign)
4924 assert (left && right);
4925 assert (AOP_SIZE(left) == AOP_SIZE(right));
4927 size = AOP_SIZE(right) - 1;
4928 mask = (0x100UL << (size*8)) - 1;
4929 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4934 resolveIfx (&rIfx, ifx);
4936 /* handle for special cases */
4937 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4940 /**********************************************************************
4941 * handle bits - bit compares are promoted to int compares seemingly! *
4942 **********************************************************************/
4944 // THIS IS COMPLETELY UNTESTED!
4945 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4946 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4947 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4948 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4951 // 1 < {0,1} is false --> clear C by skipping the next instruction
4952 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4953 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4954 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4955 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4956 emitCLRC; // only skipped for left=0 && right=1
4958 goto correct_result_in_carry;
4962 /*************************************************
4963 * make sure that left is register (or the like) *
4964 *************************************************/
4965 if (!isAOP_REGlike(left)) {
4966 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4967 assert (isAOP_LIT(left));
4968 assert (isAOP_REGlike(right));
4969 // swap left and right
4970 // left < right <==> right > left <==> (right >= left + 1)
4971 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4973 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4974 // MAXVALUE < right? always false
4975 if (performedLt) emitCLRC; else emitSETC;
4976 goto correct_result_in_carry;
4979 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4980 // that's why we handled it above.
4987 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4988 } else if (isAOP_LIT(right)) {
4989 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4992 assert (isAOP_REGlike(left)); // left must be register or the like
4993 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4995 /*************************************************
4996 * special cases go here *
4997 *************************************************/
4999 if (isAOP_LIT(right)) {
5001 // unsigned comparison to a literal
5002 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5004 // unsigned left < 0? always false
5005 if (performedLt) emitCLRC; else emitSETC;
5006 goto correct_result_in_carry;
5009 // signed comparison to a literal
5010 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5011 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5012 // signed left < 0x80000000? always false
5013 if (performedLt) emitCLRC; else emitSETC;
5014 goto correct_result_in_carry;
5015 } else if (lit == 0) {
5016 // compare left < 0; set CARRY if SIGNBIT(left) is set
5017 if (performedLt) emitSETC; else emitCLRC;
5018 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5019 if (performedLt) emitCLRC; else emitSETC;
5020 goto correct_result_in_carry;
5023 } // right is literal
5025 /*************************************************
5026 * perform a general case comparison *
5027 * make sure we get CARRY==1 <==> left >= right *
5028 *************************************************/
5029 // compare most significant bytes
5030 //DEBUGpc ("comparing bytes at offset %d", size);
5032 // unsigned comparison
5033 mov2w_regOrLit (AOP(right), lit, size);
5034 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5036 // signed comparison
5037 // (add 2^n to both operands then perform an unsigned comparison)
5038 if (isAOP_LIT(right)) {
5039 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5040 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5042 if (litbyte == 0x80) {
5043 // left >= 0x80 -- always true, but more bytes to come
5044 pic16_mov2w (AOP(left), size);
5045 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5048 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5049 pic16_mov2w (AOP(left), size);
5050 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5051 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5054 /* using PRODL as a temporary register here */
5055 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5056 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5057 pic16_mov2w (AOP(left), size);
5058 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5059 pic16_emitpcode (POC_MOVWF, pctemp);
5060 pic16_mov2w (AOP(right), size);
5061 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5062 pic16_emitpcode (POC_SUBFW, pctemp);
5063 //pic16_popReleaseTempReg(pctemp, 1);
5067 // compare remaining bytes (treat as unsigned case from above)
5068 templbl = newiTempLabel ( NULL );
5071 //DEBUGpc ("comparing bytes at offset %d", offs);
5072 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5073 mov2w_regOrLit (AOP(right), lit, offs);
5074 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5076 pic16_emitpLabel (templbl->key);
5077 goto result_in_carry;
5081 /****************************************************
5082 * now CARRY contains the result of the comparison: *
5083 * SUBWF sets CARRY iff *
5084 * F-W >= 0 <==> F >= W <==> !(F < W) *
5085 * (F=left, W=right) *
5086 ****************************************************/
5089 if (result && AOP_TYPE(result) != AOP_CRY) {
5090 // value will be stored
5093 // value wil only be used in the following genSkipc()
5094 rIfx.condition ^= 1;
5098 correct_result_in_carry:
5100 // assign result to variable (if neccessary)
5101 if (result && AOP_TYPE(result) != AOP_CRY) {
5102 //DEBUGpc ("assign result");
5103 size = AOP_SIZE(result);
5105 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5107 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5110 // perform conditional jump
5112 //DEBUGpc ("generate control flow");
5121 static void genCmp (operand *left,operand *right,
5122 operand *result, iCode *ifx, int sign)
5124 int size; //, offset = 0 ;
5125 unsigned long lit = 0L,i = 0;
5126 resolvedIfx rFalseIfx;
5127 // resolvedIfx rTrueIfx;
5129 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5132 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5133 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5139 resolveIfx(&rFalseIfx,ifx);
5140 truelbl = newiTempLabel(NULL);
5141 size = max(AOP_SIZE(left),AOP_SIZE(right));
5143 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5147 /* if literal is on the right then swap with left */
5148 if ((AOP_TYPE(right) == AOP_LIT)) {
5149 operand *tmp = right ;
5150 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5151 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5154 lit = (lit - 1) & mask;
5157 rFalseIfx.condition ^= 1;
5160 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5161 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5165 //if(IC_TRUE(ifx) == NULL)
5166 /* if left & right are bit variables */
5167 if (AOP_TYPE(left) == AOP_CRY &&
5168 AOP_TYPE(right) == AOP_CRY ) {
5169 assert (0 && "bit variables used in genCmp");
5170 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5171 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5173 /* subtract right from left if at the
5174 end the carry flag is set then we know that
5175 left is greater than right */
5177 symbol *lbl = newiTempLabel(NULL);
5180 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5181 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5185 if(AOP_TYPE(right) == AOP_LIT) {
5187 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5189 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5196 genSkipCond(&rFalseIfx,left,size-1,7);
5198 /* no need to compare to 0...*/
5199 /* NOTE: this is a de-generate compare that most certainly
5200 * creates some dead code. */
5201 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5203 if(ifx) ifx->generated = 1;
5210 //i = (lit >> (size*8)) & 0xff;
5211 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5213 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5215 i = ((0-lit) & 0xff);
5218 /* lit is 0x7f, all signed chars are less than
5219 * this except for 0x7f itself */
5220 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5221 genSkipz2(&rFalseIfx,0);
5223 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5224 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5225 genSkipc(&rFalseIfx);
5230 genSkipz2(&rFalseIfx,1);
5232 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5233 genSkipc(&rFalseIfx);
5237 if(ifx) ifx->generated = 1;
5241 /* chars are out of the way. now do ints and longs */
5244 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5251 genSkipCond(&rFalseIfx,left,size,7);
5252 if(ifx) ifx->generated = 1;
5257 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5259 //rFalseIfx.condition ^= 1;
5260 //genSkipCond(&rFalseIfx,left,size,7);
5261 //rFalseIfx.condition ^= 1;
5263 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5264 if(rFalseIfx.condition)
5265 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5267 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5269 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5270 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5271 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5274 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5276 if(rFalseIfx.condition) {
5278 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5284 genSkipc(&rFalseIfx);
5285 pic16_emitpLabel(truelbl->key);
5286 if(ifx) ifx->generated = 1;
5293 if( (lit & 0xff) == 0) {
5294 /* lower byte is zero */
5295 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5296 i = ((lit >> 8) & 0xff) ^0x80;
5297 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5298 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5299 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5300 genSkipc(&rFalseIfx);
5303 if(ifx) ifx->generated = 1;
5308 /* Special cases for signed longs */
5309 if( (lit & 0xffffff) == 0) {
5310 /* lower byte is zero */
5311 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5312 i = ((lit >> 8*3) & 0xff) ^0x80;
5313 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5314 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5315 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5316 genSkipc(&rFalseIfx);
5319 if(ifx) ifx->generated = 1;
5327 if(lit & (0x80 << (size*8))) {
5328 /* lit is negative */
5329 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5331 //genSkipCond(&rFalseIfx,left,size,7);
5333 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5335 if(rFalseIfx.condition)
5336 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5338 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5342 /* lit is positive */
5343 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5344 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5345 if(rFalseIfx.condition)
5346 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5348 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5353 This works, but is only good for ints.
5354 It also requires a "known zero" register.
5355 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5356 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5357 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5358 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5359 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5360 genSkipc(&rFalseIfx);
5362 pic16_emitpLabel(truelbl->key);
5363 if(ifx) ifx->generated = 1;
5367 /* There are no more special cases, so perform a general compare */
5369 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5370 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5376 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5378 //rFalseIfx.condition ^= 1;
5379 genSkipc(&rFalseIfx);
5381 pic16_emitpLabel(truelbl->key);
5383 if(ifx) ifx->generated = 1;
5390 /* sign is out of the way. So now do an unsigned compare */
5391 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5394 /* General case - compare to an unsigned literal on the right.*/
5396 i = (lit >> (size*8)) & 0xff;
5397 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5398 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5400 i = (lit >> (size*8)) & 0xff;
5403 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5405 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5407 /* this byte of the lit is zero,
5408 *if it's not the last then OR in the variable */
5410 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5415 pic16_emitpLabel(lbl->key);
5416 // pic16_emitpLabel(truelbl->key);
5417 //if(emitFinalCheck)
5418 genSkipc(&rFalseIfx);
5420 pic16_emitpLabel(truelbl->key);
5422 if(ifx) ifx->generated = 1;
5429 if(AOP_TYPE(left) == AOP_LIT) {
5430 //symbol *lbl = newiTempLabel(NULL);
5432 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5435 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5438 if((lit == 0) && (sign == 0)){
5441 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5443 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5445 genSkipz2(&rFalseIfx,0);
5446 if(ifx) ifx->generated = 1;
5453 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5454 /* degenerate compare can never be true */
5455 if(rFalseIfx.condition == 0)
5456 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5458 if(ifx) ifx->generated = 1;
5463 /* signed comparisons to a literal byte */
5465 int lp1 = (lit+1) & 0xff;
5467 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5470 rFalseIfx.condition ^= 1;
5471 genSkipCond(&rFalseIfx,right,0,7);
5474 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5475 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5476 genSkipz2(&rFalseIfx,1);
5479 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5480 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5481 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5482 rFalseIfx.condition ^= 1;
5483 genSkipc(&rFalseIfx);
5487 /* unsigned comparisons to a literal byte */
5489 switch(lit & 0xff ) {
5491 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5492 genSkipz2(&rFalseIfx,0);
5495 rFalseIfx.condition ^= 1;
5496 genSkipCond(&rFalseIfx,right,0,7);
5500 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5501 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5502 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5503 rFalseIfx.condition ^= 1;
5504 if (AOP_TYPE(result) == AOP_CRY)
5505 genSkipc(&rFalseIfx);
5507 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5508 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5514 if(ifx) ifx->generated = 1;
5515 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5521 /* Size is greater than 1 */
5529 /* this means lit = 0xffffffff, or -1 */
5532 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5533 rFalseIfx.condition ^= 1;
5534 genSkipCond(&rFalseIfx,right,size,7);
5535 if(ifx) ifx->generated = 1;
5537 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5546 if(rFalseIfx.condition) {
5547 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5548 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5551 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5553 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5557 if(rFalseIfx.condition) {
5558 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5559 pic16_emitpLabel(truelbl->key);
5561 rFalseIfx.condition ^= 1;
5562 genSkipCond(&rFalseIfx,right,s,7);
5565 if(ifx) ifx->generated = 1;
5567 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5573 if((size == 1) && (0 == (lp1&0xff))) {
5574 /* lower byte of signed word is zero */
5575 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5576 i = ((lp1 >> 8) & 0xff) ^0x80;
5577 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5578 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5579 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5581 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5583 if(ifx) ifx->generated = 1;
5586 rFalseIfx.condition ^= 1;
5587 genSkipc(&rFalseIfx);
5588 if(ifx) ifx->generated = 1;
5594 if(lit & (0x80 << (size*8))) {
5595 /* Lit is less than zero */
5596 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5597 //rFalseIfx.condition ^= 1;
5598 //genSkipCond(&rFalseIfx,left,size,7);
5599 //rFalseIfx.condition ^= 1;
5600 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5601 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5603 if(rFalseIfx.condition)
5604 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5606 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5610 /* Lit is greater than or equal to zero */
5611 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5612 //rFalseIfx.condition ^= 1;
5613 //genSkipCond(&rFalseIfx,right,size,7);
5614 //rFalseIfx.condition ^= 1;
5616 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5617 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620 if(rFalseIfx.condition)
5621 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5623 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5627 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5628 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5632 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5634 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5636 rFalseIfx.condition ^= 1;
5637 //rFalseIfx.condition = 1;
5638 genSkipc(&rFalseIfx);
5640 pic16_emitpLabel(truelbl->key);
5642 if(ifx) ifx->generated = 1;
5645 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5652 /* compare word or long to an unsigned literal on the right.*/
5657 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5660 break; /* handled above */
5663 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5665 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5666 genSkipz2(&rFalseIfx,0);
5670 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5672 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5675 if(rFalseIfx.condition)
5676 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5678 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5681 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5682 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5684 rFalseIfx.condition ^= 1;
5685 genSkipc(&rFalseIfx);
5688 pic16_emitpLabel(truelbl->key);
5690 if(ifx) ifx->generated = 1;
5692 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5700 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5701 i = (lit >> (size*8)) & 0xff;
5703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5704 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5707 i = (lit >> (size*8)) & 0xff;
5710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5712 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5714 /* this byte of the lit is zero,
5715 * if it's not the last then OR in the variable */
5717 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5722 pic16_emitpLabel(lbl->key);
5724 rFalseIfx.condition ^= 1;
5726 genSkipc(&rFalseIfx);
5730 pic16_emitpLabel(truelbl->key);
5731 if(ifx) ifx->generated = 1;
5733 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5739 /* Compare two variables */
5741 DEBUGpic16_emitcode(";sign","%d",sign);
5745 /* Sigh. thus sucks... */
5749 pctemp = pic16_popGetTempReg(1);
5750 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5751 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5752 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5753 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5754 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5755 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5756 pic16_popReleaseTempReg(pctemp, 1);
5758 /* Signed char comparison */
5759 /* Special thanks to Nikolai Golovchenko for this snippet */
5760 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5761 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5762 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5763 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5764 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5765 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5768 genSkipc(&rFalseIfx);
5770 if(ifx) ifx->generated = 1;
5772 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5780 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5781 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5785 /* The rest of the bytes of a multi-byte compare */
5789 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5792 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5793 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5798 pic16_emitpLabel(lbl->key);
5800 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5801 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5802 (AOP_TYPE(result) == AOP_REG)) {
5803 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5804 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5806 genSkipc(&rFalseIfx);
5808 //genSkipc(&rFalseIfx);
5809 if(ifx) ifx->generated = 1;
5812 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5820 if ((AOP_TYPE(result) != AOP_CRY)
5821 && AOP_SIZE(result)) {
5822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5824 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5826 pic16_outBitC(result);
5828 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5829 /* if the result is used in the next
5830 ifx conditional branch then generate
5831 code a little differently */
5833 genIfxJump (ifx,"c");
5835 pic16_outBitC(result);
5836 /* leave the result in acc */
5841 #elif 0 /* VR version of genCmp() */ /* } else { */
5843 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5844 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5845 operand *result, int offset, int invert_op)
5849 /* check condition, > or < ?? */
5850 if(rIfx->condition != 0)invert_op ^= 1;
5852 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5854 if(!ifx)invert_op ^= 1;
5856 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5857 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5860 if(!invert_op)return POC_CPFSGT;
5861 else return POC_CPFSLT;
5864 static int compareAopfirstpass=1;
5866 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5867 operand *oper, int offset, operand *result,
5868 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5874 /* invert if there is a result to be loaded, in order to fit,
5875 * SETC/CLRC sequence */
5876 if(AOP_SIZE(result))invert_op ^= 1;
5878 // if(sign && !offset)invert_op ^= 1;
5880 // if(sign)invert_op ^= 1;
5882 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5884 if(AOP_SIZE(result) && compareAopfirstpass) {
5887 pic16_emitpcode(POC_SETF, pcop2);
5892 pic16_emitpcode(POC_CLRF, pcop2);
5898 compareAopfirstpass = 0;
5900 /* there is a bug when comparing operands with size > 1,
5901 * because higher bytes can be equal and test should be performed
5902 * to the next lower byte, current algorithm, considers operands
5903 * inequal in these cases! -- VR 20041107 */
5907 pic16_emitpcode(op, pcop);
5909 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5912 if((!sign || !offset) && AOP_SIZE(result)) {
5915 pic16_emitpcode(POC_CLRF, pcop2);
5920 pic16_emitpcode(POC_SETF, pcop2);
5925 /* don't emit final branch (offset == 0) */
5929 pic16_emitpcode(POC_RRCF, pcop2);
5931 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5934 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5935 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5936 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5938 truelbl = newiTempLabel( NULL );
5939 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5940 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5941 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5943 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5944 pic16_emitpLabel(truelbl->key);
5946 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5951 static void genCmp (operand *left, operand *right,
5952 operand *result, iCode *ifx, int sign)
5956 resolvedIfx rFalseIfx;
5957 symbol *falselbl, *tlbl;
5961 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5963 resolveIfx(&rFalseIfx, ifx);
5964 size = max(AOP_SIZE(left), AOP_SIZE(right));
5966 /* if left & right are bit variables */
5967 if(AOP_TYPE(left) == AOP_CRY
5968 && AOP_TYPE(right) == AOP_CRY ) {
5970 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5971 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5973 werror(W_POSSBUG2, __FILE__, __LINE__);
5977 /* if literal is on the right then swap with left */
5978 if((AOP_TYPE(right) == AOP_LIT)) {
5979 operand *tmp = right ;
5980 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5982 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5984 // lit = (lit - 1) & mask;
5987 rFalseIfx.condition ^= 1; /* reverse compare */
5989 if ((AOP_TYPE(left) == AOP_LIT)) {
5990 /* float compares are handled by support functions */
5991 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5994 /* actual comparing algorithm */
5995 // size = AOP_SIZE( right );
5997 falselbl = newiTempLabel( NULL );
5998 if(AOP_TYPE(left) == AOP_LIT) {
5999 /* compare to literal */
6000 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6003 pCodeOp *pct, *pct2;
6006 /* signed compare */
6007 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6009 /* using PRODL:PRODH as a temporary register here */
6010 pct = pic16_popCopyReg(&pic16_pc_prodl);
6011 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6012 tlbl = newiTempLabel( NULL );
6014 /* first compare signs:
6015 * a. if both are positive, compare just like unsigned
6016 * b. if both are negative, invert cmpop, compare just like unsigned
6017 * c. if different signs, determine the result directly */
6023 tlbl1 = newiTempLabel( NULL );
6024 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6028 /* literal is zero or positive:
6029 * a. if carry is zero, too, continue compare,
6030 * b. if carry is set, then continue depending on cmpop ^ condition:
6031 * 1. '<' return false (literal < variable),
6032 * 2. '>' return true (literal > variable) */
6033 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6034 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6037 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6038 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6042 /* literal is negative:
6043 * a. if carry is set, too, continue compare,
6044 * b. if carry is zero, then continue depending on cmpop ^ condition:
6045 * 1. '<' return true (literal < variable),
6046 * 2. '>' return false (literal > variable) */
6047 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6048 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6050 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6051 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6056 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6058 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6059 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6064 pic16_emitpLabel( tlbl1->key );
6067 compareAopfirstpass=1;
6068 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6069 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6070 // pic16_emitpcode(POC_MOVWF, pct);
6072 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6073 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6074 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6075 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6079 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6080 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6081 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6082 // pic16_emitpcode(POC_MOVWF, pct);
6084 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6085 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6086 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6087 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6088 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6091 if(ifx)ifx->generated = 1;
6093 if(AOP_SIZE(result)) {
6094 pic16_emitpLabel(tlbl->key);
6095 pic16_emitpLabel(falselbl->key);
6096 pic16_outBitOp( result, pct2 );
6098 pic16_emitpLabel(tlbl->key);
6102 /* unsigned compare */
6103 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6105 compareAopfirstpass=1;
6108 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6109 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6112 if(ifx)ifx->generated = 1;
6114 if(AOP_SIZE(result)) {
6115 pic16_emitpLabel(falselbl->key);
6116 pic16_outBitC( result );
6121 /* compare registers */
6122 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6126 pCodeOp *pct, *pct2;
6128 /* signed compare */
6129 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6131 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6132 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6133 tlbl = newiTempLabel( NULL );
6135 compareAopfirstpass=1;
6138 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6139 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6140 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6141 pic16_emitpcode(POC_MOVWF, pct);
6143 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6144 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6145 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6147 /* WREG already holds left + 0x80 */
6148 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6152 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6153 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6154 pic16_emitpcode(POC_MOVWF, pct);
6156 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6157 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6158 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6160 /* WREG already holds left + 0x80 */
6161 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6162 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6165 if(ifx)ifx->generated = 1;
6167 if(AOP_SIZE(result)) {
6168 pic16_emitpLabel(tlbl->key);
6169 pic16_emitpLabel(falselbl->key);
6170 pic16_outBitOp( result, pct2 );
6172 pic16_emitpLabel(tlbl->key);
6176 /* unsigned compare */
6177 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6179 compareAopfirstpass=1;
6182 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6183 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6187 if(ifx)ifx->generated = 1;
6188 if(AOP_SIZE(result)) {
6190 pic16_emitpLabel(falselbl->key);
6191 pic16_outBitC( result );
6202 /*-----------------------------------------------------------------*/
6203 /* genCmpGt :- greater than comparison */
6204 /*-----------------------------------------------------------------*/
6205 static void genCmpGt (iCode *ic, iCode *ifx)
6207 operand *left, *right, *result;
6208 sym_link *letype , *retype;
6214 right= IC_RIGHT(ic);
6215 result = IC_RESULT(ic);
6217 letype = getSpec(operandType(left));
6218 retype =getSpec(operandType(right));
6219 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6220 /* assign the amsops */
6221 pic16_aopOp (left,ic,FALSE);
6222 pic16_aopOp (right,ic,FALSE);
6223 pic16_aopOp (result,ic,TRUE);
6225 genCmp(right, left, result, ifx, sign);
6227 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6228 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6229 pic16_freeAsmop(result,NULL,ic,TRUE);
6232 /*-----------------------------------------------------------------*/
6233 /* genCmpLt - less than comparisons */
6234 /*-----------------------------------------------------------------*/
6235 static void genCmpLt (iCode *ic, iCode *ifx)
6237 operand *left, *right, *result;
6238 sym_link *letype , *retype;
6244 right= IC_RIGHT(ic);
6245 result = IC_RESULT(ic);
6247 letype = getSpec(operandType(left));
6248 retype =getSpec(operandType(right));
6249 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6251 /* assign the amsops */
6252 pic16_aopOp (left,ic,FALSE);
6253 pic16_aopOp (right,ic,FALSE);
6254 pic16_aopOp (result,ic,TRUE);
6256 genCmp(left, right, result, ifx, sign);
6258 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6259 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260 pic16_freeAsmop(result,NULL,ic,TRUE);
6265 // FIXME reenable literal optimisation when the pic16 port is stable
6267 /*-----------------------------------------------------------------*/
6268 /* genc16bit2lit - compare a 16 bit value to a literal */
6269 /*-----------------------------------------------------------------*/
6270 static void genc16bit2lit(operand *op, int lit, int offset)
6274 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6275 if( (lit&0xff) == 0)
6280 switch( BYTEofLONG(lit,i)) {
6282 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6285 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6288 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6291 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6292 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6297 switch( BYTEofLONG(lit,i)) {
6299 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6303 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6307 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6310 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6312 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6321 /*-----------------------------------------------------------------*/
6322 /* gencjneshort - compare and jump if not equal */
6323 /*-----------------------------------------------------------------*/
6324 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6326 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6328 int res_offset = 0; /* the result may be a different size then left or right */
6329 int res_size = AOP_SIZE(result);
6331 symbol *lbl, *lbl_done;
6333 unsigned long lit = 0L;
6334 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6336 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6337 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6339 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6340 resolveIfx(&rIfx,ifx);
6341 lbl = newiTempLabel(NULL);
6342 lbl_done = newiTempLabel(NULL);
6345 /* if the left side is a literal or
6346 if the right is in a pointer register and left
6348 if ((AOP_TYPE(left) == AOP_LIT) ||
6349 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6354 if(AOP_TYPE(right) == AOP_LIT)
6355 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6357 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6358 preserve_result = 1;
6360 if(result && !preserve_result)
6363 for(i = 0; i < AOP_SIZE(result); i++)
6364 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6368 /* if the right side is a literal then anything goes */
6369 if (AOP_TYPE(right) == AOP_LIT &&
6370 AOP_TYPE(left) != AOP_DIR ) {
6373 genc16bit2lit(left, lit, 0);
6375 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6381 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6382 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6384 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6388 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6390 if(res_offset < res_size-1)
6398 /* if the right side is in a register or in direct space or
6399 if the left is a pointer register & right is not */
6400 else if (AOP_TYPE(right) == AOP_REG ||
6401 AOP_TYPE(right) == AOP_DIR ||
6402 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6403 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6404 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6405 int lbl_key = lbl->key;
6408 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6409 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6411 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6412 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6413 __FUNCTION__,__LINE__);
6417 /* switch(size) { */
6419 /* genc16bit2lit(left, lit, 0); */
6421 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6426 if((AOP_TYPE(left) == AOP_DIR) &&
6427 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6429 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6430 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6432 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6434 switch (lit & 0xff) {
6436 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6439 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6440 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6441 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6445 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6446 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6447 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6448 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6452 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6458 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6461 if(AOP_TYPE(result) == AOP_CRY) {
6462 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6467 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6469 /* fix me. probably need to check result size too */
6470 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6475 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6476 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6483 if(res_offset < res_size-1)
6488 } else if(AOP_TYPE(right) == AOP_REG &&
6489 AOP_TYPE(left) != AOP_DIR){
6492 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6493 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6494 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6499 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6501 if(res_offset < res_size-1)
6506 /* right is a pointer reg need both a & b */
6508 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6510 pic16_emitcode("mov","b,%s",l);
6511 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6512 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6517 if(result && preserve_result)
6520 for(i = 0; i < AOP_SIZE(result); i++)
6521 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6524 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6526 if(result && preserve_result)
6527 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6530 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6532 pic16_emitpLabel(lbl->key);
6534 if(result && preserve_result)
6537 for(i = 0; i < AOP_SIZE(result); i++)
6538 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6540 pic16_emitpLabel(lbl_done->key);
6543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6551 /*-----------------------------------------------------------------*/
6552 /* gencjne - compare and jump if not equal */
6553 /*-----------------------------------------------------------------*/
6554 static void gencjne(operand *left, operand *right, iCode *ifx)
6556 symbol *tlbl = newiTempLabel(NULL);
6558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6559 gencjneshort(left, right, lbl);
6561 pic16_emitcode("mov","a,%s",one);
6562 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6563 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6564 pic16_emitcode("clr","a");
6565 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6567 pic16_emitpLabel(lbl->key);
6568 pic16_emitpLabel(tlbl->key);
6574 /*-----------------------------------------------------------------*/
6575 /* is_LitOp - check if operand has to be treated as literal */
6576 /*-----------------------------------------------------------------*/
6577 static bool is_LitOp(operand *op)
6579 return ((AOP_TYPE(op) == AOP_LIT)
6580 || ( (AOP_TYPE(op) == AOP_PCODE)
6581 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6582 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6585 /*-----------------------------------------------------------------*/
6586 /* is_LitAOp - check if operand has to be treated as literal */
6587 /*-----------------------------------------------------------------*/
6588 static bool is_LitAOp(asmop *aop)
6590 return ((aop->type == AOP_LIT)
6591 || ( (aop->type == AOP_PCODE)
6592 && ( (aop->aopu.pcop->type == PO_LITERAL)
6593 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6598 /*-----------------------------------------------------------------*/
6599 /* genCmpEq - generates code for equal to */
6600 /*-----------------------------------------------------------------*/
6601 static void genCmpEq (iCode *ic, iCode *ifx)
6603 operand *left, *right, *result;
6604 symbol *falselbl = newiTempLabel(NULL);
6605 symbol *donelbl = newiTempLabel(NULL);
6607 int preserve_result = 0;
6608 int generate_result = 0;
6610 unsigned long lit = -1;
6614 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6615 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6616 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6618 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6620 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6622 werror(W_POSSBUG2, __FILE__, __LINE__);
6623 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6624 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6628 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6630 operand *tmp = right ;
6635 if (AOP_TYPE(right) == AOP_LIT) {
6636 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6639 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6640 preserve_result = 1;
6642 if(result && AOP_SIZE(result))
6643 generate_result = 1;
6645 if(generate_result && !preserve_result)
6647 for(i = 0; i < AOP_SIZE(result); i++)
6648 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6651 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6652 for(i=0; i < AOP_SIZE(left); i++)
6654 if(AOP_TYPE(left) != AOP_ACC)
6657 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6659 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6661 if(is_LitOp(right)) {
6662 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6663 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6666 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6668 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6673 if(generate_result && preserve_result)
6675 for(i = 0; i < AOP_SIZE(result); i++)
6676 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6680 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6682 if(generate_result && preserve_result)
6683 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6685 if(ifx && IC_TRUE(ifx))
6686 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6688 if(ifx && IC_FALSE(ifx))
6689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6691 pic16_emitpLabel(falselbl->key);
6695 if(ifx && IC_FALSE(ifx))
6696 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6698 if(generate_result && preserve_result)
6700 for(i = 0; i < AOP_SIZE(result); i++)
6701 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6704 pic16_emitpLabel(donelbl->key);
6710 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6711 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6712 pic16_freeAsmop(result,NULL,ic,TRUE);
6718 // old version kept for reference
6720 /*-----------------------------------------------------------------*/
6721 /* genCmpEq - generates code for equal to */
6722 /*-----------------------------------------------------------------*/
6723 static void genCmpEq (iCode *ic, iCode *ifx)
6725 operand *left, *right, *result;
6726 unsigned long lit = 0L;
6728 symbol *falselbl = newiTempLabel(NULL);
6731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6734 DEBUGpic16_emitcode ("; ifx is non-null","");
6736 DEBUGpic16_emitcode ("; ifx is null","");
6738 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6739 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6740 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6742 size = max(AOP_SIZE(left),AOP_SIZE(right));
6744 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6746 /* if literal, literal on the right or
6747 if the right is in a pointer register and left
6749 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6750 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6751 operand *tmp = right ;
6757 if(ifx && !AOP_SIZE(result)){
6759 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6760 /* if they are both bit variables */
6761 if (AOP_TYPE(left) == AOP_CRY &&
6762 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6763 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6764 if(AOP_TYPE(right) == AOP_LIT){
6765 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6767 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6768 pic16_emitcode("cpl","c");
6769 } else if(lit == 1L) {
6770 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6772 pic16_emitcode("clr","c");
6774 /* AOP_TYPE(right) == AOP_CRY */
6776 symbol *lbl = newiTempLabel(NULL);
6777 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6778 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6779 pic16_emitcode("cpl","c");
6780 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6782 /* if true label then we jump if condition
6784 tlbl = newiTempLabel(NULL);
6785 if ( IC_TRUE(ifx) ) {
6786 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6787 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6789 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6790 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6792 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6795 /* left and right are both bit variables, result is carry */
6798 resolveIfx(&rIfx,ifx);
6800 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6801 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6802 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6803 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6808 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6810 /* They're not both bit variables. Is the right a literal? */
6811 if(AOP_TYPE(right) == AOP_LIT) {
6812 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6817 switch(lit & 0xff) {
6819 if ( IC_TRUE(ifx) ) {
6820 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6822 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6824 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6829 if ( IC_TRUE(ifx) ) {
6830 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6832 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6834 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6835 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6839 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6841 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6846 /* end of size == 1 */
6850 genc16bit2lit(left,lit,offset);
6853 /* end of size == 2 */
6858 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6859 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6860 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6861 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6864 /* search for patterns that can be optimized */
6866 genc16bit2lit(left,lit,0);
6870 emitSKPZ; // if hi word unequal
6872 emitSKPNZ; // if hi word equal
6874 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6875 genc16bit2lit(left,lit,2);
6878 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6879 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6883 pic16_emitpLabel(falselbl->key);
6892 } else if(AOP_TYPE(right) == AOP_CRY ) {
6893 /* we know the left is not a bit, but that the right is */
6894 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6895 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6896 pic16_popGet(AOP(right),offset));
6897 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6899 /* if the two are equal, then W will be 0 and the Z bit is set
6900 * we could test Z now, or go ahead and check the high order bytes if
6901 * the variable we're comparing is larger than a byte. */
6904 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6906 if ( IC_TRUE(ifx) ) {
6908 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6909 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6912 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6913 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6917 /* They're both variables that are larger than bits */
6920 tlbl = newiTempLabel(NULL);
6923 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6924 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6926 if ( IC_TRUE(ifx) ) {
6930 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6932 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6933 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6937 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6940 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6941 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6946 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6948 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6949 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6953 if(s>1 && IC_TRUE(ifx)) {
6954 pic16_emitpLabel(tlbl->key);
6955 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6959 /* mark the icode as generated */
6964 /* if they are both bit variables */
6965 if (AOP_TYPE(left) == AOP_CRY &&
6966 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6967 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6968 if(AOP_TYPE(right) == AOP_LIT){
6969 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6971 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6972 pic16_emitcode("cpl","c");
6973 } else if(lit == 1L) {
6974 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6976 pic16_emitcode("clr","c");
6978 /* AOP_TYPE(right) == AOP_CRY */
6980 symbol *lbl = newiTempLabel(NULL);
6981 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6982 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6983 pic16_emitcode("cpl","c");
6984 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6987 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6988 pic16_outBitC(result);
6992 genIfxJump (ifx,"c");
6995 /* if the result is used in an arithmetic operation
6996 then put the result in place */
6997 pic16_outBitC(result);
7000 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7001 gencjne(left,right,result,ifx);
7004 gencjne(left,right,newiTempLabel(NULL));
7006 if(IC_TRUE(ifx)->key)
7007 gencjne(left,right,IC_TRUE(ifx)->key);
7009 gencjne(left,right,IC_FALSE(ifx)->key);
7013 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7014 pic16_aopPut(AOP(result),"a",0);
7019 genIfxJump (ifx,"a");
7023 /* if the result is used in an arithmetic operation
7024 then put the result in place */
7026 if (AOP_TYPE(result) != AOP_CRY)
7027 pic16_outAcc(result);
7029 /* leave the result in acc */
7033 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7034 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7035 pic16_freeAsmop(result,NULL,ic,TRUE);
7039 /*-----------------------------------------------------------------*/
7040 /* ifxForOp - returns the icode containing the ifx for operand */
7041 /*-----------------------------------------------------------------*/
7042 static iCode *ifxForOp ( operand *op, iCode *ic )
7046 /* if true symbol then needs to be assigned */
7047 if (IS_TRUE_SYMOP(op))
7050 /* if this has register type condition and
7051 the next instruction is ifx with the same operand
7052 and live to of the operand is upto the ifx only then */
7054 && ic->next->op == IFX
7055 && IC_COND(ic->next)->key == op->key
7056 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7058 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7064 ic->next->op == IFX &&
7065 IC_COND(ic->next)->key == op->key) {
7066 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7071 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7073 ic->next->op == IFX)
7074 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7077 ic->next->op == IFX &&
7078 IC_COND(ic->next)->key == op->key) {
7079 DEBUGpic16_emitcode ("; "," key is okay");
7080 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7081 OP_SYMBOL(op)->liveTo,
7086 /* the code below is completely untested
7087 * it just allows ulong2fs.c compile -- VR */
7090 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7091 __FILE__, __FUNCTION__, __LINE__);
7093 /* if this has register type condition and
7094 the next instruction is ifx with the same operand
7095 and live to of the operand is upto the ifx only then */
7097 ic->next->op == IFX &&
7098 IC_COND(ic->next)->key == op->key &&
7099 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7103 ic->next->op == IFX &&
7104 IC_COND(ic->next)->key == op->key) {
7105 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7109 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7110 __FILE__, __FUNCTION__, __LINE__);
7112 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7117 /*-----------------------------------------------------------------*/
7118 /* genAndOp - for && operation */
7119 /*-----------------------------------------------------------------*/
7120 static void genAndOp (iCode *ic)
7122 operand *left,*right, *result;
7127 /* note here that && operations that are in an
7128 if statement are taken away by backPatchLabels
7129 only those used in arthmetic operations remain */
7130 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7131 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7132 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7134 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7136 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7137 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7138 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7140 /* if both are bit variables */
7141 /* if (AOP_TYPE(left) == AOP_CRY && */
7142 /* AOP_TYPE(right) == AOP_CRY ) { */
7143 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7144 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7145 /* pic16_outBitC(result); */
7147 /* tlbl = newiTempLabel(NULL); */
7148 /* pic16_toBoolean(left); */
7149 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7150 /* pic16_toBoolean(right); */
7151 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7152 /* pic16_outBitAcc(result); */
7155 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7156 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7157 pic16_freeAsmop(result,NULL,ic,TRUE);
7161 /*-----------------------------------------------------------------*/
7162 /* genOrOp - for || operation */
7163 /*-----------------------------------------------------------------*/
7166 modified this code, but it doesn't appear to ever get called
7169 static void genOrOp (iCode *ic)
7171 operand *left,*right, *result;
7176 /* note here that || operations that are in an
7177 if statement are taken away by backPatchLabels
7178 only those used in arthmetic operations remain */
7179 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7180 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7181 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7183 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7185 /* if both are bit variables */
7186 if (AOP_TYPE(left) == AOP_CRY &&
7187 AOP_TYPE(right) == AOP_CRY ) {
7188 pic16_emitcode("clrc","");
7189 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7190 AOP(left)->aopu.aop_dir,
7191 AOP(left)->aopu.aop_dir);
7192 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7193 AOP(right)->aopu.aop_dir,
7194 AOP(right)->aopu.aop_dir);
7195 pic16_emitcode("setc","");
7198 tlbl = newiTempLabel(NULL);
7199 pic16_toBoolean(left);
7201 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7202 pic16_toBoolean(right);
7203 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7205 pic16_outBitAcc(result);
7208 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7209 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7210 pic16_freeAsmop(result,NULL,ic,TRUE);
7213 /*-----------------------------------------------------------------*/
7214 /* isLiteralBit - test if lit == 2^n */
7215 /*-----------------------------------------------------------------*/
7216 static int isLiteralBit(unsigned long lit)
7218 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7219 0x100L,0x200L,0x400L,0x800L,
7220 0x1000L,0x2000L,0x4000L,0x8000L,
7221 0x10000L,0x20000L,0x40000L,0x80000L,
7222 0x100000L,0x200000L,0x400000L,0x800000L,
7223 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7224 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7228 for(idx = 0; idx < 32; idx++)
7234 /*-----------------------------------------------------------------*/
7235 /* continueIfTrue - */
7236 /*-----------------------------------------------------------------*/
7237 static void continueIfTrue (iCode *ic)
7241 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7245 /*-----------------------------------------------------------------*/
7247 /*-----------------------------------------------------------------*/
7248 static void jumpIfTrue (iCode *ic)
7252 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7256 /*-----------------------------------------------------------------*/
7257 /* jmpTrueOrFalse - */
7258 /*-----------------------------------------------------------------*/
7259 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7261 // ugly but optimized by peephole
7264 symbol *nlbl = newiTempLabel(NULL);
7265 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7266 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7267 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7268 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7270 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7271 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7276 /*-----------------------------------------------------------------*/
7277 /* genAnd - code for and */
7278 /*-----------------------------------------------------------------*/
7279 static void genAnd (iCode *ic, iCode *ifx)
7281 operand *left, *right, *result;
7283 unsigned long lit = 0L;
7289 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7290 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7291 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7293 resolveIfx(&rIfx,ifx);
7295 /* if left is a literal & right is not then exchange them */
7296 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7297 AOP_NEEDSACC(left)) {
7298 operand *tmp = right ;
7303 /* if result = right then exchange them */
7304 if(pic16_sameRegs(AOP(result),AOP(right))){
7305 operand *tmp = right ;
7310 /* if right is bit then exchange them */
7311 if (AOP_TYPE(right) == AOP_CRY &&
7312 AOP_TYPE(left) != AOP_CRY){
7313 operand *tmp = right ;
7317 if(AOP_TYPE(right) == AOP_LIT)
7318 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7320 size = AOP_SIZE(result);
7322 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7325 // result = bit & yy;
7326 if (AOP_TYPE(left) == AOP_CRY){
7327 // c = bit & literal;
7328 if(AOP_TYPE(right) == AOP_LIT){
7330 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7333 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7336 if(size && (AOP_TYPE(result) == AOP_CRY)){
7337 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7340 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7344 pic16_emitcode("clr","c");
7347 if (AOP_TYPE(right) == AOP_CRY){
7349 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7350 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7353 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7355 pic16_emitcode("rrc","a");
7356 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7362 pic16_outBitC(result);
7364 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7365 genIfxJump(ifx, "c");
7369 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7370 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7371 if((AOP_TYPE(right) == AOP_LIT) &&
7372 (AOP_TYPE(result) == AOP_CRY) &&
7373 (AOP_TYPE(left) != AOP_CRY)){
7374 int posbit = isLiteralBit(lit);
7378 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7381 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7387 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7388 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7390 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7391 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7394 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7395 size = AOP_SIZE(left);
7398 int bp = posbit, ofs=0;
7405 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7406 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7410 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7411 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7413 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7420 symbol *tlbl = newiTempLabel(NULL);
7421 int sizel = AOP_SIZE(left);
7427 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7429 /* patch provided by Aaron Colwell */
7430 if((posbit = isLiteralBit(bytelit)) != 0) {
7431 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7432 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7433 (posbit-1),0, PO_GPR_REGISTER));
7435 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7436 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7438 if (bytelit == 0xff) {
7439 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7440 * a peephole could optimize it out -- VR */
7441 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7443 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7444 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7447 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7448 pic16_popGetLabel(tlbl->key));
7452 /* old code, left here for reference -- VR 09/2004 */
7453 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7455 if((posbit = isLiteralBit(bytelit)) != 0)
7456 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7458 if(bytelit != 0x0FFL)
7459 pic16_emitcode("anl","a,%s",
7460 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7461 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7467 // bit = left & literal
7470 pic16_emitpLabel(tlbl->key);
7472 // if(left & literal)
7475 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7478 pic16_emitpLabel(tlbl->key);
7483 pic16_outBitC(result);
7487 /* if left is same as result */
7488 if(pic16_sameRegs(AOP(result),AOP(left))){
7490 for(;size--; offset++,lit>>=8) {
7491 if(AOP_TYPE(right) == AOP_LIT){
7492 switch(lit & 0xff) {
7494 /* and'ing with 0 has clears the result */
7495 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7496 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7499 /* and'ing with 0xff is a nop when the result and left are the same */
7504 int p = pic16_my_powof2( (~lit) & 0xff );
7506 /* only one bit is set in the literal, so use a bcf instruction */
7507 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7508 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7511 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7512 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7513 if(know_W != (lit&0xff))
7514 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7516 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7521 if (AOP_TYPE(left) == AOP_ACC) {
7522 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7524 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7525 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7532 // left & result in different registers
7533 if(AOP_TYPE(result) == AOP_CRY){
7535 // if(size), result in bit
7536 // if(!size && ifx), conditional oper: if(left & right)
7537 symbol *tlbl = newiTempLabel(NULL);
7538 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7540 pic16_emitcode("setb","c");
7542 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7543 pic16_emitcode("anl","a,%s",
7544 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7545 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7550 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7551 pic16_outBitC(result);
7553 jmpTrueOrFalse(ifx, tlbl);
7555 for(;(size--);offset++) {
7557 // result = left & right
7558 if(AOP_TYPE(right) == AOP_LIT){
7559 int t = (lit >> (offset*8)) & 0x0FFL;
7562 pic16_emitcode("clrf","%s",
7563 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7564 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7567 pic16_emitcode("movf","%s,w",
7568 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7569 pic16_emitcode("movwf","%s",
7570 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7571 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7572 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7575 pic16_emitcode("movlw","0x%x",t);
7576 pic16_emitcode("andwf","%s,w",
7577 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7578 pic16_emitcode("movwf","%s",
7579 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7581 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7582 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7583 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7588 if (AOP_TYPE(left) == AOP_ACC) {
7589 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7590 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7592 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7593 pic16_emitcode("andwf","%s,w",
7594 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7595 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7596 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7598 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7599 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7605 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7606 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7607 pic16_freeAsmop(result,NULL,ic,TRUE);
7610 /*-----------------------------------------------------------------*/
7611 /* genOr - code for or */
7612 /*-----------------------------------------------------------------*/
7613 static void genOr (iCode *ic, iCode *ifx)
7615 operand *left, *right, *result;
7617 unsigned long lit = 0L;
7619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7621 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7622 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7623 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7625 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7627 /* if left is a literal & right is not then exchange them */
7628 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7629 AOP_NEEDSACC(left)) {
7630 operand *tmp = right ;
7635 /* if result = right then exchange them */
7636 if(pic16_sameRegs(AOP(result),AOP(right))){
7637 operand *tmp = right ;
7642 /* if right is bit then exchange them */
7643 if (AOP_TYPE(right) == AOP_CRY &&
7644 AOP_TYPE(left) != AOP_CRY){
7645 operand *tmp = right ;
7650 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7652 if(AOP_TYPE(right) == AOP_LIT)
7653 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7655 size = AOP_SIZE(result);
7659 if (AOP_TYPE(left) == AOP_CRY){
7660 if(AOP_TYPE(right) == AOP_LIT){
7661 // c = bit & literal;
7663 // lit != 0 => result = 1
7664 if(AOP_TYPE(result) == AOP_CRY){
7666 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7667 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7668 // AOP(result)->aopu.aop_dir,
7669 // AOP(result)->aopu.aop_dir);
7671 continueIfTrue(ifx);
7675 // lit == 0 => result = left
7676 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7678 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7681 if (AOP_TYPE(right) == AOP_CRY){
7682 if(pic16_sameRegs(AOP(result),AOP(left))){
7684 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7685 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7686 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7688 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7689 AOP(result)->aopu.aop_dir,
7690 AOP(result)->aopu.aop_dir);
7691 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7692 AOP(right)->aopu.aop_dir,
7693 AOP(right)->aopu.aop_dir);
7694 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7695 AOP(result)->aopu.aop_dir,
7696 AOP(result)->aopu.aop_dir);
7698 if( AOP_TYPE(result) == AOP_ACC) {
7699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7700 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7701 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7706 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7707 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7708 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7709 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7711 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7712 AOP(result)->aopu.aop_dir,
7713 AOP(result)->aopu.aop_dir);
7714 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7715 AOP(right)->aopu.aop_dir,
7716 AOP(right)->aopu.aop_dir);
7717 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7718 AOP(left)->aopu.aop_dir,
7719 AOP(left)->aopu.aop_dir);
7720 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7721 AOP(result)->aopu.aop_dir,
7722 AOP(result)->aopu.aop_dir);
7727 symbol *tlbl = newiTempLabel(NULL);
7728 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7731 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7732 if( AOP_TYPE(right) == AOP_ACC) {
7733 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7735 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7736 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7741 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7742 pic16_emitcode(";XXX setb","c");
7743 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7744 AOP(left)->aopu.aop_dir,tlbl->key+100);
7745 pic16_toBoolean(right);
7746 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7747 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7748 jmpTrueOrFalse(ifx, tlbl);
7752 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7759 pic16_outBitC(result);
7761 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7762 genIfxJump(ifx, "c");
7766 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7767 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7768 if((AOP_TYPE(right) == AOP_LIT) &&
7769 (AOP_TYPE(result) == AOP_CRY) &&
7770 (AOP_TYPE(left) != AOP_CRY)){
7772 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7775 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7777 continueIfTrue(ifx);
7780 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7781 // lit = 0, result = boolean(left)
7783 pic16_emitcode(";XXX setb","c");
7784 pic16_toBoolean(right);
7786 symbol *tlbl = newiTempLabel(NULL);
7787 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7789 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7791 genIfxJump (ifx,"a");
7795 pic16_outBitC(result);
7799 /* if left is same as result */
7800 if(pic16_sameRegs(AOP(result),AOP(left))){
7802 for(;size--; offset++,lit>>=8) {
7803 if(AOP_TYPE(right) == AOP_LIT){
7804 if((lit & 0xff) == 0)
7805 /* or'ing with 0 has no effect */
7808 int p = pic16_my_powof2(lit & 0xff);
7810 /* only one bit is set in the literal, so use a bsf instruction */
7811 pic16_emitpcode(POC_BSF,
7812 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7814 if(know_W != (lit & 0xff))
7815 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7816 know_W = lit & 0xff;
7817 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7822 if (AOP_TYPE(left) == AOP_ACC) {
7823 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7824 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7826 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7827 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7829 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7830 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7836 // left & result in different registers
7837 if(AOP_TYPE(result) == AOP_CRY){
7839 // if(size), result in bit
7840 // if(!size && ifx), conditional oper: if(left | right)
7841 symbol *tlbl = newiTempLabel(NULL);
7842 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7843 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847 pic16_emitcode(";XXX setb","c");
7849 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7850 pic16_emitcode(";XXX orl","a,%s",
7851 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7852 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7857 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7858 pic16_outBitC(result);
7860 jmpTrueOrFalse(ifx, tlbl);
7861 } else for(;(size--);offset++){
7863 // result = left & right
7864 if(AOP_TYPE(right) == AOP_LIT){
7865 int t = (lit >> (offset*8)) & 0x0FFL;
7868 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7869 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7871 pic16_emitcode("movf","%s,w",
7872 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7873 pic16_emitcode("movwf","%s",
7874 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7877 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7878 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7879 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7881 pic16_emitcode("movlw","0x%x",t);
7882 pic16_emitcode("iorwf","%s,w",
7883 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7884 pic16_emitcode("movwf","%s",
7885 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7891 // faster than result <- left, anl result,right
7892 // and better if result is SFR
7893 if (AOP_TYPE(left) == AOP_ACC) {
7894 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7895 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7898 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7900 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7901 pic16_emitcode("iorwf","%s,w",
7902 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7905 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7910 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7911 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7912 pic16_freeAsmop(result,NULL,ic,TRUE);
7915 /*-----------------------------------------------------------------*/
7916 /* genXor - code for xclusive or */
7917 /*-----------------------------------------------------------------*/
7918 static void genXor (iCode *ic, iCode *ifx)
7920 operand *left, *right, *result;
7922 unsigned long lit = 0L;
7924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7926 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7927 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7928 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7930 /* if left is a literal & right is not ||
7931 if left needs acc & right does not */
7932 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7933 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7934 operand *tmp = right ;
7939 /* if result = right then exchange them */
7940 if(pic16_sameRegs(AOP(result),AOP(right))){
7941 operand *tmp = right ;
7946 /* if right is bit then exchange them */
7947 if (AOP_TYPE(right) == AOP_CRY &&
7948 AOP_TYPE(left) != AOP_CRY){
7949 operand *tmp = right ;
7953 if(AOP_TYPE(right) == AOP_LIT)
7954 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7956 size = AOP_SIZE(result);
7960 if (AOP_TYPE(left) == AOP_CRY){
7961 if(AOP_TYPE(right) == AOP_LIT){
7962 // c = bit & literal;
7964 // lit>>1 != 0 => result = 1
7965 if(AOP_TYPE(result) == AOP_CRY){
7967 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7968 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7970 continueIfTrue(ifx);
7973 pic16_emitcode("setb","c");
7977 // lit == 0, result = left
7978 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7980 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7982 // lit == 1, result = not(left)
7983 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7984 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7985 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7986 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7989 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7990 pic16_emitcode("cpl","c");
7997 symbol *tlbl = newiTempLabel(NULL);
7998 if (AOP_TYPE(right) == AOP_CRY){
8000 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8003 int sizer = AOP_SIZE(right);
8005 // if val>>1 != 0, result = 1
8006 pic16_emitcode("setb","c");
8008 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8010 // test the msb of the lsb
8011 pic16_emitcode("anl","a,#0xfe");
8012 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8016 pic16_emitcode("rrc","a");
8018 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8019 pic16_emitcode("cpl","c");
8020 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8025 pic16_outBitC(result);
8027 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8028 genIfxJump(ifx, "c");
8032 if(pic16_sameRegs(AOP(result),AOP(left))){
8033 /* if left is same as result */
8034 for(;size--; offset++) {
8035 if(AOP_TYPE(right) == AOP_LIT){
8036 int t = (lit >> (offset*8)) & 0x0FFL;
8040 if (IS_AOP_PREG(left)) {
8041 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8042 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8043 pic16_aopPut(AOP(result),"a",offset);
8045 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8046 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8047 pic16_emitcode("xrl","%s,%s",
8048 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8049 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8052 if (AOP_TYPE(left) == AOP_ACC)
8053 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8055 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8056 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8058 if (IS_AOP_PREG(left)) {
8059 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8060 pic16_aopPut(AOP(result),"a",offset);
8062 pic16_emitcode("xrl","%s,a",
8063 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8069 // left & result in different registers
8070 if(AOP_TYPE(result) == AOP_CRY){
8072 // if(size), result in bit
8073 // if(!size && ifx), conditional oper: if(left ^ right)
8074 symbol *tlbl = newiTempLabel(NULL);
8075 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8077 pic16_emitcode("setb","c");
8079 if((AOP_TYPE(right) == AOP_LIT) &&
8080 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8081 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8083 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8084 pic16_emitcode("xrl","a,%s",
8085 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8087 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8092 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8093 pic16_outBitC(result);
8095 jmpTrueOrFalse(ifx, tlbl);
8096 } else for(;(size--);offset++){
8098 // result = left & right
8099 if(AOP_TYPE(right) == AOP_LIT){
8100 int t = (lit >> (offset*8)) & 0x0FFL;
8103 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8104 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8105 pic16_emitcode("movf","%s,w",
8106 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8107 pic16_emitcode("movwf","%s",
8108 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8111 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8112 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8113 pic16_emitcode("comf","%s,w",
8114 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8115 pic16_emitcode("movwf","%s",
8116 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8119 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8120 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8121 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8122 pic16_emitcode("movlw","0x%x",t);
8123 pic16_emitcode("xorwf","%s,w",
8124 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8125 pic16_emitcode("movwf","%s",
8126 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8132 // faster than result <- left, anl result,right
8133 // and better if result is SFR
8134 if (AOP_TYPE(left) == AOP_ACC) {
8135 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8136 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8138 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8139 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8140 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8141 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8143 if ( AOP_TYPE(result) != AOP_ACC){
8144 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8145 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8151 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8152 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8153 pic16_freeAsmop(result,NULL,ic,TRUE);
8156 /*-----------------------------------------------------------------*/
8157 /* genInline - write the inline code out */
8158 /*-----------------------------------------------------------------*/
8159 static void genInline (iCode *ic)
8161 char *buffer, *bp, *bp1;
8163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8165 _G.inLine += (!options.asmpeep);
8167 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8168 strcpy(buffer,IC_INLINE(ic));
8170 while((bp1=strstr(bp, "\\n"))) {
8178 /* This is an experimental code for #pragma inline
8179 and is temporarily disabled for 2.5.0 release */
8187 cbuf = Safe_strdup(buffer);
8188 cblen = strlen(buffer)+1;
8189 memset(cbuf, 0, cblen);
8194 if(*bp != '%')*bp1++ = *bp++;
8200 if(i>elementsInSet(asmInlineMap))break;
8203 s = indexSet(asmInlineMap, i);
8204 DEBUGpc("searching symbol s = `%s'", s);
8205 sym = findSym(SymbolTab, NULL, s);
8208 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8210 strcat(bp1, sym->rname);
8216 if(strlen(bp1) > cblen - 16) {
8217 int i = strlen(cbuf);
8219 cbuf = realloc(cbuf, cblen);
8220 memset(cbuf+i, 0, 50);
8226 buffer = Safe_strdup( cbuf );
8233 /* emit each line as a code */
8239 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8247 /* print label, use this special format with NULL directive
8248 * to denote that the argument should not be indented with tab */
8249 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8252 /* advance to end of line (prevent splitting of comments at ':' */
8253 while (*bp && *bp != '\n') {
8261 if ((bp1 != bp) && *bp1)
8262 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8267 _G.inLine -= (!options.asmpeep);
8270 /*-----------------------------------------------------------------*/
8271 /* genRRC - rotate right with carry */
8272 /*-----------------------------------------------------------------*/
8273 static void genRRC (iCode *ic)
8275 operand *left , *result ;
8276 int size, offset = 0, same;
8278 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8280 /* rotate right with carry */
8282 result=IC_RESULT(ic);
8283 pic16_aopOp (left,ic,FALSE);
8284 pic16_aopOp (result,ic,TRUE);
8286 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8288 same = pic16_sameRegs(AOP(result),AOP(left));
8290 size = AOP_SIZE(result);
8292 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8294 /* get the lsb and put it into the carry */
8295 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8302 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8304 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8305 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8311 pic16_freeAsmop(left,NULL,ic,TRUE);
8312 pic16_freeAsmop(result,NULL,ic,TRUE);
8315 /*-----------------------------------------------------------------*/
8316 /* genRLC - generate code for rotate left with carry */
8317 /*-----------------------------------------------------------------*/
8318 static void genRLC (iCode *ic)
8320 operand *left , *result ;
8321 int size, offset = 0;
8324 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8325 /* rotate right with carry */
8327 result=IC_RESULT(ic);
8328 pic16_aopOp (left,ic,FALSE);
8329 pic16_aopOp (result,ic,TRUE);
8331 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8333 same = pic16_sameRegs(AOP(result),AOP(left));
8335 /* move it to the result */
8336 size = AOP_SIZE(result);
8338 /* get the msb and put it into the carry */
8339 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8346 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8348 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8349 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8356 pic16_freeAsmop(left,NULL,ic,TRUE);
8357 pic16_freeAsmop(result,NULL,ic,TRUE);
8361 /* gpasm can get the highest order bit with HIGH/UPPER
8362 * so the following probably is not needed -- VR */
8364 /*-----------------------------------------------------------------*/
8365 /* genGetHbit - generates code get highest order bit */
8366 /*-----------------------------------------------------------------*/
8367 static void genGetHbit (iCode *ic)
8369 operand *left, *result;
8371 result=IC_RESULT(ic);
8372 pic16_aopOp (left,ic,FALSE);
8373 pic16_aopOp (result,ic,FALSE);
8375 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8376 /* get the highest order byte into a */
8377 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8378 if(AOP_TYPE(result) == AOP_CRY){
8379 pic16_emitcode("rlc","a");
8380 pic16_outBitC(result);
8383 pic16_emitcode("rl","a");
8384 pic16_emitcode("anl","a,#0x01");
8385 pic16_outAcc(result);
8389 pic16_freeAsmop(left,NULL,ic,TRUE);
8390 pic16_freeAsmop(result,NULL,ic,TRUE);
8394 /*-----------------------------------------------------------------*/
8395 /* AccRol - rotate left accumulator by known count */
8396 /*-----------------------------------------------------------------*/
8397 static void AccRol (int shCount)
8399 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8400 shCount &= 0x0007; // shCount : 0..7
8405 pic16_emitcode("rl","a");
8408 pic16_emitcode("rl","a");
8409 pic16_emitcode("rl","a");
8412 pic16_emitcode("swap","a");
8413 pic16_emitcode("rr","a");
8416 pic16_emitcode("swap","a");
8419 pic16_emitcode("swap","a");
8420 pic16_emitcode("rl","a");
8423 pic16_emitcode("rr","a");
8424 pic16_emitcode("rr","a");
8427 pic16_emitcode("rr","a");
8433 /*-----------------------------------------------------------------*/
8434 /* AccLsh - left shift accumulator by known count */
8435 /*-----------------------------------------------------------------*/
8436 static void AccLsh (int shCount)
8438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8444 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8447 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8451 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8452 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8455 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8458 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8459 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8462 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8466 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8470 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8473 /*-----------------------------------------------------------------*/
8474 /* AccRsh - right shift accumulator by known count */
8475 /*-----------------------------------------------------------------*/
8476 static void AccRsh (int shCount, int andmask)
8478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8483 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8486 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8490 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8491 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8494 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8497 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8498 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8501 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8512 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8516 /*-----------------------------------------------------------------*/
8517 /* AccSRsh - signed right shift accumulator by known count */
8518 /*-----------------------------------------------------------------*/
8519 static void AccSRsh (int shCount)
8522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8525 pic16_emitcode("mov","c,acc.7");
8526 pic16_emitcode("rrc","a");
8527 } else if(shCount == 2){
8528 pic16_emitcode("mov","c,acc.7");
8529 pic16_emitcode("rrc","a");
8530 pic16_emitcode("mov","c,acc.7");
8531 pic16_emitcode("rrc","a");
8533 tlbl = newiTempLabel(NULL);
8534 /* rotate right accumulator */
8535 AccRol(8 - shCount);
8536 /* and kill the higher order bits */
8537 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8538 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8539 pic16_emitcode("orl","a,#0x%02x",
8540 (unsigned char)~SRMask[shCount]);
8541 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8547 /*-----------------------------------------------------------------*/
8548 /* shiftR1Left2Result - shift right one byte from left to result */
8549 /*-----------------------------------------------------------------*/
8550 static void shiftR1Left2ResultSigned (operand *left, int offl,
8551 operand *result, int offr,
8556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8558 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8562 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8564 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8566 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8573 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8575 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8577 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8578 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8580 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8581 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8587 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8589 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8590 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8593 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8594 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8595 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8597 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8598 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8600 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8604 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8605 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8606 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8607 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8612 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8614 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8615 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8617 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8618 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8620 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8626 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8627 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8628 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8629 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8630 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8631 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8633 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8634 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8635 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8636 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8637 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8643 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8644 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8645 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8646 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8648 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8649 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8650 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8658 /*-----------------------------------------------------------------*/
8659 /* shiftR1Left2Result - shift right one byte from left to result */
8660 /*-----------------------------------------------------------------*/
8661 static void shiftR1Left2Result (operand *left, int offl,
8662 operand *result, int offr,
8663 int shCount, int sign)
8667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8669 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8671 /* Copy the msb into the carry if signed. */
8673 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8683 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8685 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8694 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8710 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8711 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8712 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8716 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8717 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8718 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8722 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8723 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8724 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8726 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8731 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8732 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8733 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8734 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8735 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8740 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8741 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8742 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8751 /*-----------------------------------------------------------------*/
8752 /* shiftL1Left2Result - shift left one byte from left to result */
8753 /*-----------------------------------------------------------------*/
8754 static void shiftL1Left2Result (operand *left, int offl,
8755 operand *result, int offr, int shCount)
8760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8762 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8763 DEBUGpic16_emitcode ("; ***","same = %d",same);
8764 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8766 /* shift left accumulator */
8767 //AccLsh(shCount); // don't comment out just yet...
8768 // pic16_aopPut(AOP(result),"a",offr);
8772 /* Shift left 1 bit position */
8773 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8775 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8777 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8778 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8783 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8784 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8789 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8790 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8795 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8796 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8797 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8801 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8802 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8803 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8806 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8807 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8808 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8810 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8813 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8814 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8815 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8819 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8824 /*-----------------------------------------------------------------*/
8825 /* movLeft2Result - move byte from left to result */
8826 /*-----------------------------------------------------------------*/
8827 static void movLeft2Result (operand *left, int offl,
8828 operand *result, int offr)
8831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8832 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8833 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8835 if (*l == '@' && (IS_AOP_PREG(result))) {
8836 pic16_emitcode("mov","a,%s",l);
8837 pic16_aopPut(AOP(result),"a",offr);
8839 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8845 /*-----------------------------------------------------------------*/
8846 /* shiftL2Left2Result - shift left two bytes from left to result */
8847 /*-----------------------------------------------------------------*/
8848 static void shiftL2Left2Result (operand *left, int offl,
8849 operand *result, int offr, int shCount)
8851 int same = pic16_sameRegs(AOP(result), AOP(left));
8854 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8856 if (same && (offl != offr)) { // shift bytes
8859 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8860 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8862 } else { // just treat as different later on
8875 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8877 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8881 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8888 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8889 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8890 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8891 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8893 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8894 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8896 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8901 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8902 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8903 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8904 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8905 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8906 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8907 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8909 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8910 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8913 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8914 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8915 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8916 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8917 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8927 /* note, use a mov/add for the shift since the mov has a
8928 chance of getting optimized out */
8929 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8931 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8932 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8937 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8944 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8945 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8946 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8950 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8961 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8962 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8967 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8968 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8969 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8976 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8977 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8984 /*-----------------------------------------------------------------*/
8985 /* shiftR2Left2Result - shift right two bytes from left to result */
8986 /*-----------------------------------------------------------------*/
8987 static void shiftR2Left2Result (operand *left, int offl,
8988 operand *result, int offr,
8989 int shCount, int sign)
8991 int same = pic16_sameRegs(AOP(result), AOP(left));
8993 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8995 if (same && (offl != offr)) { // shift right bytes
8998 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8999 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9001 } else { // just treat as different later on
9013 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9018 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9019 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9022 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9024 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9029 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9033 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9041 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9045 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9046 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9047 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9049 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9050 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9051 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9053 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9055 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9056 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9057 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9061 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9062 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9067 pic16_emitpcode(POC_BTFSC,
9068 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9069 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9077 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9078 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9082 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9083 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9085 pic16_emitpcode(POC_BTFSC,
9086 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9087 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9089 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9090 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9091 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9092 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9095 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9096 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9097 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9099 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9100 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9101 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9103 pic16_emitpcode(POC_BTFSC,
9104 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9105 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9107 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9108 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9115 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9116 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9117 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9121 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9123 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9128 /*-----------------------------------------------------------------*/
9129 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9130 /*-----------------------------------------------------------------*/
9131 static void shiftLLeftOrResult (operand *left, int offl,
9132 operand *result, int offr, int shCount)
9134 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9136 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9137 /* shift left accumulator */
9139 /* or with result */
9140 /* back to result */
9141 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9144 /*-----------------------------------------------------------------*/
9145 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9146 /*-----------------------------------------------------------------*/
9147 static void shiftRLeftOrResult (operand *left, int offl,
9148 operand *result, int offr, int shCount)
9150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9152 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9153 /* shift right accumulator */
9155 /* or with result */
9156 /* back to result */
9157 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9160 /*-----------------------------------------------------------------*/
9161 /* genlshOne - left shift a one byte quantity by known count */
9162 /*-----------------------------------------------------------------*/
9163 static void genlshOne (operand *result, operand *left, int shCount)
9165 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9166 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9169 /*-----------------------------------------------------------------*/
9170 /* genlshTwo - left shift two bytes by known amount != 0 */
9171 /*-----------------------------------------------------------------*/
9172 static void genlshTwo (operand *result,operand *left, int shCount)
9176 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9177 size = pic16_getDataSize(result);
9179 /* if shCount >= 8 */
9185 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9187 movLeft2Result(left, LSB, result, MSB16);
9189 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9192 /* 1 <= shCount <= 7 */
9195 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9197 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9201 /*-----------------------------------------------------------------*/
9202 /* shiftLLong - shift left one long from left to result */
9203 /* offr = LSB or MSB16 */
9204 /*-----------------------------------------------------------------*/
9205 static void shiftLLong (operand *left, operand *result, int offr )
9207 int size = AOP_SIZE(result);
9208 int same = pic16_sameRegs(AOP(left),AOP(result));
9211 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9213 if (same && (offr == MSB16)) { //shift one byte
9214 for(i=size-1;i>=MSB16;i--) {
9215 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9216 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9219 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9222 if (size > LSB+offr ){
9224 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9226 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9227 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9231 if(size > MSB16+offr){
9233 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9235 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9236 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9240 if(size > MSB24+offr){
9242 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9244 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9245 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9249 if(size > MSB32+offr){
9251 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9253 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9254 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9258 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9262 /*-----------------------------------------------------------------*/
9263 /* genlshFour - shift four byte by a known amount != 0 */
9264 /*-----------------------------------------------------------------*/
9265 static void genlshFour (operand *result, operand *left, int shCount)
9269 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9270 size = AOP_SIZE(result);
9272 /* if shifting more that 3 bytes */
9273 if (shCount >= 24 ) {
9276 /* lowest order of left goes to the highest
9277 order of the destination */
9278 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9280 movLeft2Result(left, LSB, result, MSB32);
9282 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9283 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9284 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9289 /* more than two bytes */
9290 else if ( shCount >= 16 ) {
9291 /* lower order two bytes goes to higher order two bytes */
9293 /* if some more remaining */
9295 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9297 movLeft2Result(left, MSB16, result, MSB32);
9298 movLeft2Result(left, LSB, result, MSB24);
9300 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9301 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9305 /* if more than 1 byte */
9306 else if ( shCount >= 8 ) {
9307 /* lower order three bytes goes to higher order three bytes */
9311 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9313 movLeft2Result(left, LSB, result, MSB16);
9315 else{ /* size = 4 */
9317 movLeft2Result(left, MSB24, result, MSB32);
9318 movLeft2Result(left, MSB16, result, MSB24);
9319 movLeft2Result(left, LSB, result, MSB16);
9320 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9322 else if(shCount == 1)
9323 shiftLLong(left, result, MSB16);
9325 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9326 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9327 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9328 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9333 /* 1 <= shCount <= 7 */
9334 else if(shCount <= 3)
9336 shiftLLong(left, result, LSB);
9337 while(--shCount >= 1)
9338 shiftLLong(result, result, LSB);
9340 /* 3 <= shCount <= 7, optimize */
9342 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9343 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9344 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9348 /*-----------------------------------------------------------------*/
9349 /* genLeftShiftLiteral - left shifting by known count */
9350 /*-----------------------------------------------------------------*/
9351 void pic16_genLeftShiftLiteral (operand *left,
9356 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9360 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9361 pic16_freeAsmop(right,NULL,ic,TRUE);
9363 pic16_aopOp(left,ic,FALSE);
9364 pic16_aopOp(result,ic,TRUE);
9366 size = getSize(operandType(result));
9369 pic16_emitcode("; shift left ","result %d, left %d",size,
9373 /* I suppose that the left size >= result size */
9376 movLeft2Result(left, size, result, size);
9380 else if(shCount >= (size * 8))
9382 pic16_aopPut(AOP(result),zero,size);
9386 genlshOne (result,left,shCount);
9391 genlshTwo (result,left,shCount);
9395 genlshFour (result,left,shCount);
9399 pic16_freeAsmop(left,NULL,ic,TRUE);
9400 pic16_freeAsmop(result,NULL,ic,TRUE);
9403 /*-----------------------------------------------------------------*
9404 * genMultiAsm - repeat assembly instruction for size of register.
9405 * if endian == 1, then the high byte (i.e base address + size of
9406 * register) is used first else the low byte is used first;
9407 *-----------------------------------------------------------------*/
9408 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9413 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9426 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9432 #if !(USE_GENERIC_SIGNED_SHIFT)
9433 /*-----------------------------------------------------------------*/
9434 /* genLeftShift - generates code for left shifting */
9435 /*-----------------------------------------------------------------*/
9436 static void genLeftShift (iCode *ic)
9438 operand *left,*right, *result;
9441 symbol *tlbl , *tlbl1;
9444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9446 right = IC_RIGHT(ic);
9448 result = IC_RESULT(ic);
9450 pic16_aopOp(right,ic,FALSE);
9452 /* if the shift count is known then do it
9453 as efficiently as possible */
9454 if (AOP_TYPE(right) == AOP_LIT) {
9455 pic16_genLeftShiftLiteral (left,right,result,ic);
9459 /* shift count is unknown then we have to form
9460 * a loop. Get the loop count in WREG : Note: we take
9461 * only the lower order byte since shifting
9462 * more than 32 bits make no sense anyway, ( the
9463 * largest size of an object can be only 32 bits ) */
9465 pic16_aopOp(left,ic,FALSE);
9466 pic16_aopOp(result,ic,FALSE);
9468 /* now move the left to the result if they are not the
9469 * same, and if size > 1,
9470 * and if right is not same to result (!!!) -- VR */
9471 if (!pic16_sameRegs(AOP(left),AOP(result))
9472 && (AOP_SIZE(result) > 1)) {
9474 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9476 size = AOP_SIZE(result);
9481 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9482 if (*l == '@' && (IS_AOP_PREG(result))) {
9484 pic16_emitcode("mov","a,%s",l);
9485 pic16_aopPut(AOP(result),"a",offset);
9489 /* we don't know if left is a literal or a register, take care -- VR */
9490 pic16_mov2f(AOP(result), AOP(left), offset);
9496 size = AOP_SIZE(result);
9498 /* if it is only one byte then */
9500 if(optimized_for_speed) {
9501 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9502 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9503 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9504 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9505 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9506 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9507 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9508 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9509 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9510 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9511 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9512 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9515 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9517 tlbl = newiTempLabel(NULL);
9520 /* this is already done, why change it? */
9521 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9522 pic16_mov2f(AOP(result), AOP(left), 0);
9526 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9527 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9528 pic16_emitpLabel(tlbl->key);
9529 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9530 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9532 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9537 if (pic16_sameRegs(AOP(left),AOP(result))) {
9539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9541 tlbl = newiTempLabel(NULL);
9542 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9543 genMultiAsm(POC_RRCF, result, size,1);
9544 pic16_emitpLabel(tlbl->key);
9545 genMultiAsm(POC_RLCF, result, size,0);
9546 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9548 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9552 //tlbl = newiTempLabel(NULL);
9554 //tlbl1 = newiTempLabel(NULL);
9556 //reAdjustPreg(AOP(result));
9558 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9559 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9560 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9562 //pic16_emitcode("add","a,acc");
9563 //pic16_aopPut(AOP(result),"a",offset++);
9565 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9567 // pic16_emitcode("rlc","a");
9568 // pic16_aopPut(AOP(result),"a",offset++);
9570 //reAdjustPreg(AOP(result));
9572 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9573 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9576 tlbl = newiTempLabel(NULL);
9577 tlbl1= newiTempLabel(NULL);
9579 size = AOP_SIZE(result);
9582 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9586 /* offset should be 0, 1 or 3 */
9588 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9590 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9592 pic16_emitpcode(POC_MOVWF, pctemp);
9595 pic16_emitpLabel(tlbl->key);
9598 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9600 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9602 pic16_emitpcode(POC_DECFSZ, pctemp);
9603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9604 pic16_emitpLabel(tlbl1->key);
9606 pic16_popReleaseTempReg(pctemp,1);
9610 pic16_freeAsmop (right,NULL,ic,TRUE);
9611 pic16_freeAsmop(left,NULL,ic,TRUE);
9612 pic16_freeAsmop(result,NULL,ic,TRUE);
9618 #error old code (left here for reference)
9619 /*-----------------------------------------------------------------*/
9620 /* genLeftShift - generates code for left shifting */
9621 /*-----------------------------------------------------------------*/
9622 static void genLeftShift (iCode *ic)
9624 operand *left,*right, *result;
9627 symbol *tlbl , *tlbl1;
9630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9632 right = IC_RIGHT(ic);
9634 result = IC_RESULT(ic);
9636 pic16_aopOp(right,ic,FALSE);
9638 /* if the shift count is known then do it
9639 as efficiently as possible */
9640 if (AOP_TYPE(right) == AOP_LIT) {
9641 pic16_genLeftShiftLiteral (left,right,result,ic);
9645 /* shift count is unknown then we have to form
9646 a loop get the loop count in B : Note: we take
9647 only the lower order byte since shifting
9648 more that 32 bits make no sense anyway, ( the
9649 largest size of an object can be only 32 bits ) */
9652 pic16_aopOp(left,ic,FALSE);
9653 pic16_aopOp(result,ic,FALSE);
9655 /* now move the left to the result if they are not the
9657 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9658 AOP_SIZE(result) > 1) {
9660 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9662 size = AOP_SIZE(result);
9665 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9666 if (*l == '@' && (IS_AOP_PREG(result))) {
9668 pic16_emitcode("mov","a,%s",l);
9669 pic16_aopPut(AOP(result),"a",offset);
9672 /* we don't know if left is a literal or a register, take care -- VR */
9673 pic16_mov2f(AOP(result), AOP(left), offset);
9679 size = AOP_SIZE(result);
9681 /* if it is only one byte then */
9683 if(optimized_for_speed) {
9684 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9685 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9686 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9687 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9689 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9690 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9691 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9693 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9694 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9695 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9700 tlbl = newiTempLabel(NULL);
9701 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9702 pic16_mov2f(AOP(result), AOP(left), 0);
9704 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9705 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9708 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9709 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9710 pic16_emitpLabel(tlbl->key);
9711 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9712 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9714 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9719 if (pic16_sameRegs(AOP(left),AOP(result))) {
9721 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9723 tlbl = newiTempLabel(NULL);
9724 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9725 genMultiAsm(POC_RRCF, result, size,1);
9726 pic16_emitpLabel(tlbl->key);
9727 genMultiAsm(POC_RLCF, result, size,0);
9728 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9730 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9734 //tlbl = newiTempLabel(NULL);
9736 //tlbl1 = newiTempLabel(NULL);
9738 //reAdjustPreg(AOP(result));
9740 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9741 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9742 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9744 //pic16_emitcode("add","a,acc");
9745 //pic16_aopPut(AOP(result),"a",offset++);
9747 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9749 // pic16_emitcode("rlc","a");
9750 // pic16_aopPut(AOP(result),"a",offset++);
9752 //reAdjustPreg(AOP(result));
9754 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9755 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9758 tlbl = newiTempLabel(NULL);
9759 tlbl1= newiTempLabel(NULL);
9761 size = AOP_SIZE(result);
9764 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9766 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9768 /* offset should be 0, 1 or 3 */
9770 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9772 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9774 pic16_emitpcode(POC_MOVWF, pctemp);
9777 pic16_emitpLabel(tlbl->key);
9780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9782 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9784 pic16_emitpcode(POC_DECFSZ, pctemp);
9785 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9786 pic16_emitpLabel(tlbl1->key);
9788 pic16_popReleaseTempReg(pctemp,1);
9792 pic16_freeAsmop (right,NULL,ic,TRUE);
9793 pic16_freeAsmop(left,NULL,ic,TRUE);
9794 pic16_freeAsmop(result,NULL,ic,TRUE);
9798 /*-----------------------------------------------------------------*/
9799 /* genrshOne - right shift a one byte quantity by known count */
9800 /*-----------------------------------------------------------------*/
9801 static void genrshOne (operand *result, operand *left,
9802 int shCount, int sign)
9804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9805 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9808 /*-----------------------------------------------------------------*/
9809 /* genrshTwo - right shift two bytes by known amount != 0 */
9810 /*-----------------------------------------------------------------*/
9811 static void genrshTwo (operand *result,operand *left,
9812 int shCount, int sign)
9814 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9815 /* if shCount >= 8 */
9819 shiftR1Left2Result(left, MSB16, result, LSB,
9822 movLeft2Result(left, MSB16, result, LSB);
9824 pic16_addSign (result, 1, sign);
9827 /* 1 <= shCount <= 7 */
9829 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9832 /*-----------------------------------------------------------------*/
9833 /* shiftRLong - shift right one long from left to result */
9834 /* offl = LSB or MSB16 */
9835 /*-----------------------------------------------------------------*/
9836 static void shiftRLong (operand *left, int offl,
9837 operand *result, int sign)
9839 int size = AOP_SIZE(result);
9840 int same = pic16_sameRegs(AOP(left),AOP(result));
9842 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9844 if (same && (offl == MSB16)) { //shift one byte right
9845 for(i=MSB16;i<size;i++) {
9846 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9847 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9852 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9858 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9860 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9861 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9865 /* add sign of "a" */
9866 pic16_addSign(result, MSB32, sign);
9870 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9872 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9873 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9877 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9879 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9880 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9884 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9887 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9888 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9893 /*-----------------------------------------------------------------*/
9894 /* genrshFour - shift four byte by a known amount != 0 */
9895 /*-----------------------------------------------------------------*/
9896 static void genrshFour (operand *result, operand *left,
9897 int shCount, int sign)
9899 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9900 /* if shifting more that 3 bytes */
9901 if(shCount >= 24 ) {
9904 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9906 movLeft2Result(left, MSB32, result, LSB);
9908 pic16_addSign(result, MSB16, sign);
9910 else if(shCount >= 16){
9913 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9915 movLeft2Result(left, MSB24, result, LSB);
9916 movLeft2Result(left, MSB32, result, MSB16);
9918 pic16_addSign(result, MSB24, sign);
9920 else if(shCount >= 8){
9923 shiftRLong(left, MSB16, result, sign);
9924 else if(shCount == 0){
9925 movLeft2Result(left, MSB16, result, LSB);
9926 movLeft2Result(left, MSB24, result, MSB16);
9927 movLeft2Result(left, MSB32, result, MSB24);
9928 pic16_addSign(result, MSB32, sign);
9930 else{ //shcount >= 2
9931 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9932 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9933 /* the last shift is signed */
9934 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9935 pic16_addSign(result, MSB32, sign);
9938 else{ /* 1 <= shCount <= 7 */
9940 shiftRLong(left, LSB, result, sign);
9942 shiftRLong(result, LSB, result, sign);
9945 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9946 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9947 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9952 /*-----------------------------------------------------------------*/
9953 /* genRightShiftLiteral - right shifting by known count */
9954 /*-----------------------------------------------------------------*/
9955 static void genRightShiftLiteral (operand *left,
9961 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9964 pic16_freeAsmop(right,NULL,ic,TRUE);
9966 pic16_aopOp(left,ic,FALSE);
9967 pic16_aopOp(result,ic,TRUE);
9969 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9972 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9976 lsize = pic16_getDataSize(left);
9977 res_size = pic16_getDataSize(result);
9978 /* test the LEFT size !!! */
9980 /* I suppose that the left size >= result size */
9982 assert (res_size <= lsize);
9983 while (res_size--) {
9984 pic16_mov2f (AOP(result), AOP(left), res_size);
9988 else if(shCount >= (lsize * 8)){
9991 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9993 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9994 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9999 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10000 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10001 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10008 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10013 switch (res_size) {
10015 genrshOne (result,left,shCount,sign);
10019 genrshTwo (result,left,shCount,sign);
10023 genrshFour (result,left,shCount,sign);
10031 pic16_freeAsmop(left,NULL,ic,TRUE);
10032 pic16_freeAsmop(result,NULL,ic,TRUE);
10035 #if !(USE_GENERIC_SIGNED_SHIFT)
10036 /*-----------------------------------------------------------------*/
10037 /* genSignedRightShift - right shift of signed number */
10038 /*-----------------------------------------------------------------*/
10039 static void genSignedRightShift (iCode *ic)
10041 operand *right, *left, *result;
10044 symbol *tlbl, *tlbl1 ;
10047 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10049 /* we do it the hard way put the shift count in b
10050 and loop thru preserving the sign */
10051 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10053 right = IC_RIGHT(ic);
10054 left = IC_LEFT(ic);
10055 result = IC_RESULT(ic);
10057 pic16_aopOp(right,ic,FALSE);
10058 pic16_aopOp(left,ic,FALSE);
10059 pic16_aopOp(result,ic,FALSE);
10062 if ( AOP_TYPE(right) == AOP_LIT) {
10063 genRightShiftLiteral (left,right,result,ic,1);
10066 /* shift count is unknown then we have to form
10067 a loop get the loop count in B : Note: we take
10068 only the lower order byte since shifting
10069 more that 32 bits make no sense anyway, ( the
10070 largest size of an object can be only 32 bits ) */
10072 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10073 //pic16_emitcode("inc","b");
10074 //pic16_freeAsmop (right,NULL,ic,TRUE);
10075 //pic16_aopOp(left,ic,FALSE);
10076 //pic16_aopOp(result,ic,FALSE);
10078 /* now move the left to the result if they are not the
10080 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10081 AOP_SIZE(result) > 1) {
10083 size = AOP_SIZE(result);
10087 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10088 if (*l == '@' && IS_AOP_PREG(result)) {
10090 pic16_emitcode("mov","a,%s",l);
10091 pic16_aopPut(AOP(result),"a",offset);
10093 pic16_aopPut(AOP(result),l,offset);
10095 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10096 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10102 /* mov the highest order bit to OVR */
10103 tlbl = newiTempLabel(NULL);
10104 tlbl1= newiTempLabel(NULL);
10106 size = AOP_SIZE(result);
10109 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10111 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10113 /* offset should be 0, 1 or 3 */
10114 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10116 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10118 pic16_emitpcode(POC_MOVWF, pctemp);
10121 pic16_emitpLabel(tlbl->key);
10123 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10124 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10127 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10130 pic16_emitpcode(POC_DECFSZ, pctemp);
10131 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10132 pic16_emitpLabel(tlbl1->key);
10134 pic16_popReleaseTempReg(pctemp,1);
10136 size = AOP_SIZE(result);
10138 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10139 pic16_emitcode("rlc","a");
10140 pic16_emitcode("mov","ov,c");
10141 /* if it is only one byte then */
10143 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10145 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10146 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10147 pic16_emitcode("mov","c,ov");
10148 pic16_emitcode("rrc","a");
10149 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10150 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10151 pic16_aopPut(AOP(result),"a",0);
10155 reAdjustPreg(AOP(result));
10156 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10157 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10158 pic16_emitcode("mov","c,ov");
10160 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10162 pic16_emitcode("rrc","a");
10163 pic16_aopPut(AOP(result),"a",offset--);
10165 reAdjustPreg(AOP(result));
10166 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10167 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10172 pic16_freeAsmop(left,NULL,ic,TRUE);
10173 pic16_freeAsmop(result,NULL,ic,TRUE);
10174 pic16_freeAsmop(right,NULL,ic,TRUE);
10178 #if !(USE_GENERIC_SIGNED_SHIFT)
10179 #warning This implementation of genRightShift() is incomplete!
10180 /*-----------------------------------------------------------------*/
10181 /* genRightShift - generate code for right shifting */
10182 /*-----------------------------------------------------------------*/
10183 static void genRightShift (iCode *ic)
10185 operand *right, *left, *result;
10189 symbol *tlbl, *tlbl1 ;
10191 /* if signed then we do it the hard way preserve the
10192 sign bit moving it inwards */
10193 letype = getSpec(operandType(IC_LEFT(ic)));
10194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10196 if (!SPEC_USIGN(letype)) {
10197 genSignedRightShift (ic);
10201 /* signed & unsigned types are treated the same : i.e. the
10202 signed is NOT propagated inwards : quoting from the
10203 ANSI - standard : "for E1 >> E2, is equivalent to division
10204 by 2**E2 if unsigned or if it has a non-negative value,
10205 otherwise the result is implementation defined ", MY definition
10206 is that the sign does not get propagated */
10208 right = IC_RIGHT(ic);
10209 left = IC_LEFT(ic);
10210 result = IC_RESULT(ic);
10212 pic16_aopOp(right,ic,FALSE);
10214 /* if the shift count is known then do it
10215 as efficiently as possible */
10216 if (AOP_TYPE(right) == AOP_LIT) {
10217 genRightShiftLiteral (left,right,result,ic, 0);
10221 /* shift count is unknown then we have to form
10222 a loop get the loop count in B : Note: we take
10223 only the lower order byte since shifting
10224 more that 32 bits make no sense anyway, ( the
10225 largest size of an object can be only 32 bits ) */
10227 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10228 pic16_emitcode("inc","b");
10229 pic16_aopOp(left,ic,FALSE);
10230 pic16_aopOp(result,ic,FALSE);
10232 /* now move the left to the result if they are not the
10234 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10235 AOP_SIZE(result) > 1) {
10237 size = AOP_SIZE(result);
10240 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10241 if (*l == '@' && IS_AOP_PREG(result)) {
10243 pic16_emitcode("mov","a,%s",l);
10244 pic16_aopPut(AOP(result),"a",offset);
10246 pic16_aopPut(AOP(result),l,offset);
10251 tlbl = newiTempLabel(NULL);
10252 tlbl1= newiTempLabel(NULL);
10253 size = AOP_SIZE(result);
10256 /* if it is only one byte then */
10259 tlbl = newiTempLabel(NULL);
10260 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10261 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10262 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10265 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10266 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10267 pic16_emitpLabel(tlbl->key);
10268 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10269 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10271 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10276 reAdjustPreg(AOP(result));
10277 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10278 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10281 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10283 pic16_emitcode("rrc","a");
10284 pic16_aopPut(AOP(result),"a",offset--);
10286 reAdjustPreg(AOP(result));
10288 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10289 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10292 pic16_freeAsmop(left,NULL,ic,TRUE);
10293 pic16_freeAsmop (right,NULL,ic,TRUE);
10294 pic16_freeAsmop(result,NULL,ic,TRUE);
10298 #if (USE_GENERIC_SIGNED_SHIFT)
10299 /*-----------------------------------------------------------------*/
10300 /* genGenericShift - generates code for left or right shifting */
10301 /*-----------------------------------------------------------------*/
10302 static void genGenericShift (iCode *ic, int isShiftLeft) {
10303 operand *left,*right, *result;
10305 int sign, signedCount;
10306 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10307 PIC_OPCODE pos_shift, neg_shift;
10311 right = IC_RIGHT(ic);
10312 left = IC_LEFT(ic);
10313 result = IC_RESULT(ic);
10315 pic16_aopOp(right,ic,FALSE);
10316 pic16_aopOp(left,ic,FALSE);
10317 pic16_aopOp(result,ic,TRUE);
10319 sign = !SPEC_USIGN(operandType (left));
10320 signedCount = !SPEC_USIGN(operandType (right));
10322 /* if the shift count is known then do it
10323 as efficiently as possible */
10324 if (AOP_TYPE(right) == AOP_LIT) {
10325 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10326 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10327 // we should modify right->aopu.aop_lit here!
10328 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10329 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10331 pic16_genLeftShiftLiteral (left,right,result,ic);
10333 genRightShiftLiteral (left,right,result,ic, sign);
10336 } // if (right is literal)
10338 /* shift count is unknown then we have to form a loop.
10339 * Note: we take only the lower order byte since shifting
10340 * more than 32 bits make no sense anyway, ( the
10341 * largest size of an object can be only 32 bits )
10342 * Note: we perform arithmetic shifts if the left operand is
10343 * signed and we do an (effective) right shift, i. e. we
10344 * shift in the sign bit from the left. */
10346 label_complete = newiTempLabel ( NULL );
10347 label_loop_pos = newiTempLabel ( NULL );
10348 label_loop_neg = NULL;
10349 label_negative = NULL;
10350 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10351 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10354 // additional labels needed
10355 label_loop_neg = newiTempLabel ( NULL );
10356 label_negative = newiTempLabel ( NULL );
10359 // copy source to result -- this will effectively truncate the left operand to the size of result!
10360 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10361 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10362 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10363 pic16_mov2f (AOP(result),AOP(left), offset);
10366 // if result is longer than left, fill with zeros (or sign)
10367 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10368 if (sign && AOP_SIZE(left) > 0) {
10369 // shift signed operand -- fill with sign
10370 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10371 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10372 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10373 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10374 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10377 // shift unsigned operand -- fill result with zeros
10378 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10379 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10382 } // if (size mismatch)
10384 pic16_mov2w (AOP(right), 0);
10385 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10386 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10389 // perform a shift by one (shift count is positive)
10390 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10391 // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3] ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10392 pic16_emitpLabel (label_loop_pos->key);
10394 if (sign && (pos_shift == POC_RRCF)) {
10395 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10398 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10399 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10400 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10402 // perform a shift by one (shift count is positive)
10403 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10404 // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6] ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10405 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10406 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10408 pic16_emitpLabel (label_loop_pos->key);
10409 if (sign && (pos_shift == POC_RRCF)) {
10410 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10413 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10414 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10415 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10416 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10420 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10422 pic16_emitpLabel (label_negative->key);
10423 // perform a shift by -1 (shift count is negative)
10424 // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4 ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10426 pic16_emitpLabel (label_loop_neg->key);
10427 if (sign && (neg_shift == POC_RRCF)) {
10428 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10431 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10432 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10433 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10434 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10435 } // if (signedCount)
10437 pic16_emitpLabel (label_complete->key);
10440 pic16_freeAsmop (right,NULL,ic,TRUE);
10441 pic16_freeAsmop(left,NULL,ic,TRUE);
10442 pic16_freeAsmop(result,NULL,ic,TRUE);
10445 static void genLeftShift (iCode *ic) {
10446 genGenericShift (ic, 1);
10449 static void genRightShift (iCode *ic) {
10450 genGenericShift (ic, 0);
10455 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10456 void pic16_loadFSR0(operand *op, int lit)
10458 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10459 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10461 assert (!OP_SYMBOL(op)->remat);
10462 // set up FSR0 with address of result
10463 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10464 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10468 /*----------------------------------------------------------------*/
10469 /* pic16_derefPtr - move one byte from the location ptr points to */
10470 /* to WREG (doWrite == 0) or one byte from WREG */
10471 /* to the location ptr points to (doWrite != 0) */
10472 /*----------------------------------------------------------------*/
10473 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10475 if (!IS_PTR(operandType(ptr)))
10477 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10478 else pic16_mov2w (AOP(ptr), 0);
10482 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10483 /* We might determine pointer type right here: */
10484 p_type = DCL_TYPE(operandType(ptr));
10489 if (!fsr0_setup || !*fsr0_setup)
10491 pic16_loadFSR0( ptr, 0 );
10492 if (fsr0_setup) *fsr0_setup = 1;
10495 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10497 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10501 if (AOP(ptr)->aopu.aop_reg[2]) {
10502 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10503 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10504 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10505 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10506 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10507 pic16_callGenericPointerRW(doWrite, 1);
10509 // data pointer (just 2 byte given)
10510 if (!fsr0_setup || !*fsr0_setup)
10512 pic16_loadFSR0( ptr, 0 );
10513 if (fsr0_setup) *fsr0_setup = 1;
10516 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10518 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10523 assert (0 && "invalid pointer type specified");
10528 /*-----------------------------------------------------------------*/
10529 /* genUnpackBits - generates code for unpacking bits */
10530 /*-----------------------------------------------------------------*/
10531 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10534 sym_link *etype, *letype;
10535 int blen=0, bstr=0;
10540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10541 etype = getSpec(operandType(result));
10542 letype = getSpec(operandType(left));
10544 // if(IS_BITFIELD(etype)) {
10545 blen = SPEC_BLEN(etype);
10546 bstr = SPEC_BSTR(etype);
10549 lbstr = SPEC_BSTR( letype );
10551 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10552 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10555 if((blen == 1) && (bstr < 8)
10556 && (!IS_PTR(operandType(left)) || PIC_IS_DATA_PTR(operandType(left)))) {
10557 /* it is a single bit, so use the appropriate bit instructions */
10558 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10560 same = pic16_sameRegs(AOP(left),AOP(result));
10561 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10562 pic16_emitpcode(POC_CLRF, op);
10564 if(!IS_PTR(operandType(left))) {
10565 /* workaround to reduce the extra lfsr instruction */
10566 pic16_emitpcode(POC_BTFSC,
10567 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10569 assert (PIC_IS_DATA_PTR (operandType(left)));
10570 pic16_loadFSR0 (left, 0);
10571 pic16_emitpcode(POC_BTFSC,
10572 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10575 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10576 /* unsigned bitfields result in either 0 or 1 */
10577 pic16_emitpcode(POC_INCF, op);
10579 /* signed bitfields result in either 0 or -1 */
10580 pic16_emitpcode(POC_DECF, op);
10583 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10586 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10592 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10593 // access symbol directly
10594 pic16_mov2w (AOP(left), 0);
10596 pic16_derefPtr (left, ptype, 0, NULL);
10599 /* if we have bitdisplacement then it fits */
10600 /* into this byte completely or if length is */
10601 /* less than a byte */
10602 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10604 /* shift right acc */
10607 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10608 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10610 /* VR -- normally I would use the following, but since we use the hack,
10611 * to avoid the masking from AccRsh, why not mask it right now? */
10614 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10617 /* extend signed bitfields to 8 bits */
10618 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10620 assert (blen + bstr > 0);
10621 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10622 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10625 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10627 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10631 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10632 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10639 static void genDataPointerGet(operand *left,
10643 int size, offset = 0, leoffset=0 ;
10645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10646 pic16_aopOp(result, ic, TRUE);
10650 size = AOP_SIZE(result);
10651 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10655 /* The following tests may save a redudant movff instruction when
10656 * accessing unions */
10658 /* if they are the same */
10659 if (operandsEqu (left, result)) {
10660 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10666 /* if they are the same registers */
10667 if (pic16_sameRegs(AOP(left),AOP(result))) {
10668 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10674 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10675 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10676 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10683 if ( AOP_TYPE(left) == AOP_PCODE) {
10684 fprintf(stderr,"genDataPointerGet %s, %d\n",
10685 AOP(left)->aopu.pcop->name,
10686 (AOP(left)->aopu.pcop->type == PO_DIR)?
10687 PCOR(AOP(left)->aopu.pcop)->instance:
10688 PCOI(AOP(left)->aopu.pcop)->offset);
10692 if(AOP(left)->aopu.pcop->type == PO_DIR)
10693 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10695 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10698 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10700 // pic16_DumpOp("(result)",result);
10701 if(is_LitAOp(AOP(result))) {
10702 pic16_mov2w(AOP(left), offset); // patch 8
10703 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10705 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10706 pic16_popGet(AOP(left), offset), //patch 8
10707 pic16_popGet(AOP(result), offset)));
10715 pic16_freeAsmop(result,NULL,ic,TRUE);
10720 /*-----------------------------------------------------------------*/
10721 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10722 /*-----------------------------------------------------------------*/
10723 static void genNearPointerGet (operand *left,
10727 // asmop *aop = NULL;
10728 //regs *preg = NULL ;
10729 sym_link *rtype, *retype;
10730 sym_link *ltype, *letype;
10734 rtype = operandType(result);
10735 retype= getSpec(rtype);
10736 ltype = operandType(left);
10737 letype= getSpec(ltype);
10739 pic16_aopOp(left,ic,FALSE);
10741 // pic16_DumpOp("(left)",left);
10742 // pic16_DumpOp("(result)",result);
10744 /* if left is rematerialisable and
10745 * result is not bit variable type and
10746 * the left is pointer to data space i.e
10747 * lower 128 bytes of space */
10749 if (AOP_TYPE(left) == AOP_PCODE
10750 && !IS_BITFIELD(retype)
10751 && DCL_TYPE(ltype) == POINTER) {
10753 genDataPointerGet (left,result,ic);
10754 pic16_freeAsmop(left, NULL, ic, TRUE);
10758 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10759 pic16_aopOp (result,ic,TRUE);
10761 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10764 if(IS_BITFIELD( retype )
10765 && (SPEC_BLEN(operandType(result))==1)
10769 int bitstrt, bytestrt;
10771 /* if this is bitfield of size 1, see if we are checking the value
10772 * of a single bit in an if-statement,
10773 * if yes, then don't generate usual code, but execute the
10774 * genIfx directly -- VR */
10778 /* CHECK: if next iCode is IFX
10779 * and current result operand is nextic's conditional operand
10780 * and current result operand live ranges ends at nextic's key number
10782 if((nextic->op == IFX)
10783 && (result == IC_COND(nextic))
10784 && (OP_LIVETO(result) == nextic->seq)
10785 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10787 /* everything is ok then */
10788 /* find a way to optimize the genIfx iCode */
10790 bytestrt = SPEC_BSTR(operandType(result))/8;
10791 bitstrt = SPEC_BSTR(operandType(result))%8;
10793 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10795 genIfxpCOpJump(nextic, jop);
10797 pic16_freeAsmop(left, NULL, ic, TRUE);
10798 pic16_freeAsmop(result, NULL, ic, TRUE);
10804 /* if bitfield then unpack the bits */
10805 if (IS_BITFIELD(letype))
10806 genUnpackBits (result, left, NULL, POINTER);
10808 /* we have can just get the values */
10809 int size = AOP_SIZE(result);
10812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10814 pic16_loadFSR0( left, 0 );
10818 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10819 pic16_popGet(AOP(result), offset++)));
10821 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10822 pic16_popGet(AOP(result), offset++)));
10828 /* now some housekeeping stuff */
10830 /* we had to allocate for this iCode */
10831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10832 pic16_freeAsmop(NULL,aop,ic,TRUE);
10834 /* we did not allocate which means left
10835 * already in a pointer register, then
10836 * if size > 0 && this could be used again
10837 * we have to point it back to where it
10839 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10840 if (AOP_SIZE(result) > 1
10841 && !OP_SYMBOL(left)->remat
10842 && ( OP_SYMBOL(left)->liveTo > ic->seq
10844 // int size = AOP_SIZE(result) - 1;
10846 // pic16_emitcode("dec","%s",rname);
10852 pic16_freeAsmop(left,NULL,ic,TRUE);
10853 pic16_freeAsmop(result,NULL,ic,TRUE);
10856 /*-----------------------------------------------------------------*/
10857 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10858 /*-----------------------------------------------------------------*/
10859 static void genPagedPointerGet (operand *left,
10864 regs *preg = NULL ;
10866 sym_link *rtype, *retype;
10868 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10870 rtype = operandType(result);
10871 retype= getSpec(rtype);
10873 pic16_aopOp(left,ic,FALSE);
10875 /* if the value is already in a pointer register
10876 then don't need anything more */
10877 if (!AOP_INPREG(AOP(left))) {
10878 /* otherwise get a free pointer register */
10880 preg = getFreePtr(ic,&aop,FALSE);
10881 pic16_emitcode("mov","%s,%s",
10883 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10884 rname = preg->name ;
10886 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10888 pic16_freeAsmop(left,NULL,ic,TRUE);
10889 pic16_aopOp (result,ic,TRUE);
10891 /* if bitfield then unpack the bits */
10892 if (IS_BITFIELD(retype))
10893 genUnpackBits (result,left,rname,PPOINTER);
10895 /* we have can just get the values */
10896 int size = AOP_SIZE(result);
10901 pic16_emitcode("movx","a,@%s",rname);
10902 pic16_aopPut(AOP(result),"a",offset);
10907 pic16_emitcode("inc","%s",rname);
10911 /* now some housekeeping stuff */
10913 /* we had to allocate for this iCode */
10914 pic16_freeAsmop(NULL,aop,ic,TRUE);
10916 /* we did not allocate which means left
10917 already in a pointer register, then
10918 if size > 0 && this could be used again
10919 we have to point it back to where it
10921 if (AOP_SIZE(result) > 1 &&
10922 !OP_SYMBOL(left)->remat &&
10923 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10925 int size = AOP_SIZE(result) - 1;
10927 pic16_emitcode("dec","%s",rname);
10932 pic16_freeAsmop(result,NULL,ic,TRUE);
10938 /* This code is not adjusted to PIC16 and fails utterly.
10939 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10941 /*-----------------------------------------------------------------*/
10942 /* genFarPointerGet - gget value from far space */
10943 /*-----------------------------------------------------------------*/
10944 static void genFarPointerGet (operand *left,
10945 operand *result, iCode *ic)
10948 sym_link *retype = getSpec(operandType(result));
10950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10952 pic16_aopOp(left,ic,FALSE);
10954 /* if the operand is already in dptr
10955 then we do nothing else we move the value to dptr */
10956 if (AOP_TYPE(left) != AOP_STR) {
10957 /* if this is remateriazable */
10958 if (AOP_TYPE(left) == AOP_IMMD)
10959 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10960 else { /* we need to get it byte by byte */
10961 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10962 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10963 if (options.model == MODEL_FLAT24)
10965 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10969 /* so dptr know contains the address */
10970 pic16_freeAsmop(left,NULL,ic,TRUE);
10971 pic16_aopOp(result,ic,TRUE);
10973 /* if bit then unpack */
10974 if (IS_BITFIELD(retype))
10975 genUnpackBits(result,left,"dptr",FPOINTER);
10977 size = AOP_SIZE(result);
10981 pic16_emitcode("movx","a,@dptr");
10982 pic16_aopPut(AOP(result),"a",offset++);
10984 pic16_emitcode("inc","dptr");
10988 pic16_freeAsmop(result,NULL,ic,TRUE);
10993 /*-----------------------------------------------------------------*/
10994 /* genCodePointerGet - get value from code space */
10995 /*-----------------------------------------------------------------*/
10996 static void genCodePointerGet (operand *left,
10997 operand *result, iCode *ic)
11000 sym_link *retype = getSpec(operandType(result));
11002 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11004 pic16_aopOp(left,ic,FALSE);
11006 /* if the operand is already in dptr
11007 then we do nothing else we move the value to dptr */
11008 if (AOP_TYPE(left) != AOP_STR) {
11009 /* if this is remateriazable */
11010 if (AOP_TYPE(left) == AOP_IMMD)
11011 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11012 else { /* we need to get it byte by byte */
11013 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11014 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11015 if (options.model == MODEL_FLAT24)
11017 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11021 /* so dptr know contains the address */
11022 pic16_freeAsmop(left,NULL,ic,TRUE);
11023 pic16_aopOp(result,ic,FALSE);
11025 /* if bit then unpack */
11026 if (IS_BITFIELD(retype))
11027 genUnpackBits(result,left,"dptr",CPOINTER);
11029 size = AOP_SIZE(result);
11033 pic16_emitcode("clr","a");
11034 pic16_emitcode("movc","a,@a+dptr");
11035 pic16_aopPut(AOP(result),"a",offset++);
11037 pic16_emitcode("inc","dptr");
11041 pic16_freeAsmop(result,NULL,ic,TRUE);
11046 /*-----------------------------------------------------------------*/
11047 /* genGenPointerGet - gget value from generic pointer space */
11048 /*-----------------------------------------------------------------*/
11049 static void genGenPointerGet (operand *left,
11050 operand *result, iCode *ic)
11052 int size, offset, lit;
11053 sym_link *retype = getSpec(operandType(result));
11055 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11056 pic16_aopOp(left,ic,FALSE);
11057 pic16_aopOp(result,ic,FALSE);
11058 size = AOP_SIZE(result);
11060 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11062 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11064 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11065 // load FSR0 from immediate
11066 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11068 // pic16_loadFSR0( left );
11073 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11075 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11082 else { /* we need to get it byte by byte */
11083 // set up FSR0 with address from left
11084 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11085 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11091 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11093 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11100 /* if bit then unpack */
11101 if (IS_BITFIELD(retype))
11102 genUnpackBits(result,left,"BAD",GPOINTER);
11105 pic16_freeAsmop(left,NULL,ic,TRUE);
11106 pic16_freeAsmop(result,NULL,ic,TRUE);
11112 /*-----------------------------------------------------------------*/
11113 /* genGenPointerGet - gget value from generic pointer space */
11114 /*-----------------------------------------------------------------*/
11115 static void genGenPointerGet (operand *left,
11116 operand *result, iCode *ic)
11118 int size, offset, lit;
11119 sym_link *letype = getSpec(operandType(left));
11121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11122 pic16_aopOp(left,ic,FALSE);
11123 pic16_aopOp(result,ic,TRUE);
11124 size = AOP_SIZE(result);
11126 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11128 /* if bit then unpack */
11129 if (IS_BITFIELD(letype)) {
11130 genUnpackBits(result,left,"BAD",GPOINTER);
11134 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11136 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11137 // load FSR0 from immediate
11138 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11140 werror(W_POSSBUG2, __FILE__, __LINE__);
11145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11147 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11154 } else { /* we need to get it byte by byte */
11156 /* set up WREG:PRODL:FSR0L with address from left */
11157 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11158 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11161 pic16_callGenericPointerRW(0, size);
11163 assignResultValue(result, 1);
11169 pic16_freeAsmop(left,NULL,ic,TRUE);
11170 pic16_freeAsmop(result,NULL,ic,TRUE);
11173 /*-----------------------------------------------------------------*/
11174 /* genConstPointerGet - get value from const generic pointer space */
11175 /*-----------------------------------------------------------------*/
11176 static void genConstPointerGet (operand *left,
11177 operand *result, iCode *ic)
11179 //sym_link *retype = getSpec(operandType(result));
11180 // symbol *albl = newiTempLabel(NULL); // patch 15
11181 // symbol *blbl = newiTempLabel(NULL); //
11182 // PIC_OPCODE poc; // patch 15
11186 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11187 pic16_aopOp(left,ic,FALSE);
11188 pic16_aopOp(result,ic,TRUE);
11189 size = AOP_SIZE(result);
11191 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11193 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11195 // set up table pointer
11196 if( (AOP_TYPE(left) == AOP_PCODE)
11197 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11198 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11200 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11201 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11202 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11203 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11204 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11205 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11207 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11208 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11209 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11213 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11214 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11218 pic16_freeAsmop(left,NULL,ic,TRUE);
11219 pic16_freeAsmop(result,NULL,ic,TRUE);
11223 /*-----------------------------------------------------------------*/
11224 /* genPointerGet - generate code for pointer get */
11225 /*-----------------------------------------------------------------*/
11226 static void genPointerGet (iCode *ic)
11228 operand *left, *result ;
11229 sym_link *type, *etype;
11234 left = IC_LEFT(ic);
11235 result = IC_RESULT(ic) ;
11237 /* depending on the type of pointer we need to
11238 move it to the correct pointer register */
11239 type = operandType(left);
11240 etype = getSpec(type);
11243 if (IS_PTR_CONST(type))
11245 if (IS_CODEPTR(type))
11247 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11249 /* if left is of type of pointer then it is simple */
11250 if (IS_PTR(type) && !IS_FUNC(type->next))
11251 p_type = DCL_TYPE(type);
11253 /* we have to go by the storage class */
11254 p_type = PTR_TYPE(SPEC_OCLS(etype));
11256 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11258 if (SPEC_OCLS(etype)->codesp ) {
11259 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11260 //p_type = CPOINTER ;
11262 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11263 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11264 /*p_type = FPOINTER ;*/
11266 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11267 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11268 /* p_type = PPOINTER; */
11270 if (SPEC_OCLS(etype) == idata ) {
11271 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11272 /* p_type = IPOINTER; */
11274 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11275 /* p_type = POINTER ; */
11279 /* now that we have the pointer type we assign
11280 the pointer values */
11285 genNearPointerGet (left,result,ic);
11289 genPagedPointerGet(left,result,ic);
11293 /* PICs do not support FAR pointers... */
11294 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11296 genFarPointerGet (left,result,ic);
11301 genConstPointerGet (left,result,ic);
11302 //pic16_emitcodePointerGet (left,result,ic);
11307 if (IS_PTR_CONST(type))
11308 genConstPointerGet (left,result,ic);
11311 genGenPointerGet (left,result,ic);
11315 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11316 "genPointerGet: illegal pointer type");
11321 /*-----------------------------------------------------------------*/
11322 /* genPackBits - generates code for packed bit storage */
11323 /*-----------------------------------------------------------------*/
11324 static void genPackBits (sym_link *etype , operand *result,
11326 char *rname, int p_type)
11334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11335 blen = SPEC_BLEN(etype);
11336 bstr = SPEC_BSTR(etype);
11338 retype = getSpec(operandType(right));
11340 if(AOP_TYPE(right) == AOP_LIT) {
11341 if((blen == 1) && (bstr < 8)) {
11343 /* it is a single bit, so use the appropriate bit instructions */
11345 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11347 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11348 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11349 if(!IS_PTR(operandType(result))) {
11350 /* workaround to reduce the extra lfsr instruction */
11352 pic16_emitpcode(POC_BSF,
11353 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11355 pic16_emitpcode(POC_BCF,
11356 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11359 if (PIC_IS_DATA_PTR(operandType(result))) {
11360 pic16_loadFSR0(result, 0);
11361 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11362 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11364 /* get old value */
11365 pic16_derefPtr (result, p_type, 0, NULL);
11366 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11367 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11368 /* write back new value */
11369 pic16_derefPtr (result, p_type, 1, NULL);
11375 /* move literal to W */
11376 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11379 if(IS_BITFIELD(retype)
11380 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11384 rblen = SPEC_BLEN( retype );
11385 rbstr = SPEC_BSTR( retype );
11388 if(IS_BITFIELD(etype)) {
11389 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11390 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11392 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11395 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11397 if(IS_BITFIELD(etype)) {
11398 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11400 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11403 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11407 /* move right to W */
11408 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11411 /* if the bit length is less than or */
11412 /* it exactly fits a byte then */
11413 if((shCnt=SPEC_BSTR(etype))
11414 || SPEC_BLEN(etype) <= 8 ) {
11415 int fsr0_setup = 0;
11417 if (blen != 8 || bstr != 0) {
11418 // we need to combine the value with the old value
11419 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11421 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11422 SPEC_BSTR(etype), SPEC_BLEN(etype));
11424 /* shift left acc */
11427 /* using PRODH as a temporary register here */
11428 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11430 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11431 /* access symbol directly */
11432 pic16_mov2w (AOP(result), 0);
11434 /* get old value */
11435 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11438 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11439 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11440 (unsigned char)(0xff >> (8-bstr))) ));
11441 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11442 } // if (blen != 8 || bstr != 0)
11444 /* write new value back */
11445 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11446 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11448 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11457 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11458 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11463 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11464 rLen = SPEC_BLEN(etype)-8;
11466 /* now generate for lengths greater than one byte */
11470 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11476 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11482 pic16_emitcode("movx","@dptr,a");
11487 DEBUGpic16_emitcode(";lcall","__gptrput");
11495 pic16_mov2w(AOP(right), offset++);
11498 /* last last was not complete */
11500 /* save the byte & read byte */
11503 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11504 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11509 pic16_emitcode ("mov","b,a");
11510 pic16_emitcode("movx","a,@dptr");
11514 pic16_emitcode ("push","b");
11515 pic16_emitcode ("push","acc");
11516 pic16_emitcode ("lcall","__gptrget");
11517 pic16_emitcode ("pop","b");
11523 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11524 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11525 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11526 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11527 // pic16_emitcode ("orl","a,b");
11530 // if (p_type == GPOINTER)
11531 // pic16_emitcode("pop","b");
11536 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11537 // pic16_emitcode("mov","@%s,a",rname);
11541 pic16_emitcode("movx","@dptr,a");
11545 DEBUGpic16_emitcode(";lcall","__gptrput");
11552 // pic16_freeAsmop(right, NULL, ic, TRUE);
11555 /*-----------------------------------------------------------------*/
11556 /* genDataPointerSet - remat pointer to data space */
11557 /*-----------------------------------------------------------------*/
11558 static void genDataPointerSet(operand *right,
11562 int size, offset = 0, resoffset=0 ;
11564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11565 pic16_aopOp(right,ic,FALSE);
11567 size = AOP_SIZE(right);
11569 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11572 if ( AOP_TYPE(result) == AOP_PCODE) {
11573 fprintf(stderr,"genDataPointerSet %s, %d\n",
11574 AOP(result)->aopu.pcop->name,
11575 (AOP(result)->aopu.pcop->type == PO_DIR)?
11576 PCOR(AOP(result)->aopu.pcop)->instance:
11577 PCOI(AOP(result)->aopu.pcop)->offset);
11581 if(AOP(result)->aopu.pcop->type == PO_DIR)
11582 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11585 if (AOP_TYPE(right) == AOP_LIT) {
11588 if(!IS_FLOAT(operandType( right )))
11589 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11592 unsigned long lit_int;
11596 /* take care if literal is a float */
11597 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11598 lit = info.lit_int;
11601 lit = lit >> (8*offset);
11602 pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11604 pic16_mov2w(AOP(right), offset);
11605 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11611 pic16_freeAsmop(right,NULL,ic,TRUE);
11616 /*-----------------------------------------------------------------*/
11617 /* genNearPointerSet - pic16_emitcode for near pointer put */
11618 /*-----------------------------------------------------------------*/
11619 static void genNearPointerSet (operand *right,
11625 sym_link *ptype = operandType(result);
11626 sym_link *resetype;
11628 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11629 retype= getSpec(operandType(right));
11630 resetype = getSpec(operandType(result));
11632 pic16_aopOp(result,ic,FALSE);
11634 /* if the result is rematerializable &
11635 * in data space & not a bit variable */
11637 /* and result is not a bit variable */
11638 if (AOP_TYPE(result) == AOP_PCODE
11639 // && AOP_TYPE(result) == AOP_IMMD
11640 && DCL_TYPE(ptype) == POINTER
11641 && !IS_BITFIELD(retype)
11642 && !IS_BITFIELD(resetype)) {
11644 genDataPointerSet (right,result,ic);
11645 pic16_freeAsmop(result,NULL,ic,TRUE);
11649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11650 pic16_aopOp(right,ic,FALSE);
11651 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11653 /* if bitfield then unpack the bits */
11654 if (IS_BITFIELD(resetype)) {
11655 genPackBits (resetype, result, right, NULL, POINTER);
11657 /* we have can just get the values */
11658 int size = AOP_SIZE(right);
11661 pic16_loadFSR0(result, 0);
11663 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11665 if (AOP_TYPE(right) == AOP_LIT) {
11666 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11668 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11670 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11672 } else { // no literal
11674 pic16_emitpcode(POC_MOVFF,
11675 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11676 pic16_popCopyReg(&pic16_pc_postinc0)));
11678 pic16_emitpcode(POC_MOVFF,
11679 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11680 pic16_popCopyReg(&pic16_pc_indf0)));
11687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11688 /* now some housekeeping stuff */
11690 /* we had to allocate for this iCode */
11691 pic16_freeAsmop(NULL,aop,ic,TRUE);
11693 /* we did not allocate which means left
11694 * already in a pointer register, then
11695 * if size > 0 && this could be used again
11696 * we have to point it back to where it
11698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11699 if (AOP_SIZE(right) > 1
11700 && !OP_SYMBOL(result)->remat
11701 && ( OP_SYMBOL(result)->liveTo > ic->seq
11704 int size = AOP_SIZE(right) - 1;
11707 pic16_emitcode("decf","fsr0,f");
11708 //pic16_emitcode("dec","%s",rname);
11712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11715 pic16_freeAsmop(right,NULL,ic,TRUE);
11716 pic16_freeAsmop(result,NULL,ic,TRUE);
11719 /*-----------------------------------------------------------------*/
11720 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11721 /*-----------------------------------------------------------------*/
11722 static void genPagedPointerSet (operand *right,
11727 regs *preg = NULL ;
11731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11733 retype= getSpec(operandType(right));
11735 pic16_aopOp(result,ic,FALSE);
11737 /* if the value is already in a pointer register
11738 then don't need anything more */
11739 if (!AOP_INPREG(AOP(result))) {
11740 /* otherwise get a free pointer register */
11742 preg = getFreePtr(ic,&aop,FALSE);
11743 pic16_emitcode("mov","%s,%s",
11745 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11746 rname = preg->name ;
11748 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11750 pic16_freeAsmop(result,NULL,ic,TRUE);
11751 pic16_aopOp (right,ic,FALSE);
11753 /* if bitfield then unpack the bits */
11754 if (IS_BITFIELD(retype))
11755 genPackBits (retype,result,right,rname,PPOINTER);
11757 /* we have can just get the values */
11758 int size = AOP_SIZE(right);
11762 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11765 pic16_emitcode("movx","@%s,a",rname);
11768 pic16_emitcode("inc","%s",rname);
11774 /* now some housekeeping stuff */
11776 /* we had to allocate for this iCode */
11777 pic16_freeAsmop(NULL,aop,ic,TRUE);
11779 /* we did not allocate which means left
11780 already in a pointer register, then
11781 if size > 0 && this could be used again
11782 we have to point it back to where it
11784 if (AOP_SIZE(right) > 1 &&
11785 !OP_SYMBOL(result)->remat &&
11786 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11788 int size = AOP_SIZE(right) - 1;
11790 pic16_emitcode("dec","%s",rname);
11795 pic16_freeAsmop(right,NULL,ic,TRUE);
11801 /* This code is not adjusted to PIC16 and fails utterly...
11802 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11804 /*-----------------------------------------------------------------*/
11805 /* genFarPointerSet - set value from far space */
11806 /*-----------------------------------------------------------------*/
11807 static void genFarPointerSet (operand *right,
11808 operand *result, iCode *ic)
11811 sym_link *retype = getSpec(operandType(right));
11813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11814 pic16_aopOp(result,ic,FALSE);
11816 /* if the operand is already in dptr
11817 then we do nothing else we move the value to dptr */
11818 if (AOP_TYPE(result) != AOP_STR) {
11819 /* if this is remateriazable */
11820 if (AOP_TYPE(result) == AOP_IMMD)
11821 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11822 else { /* we need to get it byte by byte */
11823 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11824 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11825 if (options.model == MODEL_FLAT24)
11827 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11831 /* so dptr know contains the address */
11832 pic16_freeAsmop(result,NULL,ic,TRUE);
11833 pic16_aopOp(right,ic,FALSE);
11835 /* if bit then unpack */
11836 if (IS_BITFIELD(retype))
11837 genPackBits(retype,result,right,"dptr",FPOINTER);
11839 size = AOP_SIZE(right);
11843 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11845 pic16_emitcode("movx","@dptr,a");
11847 pic16_emitcode("inc","dptr");
11851 pic16_freeAsmop(right,NULL,ic,TRUE);
11855 /*-----------------------------------------------------------------*/
11856 /* genGenPointerSet - set value from generic pointer space */
11857 /*-----------------------------------------------------------------*/
11859 static void genGenPointerSet (operand *right,
11860 operand *result, iCode *ic)
11862 int i, size, offset, lit;
11863 sym_link *retype = getSpec(operandType(right));
11865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11867 pic16_aopOp(result,ic,FALSE);
11868 pic16_aopOp(right,ic,FALSE);
11869 size = AOP_SIZE(right);
11872 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11874 /* if the operand is already in dptr
11875 then we do nothing else we move the value to dptr */
11876 if (AOP_TYPE(result) != AOP_STR) {
11877 /* if this is remateriazable */
11878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11879 // WARNING: anythig until "else" is untested!
11880 if (AOP_TYPE(result) == AOP_IMMD) {
11881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11882 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11883 // load FSR0 from immediate
11884 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11888 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11890 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11896 else { /* we need to get it byte by byte */
11897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11898 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11900 // set up FSR0 with address of result
11901 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11902 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11904 /* hack hack! see if this the FSR. If so don't load W */
11905 if(AOP_TYPE(right) != AOP_ACC) {
11907 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11909 if(AOP_TYPE(right) == AOP_LIT)
11912 // note: pic16_popGet handles sign extension
11913 for(i=0;i<size;i++) {
11914 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11916 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11918 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11923 for(i=0;i<size;i++) {
11925 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11926 pic16_popCopyReg(&pic16_pc_postinc0)));
11928 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11929 pic16_popCopyReg(&pic16_pc_indf0)));
11935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11936 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11938 } // if (AOP_TYPE(result) != AOP_IMMD)
11940 } // if (AOP_TYPE(result) != AOP_STR)
11941 /* so dptr know contains the address */
11944 /* if bit then unpack */
11945 if (IS_BITFIELD(retype))
11946 genPackBits(retype,result,right,"dptr",GPOINTER);
11948 size = AOP_SIZE(right);
11951 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11953 // set up FSR0 with address of result
11954 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11955 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11958 if (AOP_TYPE(right) == AOP_LIT) {
11959 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11961 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11963 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11965 } else { // no literal
11967 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11969 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11977 pic16_freeAsmop(right,NULL,ic,TRUE);
11978 pic16_freeAsmop(result,NULL,ic,TRUE);
11982 static void genGenPointerSet (operand *right,
11983 operand *result, iCode *ic)
11986 sym_link *retype = getSpec(operandType(result));
11988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11990 pic16_aopOp(result,ic,FALSE);
11991 pic16_aopOp(right,ic,FALSE);
11992 size = AOP_SIZE(right);
11994 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11997 /* if bit then unpack */
11998 if (IS_BITFIELD(retype)) {
11999 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12000 genPackBits(retype,result,right,"dptr",GPOINTER);
12004 size = AOP_SIZE(right);
12006 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12009 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12011 /* value of right+0 is placed on stack, which will be retrieved
12012 * by the support function this restoring the stack. The important
12013 * thing is that there is no need to manually restore stack pointer
12015 pushaop(AOP(right), 0);
12016 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12017 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12018 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12019 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12021 /* load address to write to in WREG:FSR0H:FSR0L */
12022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12023 pic16_popCopyReg(&pic16_pc_fsr0l)));
12024 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12025 pic16_popCopyReg(&pic16_pc_prodl)));
12026 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12028 pic16_callGenericPointerRW(1, size);
12031 pic16_freeAsmop(right,NULL,ic,TRUE);
12032 pic16_freeAsmop(result,NULL,ic,TRUE);
12035 /*-----------------------------------------------------------------*/
12036 /* genPointerSet - stores the value into a pointer location */
12037 /*-----------------------------------------------------------------*/
12038 static void genPointerSet (iCode *ic)
12040 operand *right, *result ;
12041 sym_link *type, *etype;
12046 right = IC_RIGHT(ic);
12047 result = IC_RESULT(ic) ;
12049 /* depending on the type of pointer we need to
12050 move it to the correct pointer register */
12051 type = operandType(result);
12052 etype = getSpec(type);
12054 /* if left is of type of pointer then it is simple */
12055 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12056 p_type = DCL_TYPE(type);
12059 /* we have to go by the storage class */
12060 p_type = PTR_TYPE(SPEC_OCLS(etype));
12062 /* if (SPEC_OCLS(etype)->codesp ) { */
12063 /* p_type = CPOINTER ; */
12066 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12067 /* p_type = FPOINTER ; */
12069 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12070 /* p_type = PPOINTER ; */
12072 /* if (SPEC_OCLS(etype) == idata ) */
12073 /* p_type = IPOINTER ; */
12075 /* p_type = POINTER ; */
12078 /* now that we have the pointer type we assign
12079 the pointer values */
12084 genNearPointerSet (right,result,ic);
12088 genPagedPointerSet (right,result,ic);
12092 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12094 genFarPointerSet (right,result,ic);
12099 genGenPointerSet (right,result,ic);
12103 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12104 "genPointerSet: illegal pointer type");
12108 /*-----------------------------------------------------------------*/
12109 /* genIfx - generate code for Ifx statement */
12110 /*-----------------------------------------------------------------*/
12111 static void genIfx (iCode *ic, iCode *popIc)
12113 operand *cond = IC_COND(ic);
12118 pic16_aopOp(cond,ic,FALSE);
12120 /* get the value into acc */
12121 if (AOP_TYPE(cond) != AOP_CRY)
12122 pic16_toBoolean(cond);
12125 /* the result is now in the accumulator */
12126 pic16_freeAsmop(cond,NULL,ic,TRUE);
12128 /* if there was something to be popped then do it */
12132 /* if the condition is a bit variable */
12133 if (isbit && IS_ITEMP(cond) &&
12135 genIfxJump(ic,"c");
12136 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12138 if (isbit && !IS_ITEMP(cond))
12139 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12141 genIfxJump(ic,"a");
12146 /*-----------------------------------------------------------------*/
12147 /* genAddrOf - generates code for address of */
12148 /*-----------------------------------------------------------------*/
12149 static void genAddrOf (iCode *ic)
12151 operand *result, *left;
12153 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12154 pCodeOp *pcop0, *pcop1, *pcop2;
12158 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12160 sym = OP_SYMBOL( IC_LEFT(ic) );
12163 /* get address of symbol on stack */
12164 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12166 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12167 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12170 // operands on stack are accessible via "FSR2 + index" with index
12171 // starting at 2 for arguments and growing from 0 downwards for
12172 // local variables (index == 0 is not assigned so we add one here)
12174 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12176 assert (soffs < 0);
12179 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12180 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12181 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12182 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12183 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12184 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12185 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12191 // if(pic16_debug_verbose) {
12192 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12193 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12196 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12197 size = AOP_SIZE(IC_RESULT(ic));
12199 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12200 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12201 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12204 pic16_emitpcode(POC_MOVLW, pcop0);
12205 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12206 pic16_emitpcode(POC_MOVLW, pcop1);
12207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12208 pic16_emitpcode(POC_MOVLW, pcop2);
12209 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12212 pic16_emitpcode(POC_MOVLW, pcop0);
12213 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12214 pic16_emitpcode(POC_MOVLW, pcop1);
12215 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12217 pic16_emitpcode(POC_MOVLW, pcop0);
12218 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12221 pic16_freeAsmop(left, NULL, ic, FALSE);
12223 pic16_freeAsmop(result,NULL,ic,TRUE);
12228 /*-----------------------------------------------------------------*/
12229 /* genFarFarAssign - assignment when both are in far space */
12230 /*-----------------------------------------------------------------*/
12231 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12233 int size = AOP_SIZE(right);
12236 /* first push the right side on to the stack */
12238 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12240 pic16_emitcode ("push","acc");
12243 pic16_freeAsmop(right,NULL,ic,FALSE);
12244 /* now assign DPTR to result */
12245 pic16_aopOp(result,ic,FALSE);
12246 size = AOP_SIZE(result);
12248 pic16_emitcode ("pop","acc");
12249 pic16_aopPut(AOP(result),"a",--offset);
12251 pic16_freeAsmop(result,NULL,ic,FALSE);
12256 /*-----------------------------------------------------------------*/
12257 /* genAssign - generate code for assignment */
12258 /*-----------------------------------------------------------------*/
12259 static void genAssign (iCode *ic)
12261 operand *result, *right;
12262 sym_link *restype, *rtype;
12263 int size, offset,know_W;
12264 unsigned long lit = 0L;
12266 result = IC_RESULT(ic);
12267 right = IC_RIGHT(ic) ;
12271 /* if they are the same */
12272 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12275 /* reversed order operands are aopOp'ed so that result operand
12276 * is effective in case right is a stack symbol. This maneauver
12277 * allows to use the _G.resDirect flag later */
12278 pic16_aopOp(result,ic,TRUE);
12279 pic16_aopOp(right,ic,FALSE);
12281 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12283 /* if they are the same registers */
12284 if (pic16_sameRegs(AOP(right),AOP(result)))
12287 /* if the result is a bit */
12288 if (AOP_TYPE(result) == AOP_CRY) {
12289 /* if the right size is a literal then
12290 we know what the value is */
12291 if (AOP_TYPE(right) == AOP_LIT) {
12293 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12294 pic16_popGet(AOP(result),0));
12296 if (((int) operandLitValue(right)))
12297 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12298 AOP(result)->aopu.aop_dir,
12299 AOP(result)->aopu.aop_dir);
12301 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12302 AOP(result)->aopu.aop_dir,
12303 AOP(result)->aopu.aop_dir);
12307 /* the right is also a bit variable */
12308 if (AOP_TYPE(right) == AOP_CRY) {
12309 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12310 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12311 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12313 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12314 AOP(result)->aopu.aop_dir,
12315 AOP(result)->aopu.aop_dir);
12316 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12317 AOP(right)->aopu.aop_dir,
12318 AOP(right)->aopu.aop_dir);
12319 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12320 AOP(result)->aopu.aop_dir,
12321 AOP(result)->aopu.aop_dir);
12325 /* we need to or */
12326 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12327 pic16_toBoolean(right);
12329 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12330 //pic16_aopPut(AOP(result),"a",0);
12334 /* bit variables done */
12336 size = AOP_SIZE(result);
12337 restype = operandType(result);
12338 rtype = operandType(right);
12341 if(AOP_TYPE(right) == AOP_LIT) {
12342 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12344 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12346 /* patch tag for literals that are cast to pointers */
12347 if (IS_CODEPTR(restype)) {
12348 //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12349 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12351 if (IS_GENPTR(restype))
12353 if (IS_CODEPTR(rtype)) {
12354 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12355 lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12356 } else if (PIC_IS_DATA_PTR(rtype)) {
12357 //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12358 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12359 } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12360 //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12361 } else if (IS_PTR(rtype)) {
12362 fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12363 lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12369 unsigned long lit_int;
12374 if(IS_FIXED16X16(operandType(right))) {
12375 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12377 /* take care if literal is a float */
12378 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12379 lit = info.lit_int;
12384 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12385 // sizeof(unsigned long int), sizeof(float));
12388 if (AOP_TYPE(right) == AOP_REG) {
12389 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12391 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12396 /* when do we have to read the program memory?
12397 * - if right itself is a symbol in code space
12398 * (we don't care what it points to if it's a pointer)
12399 * - AND right is not a function (we would want its address)
12401 if(AOP_TYPE(right) != AOP_LIT
12402 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12403 && !IS_FUNC(OP_SYM_TYPE(right))
12404 && !IS_ITEMP(right))
12406 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12407 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12409 // set up table pointer
12410 if(is_LitOp(right)) {
12411 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12412 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12413 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12414 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12415 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12416 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12417 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12419 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12420 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12421 pic16_popCopyReg(&pic16_pc_tblptrl)));
12422 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12423 pic16_popCopyReg(&pic16_pc_tblptrh)));
12424 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12425 pic16_popCopyReg(&pic16_pc_tblptru)));
12428 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12429 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12431 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12432 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12433 pic16_popGet(AOP(result),offset)));
12437 /* FIXME: for pointers we need to extend differently (according
12438 * to pointer type DATA/CODE/EEPROM/... :*/
12439 size = getSize(OP_SYM_TYPE(right));
12440 if(AOP_SIZE(result) > size) {
12441 size = AOP_SIZE(result) - size;
12443 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12451 /* VR - What is this?! */
12452 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12453 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12454 if(aopIdx(AOP(result),0) == 4) {
12456 /* this is a workaround to save value of right into wreg too,
12457 * value of wreg is going to be used later */
12458 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12459 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12460 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12464 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12470 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12471 if(AOP_TYPE(right) == AOP_LIT) {
12473 if(know_W != (lit&0xff))
12474 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12476 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12478 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12482 } else if (AOP_TYPE(right) == AOP_CRY) {
12483 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12485 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12486 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12487 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12489 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12490 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12491 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12493 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12495 if(!_G.resDirect) /* use this aopForSym feature */
12496 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12503 pic16_freeAsmop (right,NULL,ic,FALSE);
12504 pic16_freeAsmop (result,NULL,ic,TRUE);
12507 /*-----------------------------------------------------------------*/
12508 /* genJumpTab - generates code for jump table */
12509 /*-----------------------------------------------------------------*/
12510 static void genJumpTab (iCode *ic)
12515 pCodeOp *jt_offs_hi;
12520 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12521 /* get the condition into accumulator */
12522 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12524 /* multiply by three */
12525 pic16_emitcode("add","a,acc");
12526 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12528 jtab = newiTempLabel(NULL);
12529 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12530 pic16_emitcode("jmp","@a+dptr");
12531 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12534 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12535 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12537 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12538 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12539 pic16_emitpLabel(jtab->key);
12543 jt_offs = pic16_popGetTempReg(0);
12544 jt_offs_hi = pic16_popGetTempReg(1);
12545 jt_label = pic16_popGetLabel (jtab->key);
12546 //fprintf (stderr, "Creating jump table...\n");
12548 // calculate offset into jump table (idx * sizeof (GOTO))
12549 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12550 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12551 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12552 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12553 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12554 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12555 pic16_emitpcode(POC_MOVWF , jt_offs);
12557 // prepare PCLATx (set to first entry in jump table)
12558 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12559 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12560 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12561 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12562 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12564 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12565 pic16_emitpcode(POC_ADDWF , jt_offs);
12566 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12567 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12569 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12571 // release temporaries and prepare jump into table (new PCL --> WREG)
12572 pic16_emitpcode(POC_MOVFW , jt_offs);
12573 pic16_popReleaseTempReg (jt_offs_hi, 1);
12574 pic16_popReleaseTempReg (jt_offs, 0);
12576 // jump into the table
12577 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12579 pic16_emitpLabelFORCE(jtab->key);
12582 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12583 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12585 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12586 /* now generate the jump labels */
12587 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12588 jtab = setNextItem(IC_JTLABELS(ic))) {
12589 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12590 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12593 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12597 /*-----------------------------------------------------------------*/
12598 /* genMixedOperation - gen code for operators between mixed types */
12599 /*-----------------------------------------------------------------*/
12601 TSD - Written for the PIC port - but this unfortunately is buggy.
12602 This routine is good in that it is able to efficiently promote
12603 types to different (larger) sizes. Unfortunately, the temporary
12604 variables that are optimized out by this routine are sometimes
12605 used in other places. So until I know how to really parse the
12606 iCode tree, I'm going to not be using this routine :(.
12608 static int genMixedOperation (iCode *ic)
12611 operand *result = IC_RESULT(ic);
12612 sym_link *ctype = operandType(IC_LEFT(ic));
12613 operand *right = IC_RIGHT(ic);
12619 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12621 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12627 nextright = IC_RIGHT(nextic);
12628 nextleft = IC_LEFT(nextic);
12629 nextresult = IC_RESULT(nextic);
12631 pic16_aopOp(right,ic,FALSE);
12632 pic16_aopOp(result,ic,FALSE);
12633 pic16_aopOp(nextright, nextic, FALSE);
12634 pic16_aopOp(nextleft, nextic, FALSE);
12635 pic16_aopOp(nextresult, nextic, FALSE);
12637 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12639 operand *t = right;
12643 pic16_emitcode(";remove right +","");
12645 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12647 operand *t = right;
12651 pic16_emitcode(";remove left +","");
12655 big = AOP_SIZE(nextleft);
12656 small = AOP_SIZE(nextright);
12658 switch(nextic->op) {
12661 pic16_emitcode(";optimize a +","");
12662 /* if unsigned or not an integral type */
12663 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12664 pic16_emitcode(";add a bit to something","");
12667 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12669 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12670 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12671 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12673 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12681 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12682 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12683 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12686 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12688 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12689 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12690 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12691 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12692 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12695 pic16_emitcode("rlf","known_zero,w");
12702 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12703 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12704 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12706 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12716 pic16_freeAsmop(right,NULL,ic,TRUE);
12717 pic16_freeAsmop(result,NULL,ic,TRUE);
12718 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12719 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12721 nextic->generated = 1;
12728 /*-----------------------------------------------------------------*/
12729 /* genCast - gen code for casting */
12730 /*-----------------------------------------------------------------*/
12731 static void genCast (iCode *ic)
12733 operand *result = IC_RESULT(ic);
12734 sym_link *ctype = operandType(IC_LEFT(ic));
12735 sym_link *rtype = operandType(IC_RIGHT(ic));
12736 sym_link *restype = operandType(IC_RESULT(ic));
12737 operand *right = IC_RIGHT(ic);
12743 /* if they are equivalent then do nothing */
12744 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12747 pic16_aopOp(result,ic,FALSE);
12748 pic16_aopOp(right,ic,FALSE) ;
12750 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12753 /* if the result is a bit */
12754 if (AOP_TYPE(result) == AOP_CRY) {
12756 /* if the right size is a literal then
12757 * we know what the value is */
12758 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12760 if (AOP_TYPE(right) == AOP_LIT) {
12761 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12762 pic16_popGet(AOP(result),0));
12764 if (((int) operandLitValue(right)))
12765 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12766 AOP(result)->aopu.aop_dir,
12767 AOP(result)->aopu.aop_dir);
12769 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12770 AOP(result)->aopu.aop_dir,
12771 AOP(result)->aopu.aop_dir);
12775 /* the right is also a bit variable */
12776 if (AOP_TYPE(right) == AOP_CRY) {
12778 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12780 pic16_emitcode("clrc","");
12781 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12782 AOP(right)->aopu.aop_dir,
12783 AOP(right)->aopu.aop_dir);
12784 pic16_aopPut(AOP(result),"c",0);
12788 /* we need to or */
12789 if (AOP_TYPE(right) == AOP_REG) {
12790 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12791 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12792 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12794 pic16_toBoolean(right);
12795 pic16_aopPut(AOP(result),"a",0);
12799 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12802 size = AOP_SIZE(result);
12804 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12806 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12807 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12808 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12811 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12816 if(IS_BITFIELD(getSpec(restype))
12817 && IS_BITFIELD(getSpec(rtype))) {
12818 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12821 /* port from pic14 to cope with generic pointers */
12822 if (PIC_IS_TAGGED(restype))
12824 operand *result = IC_RESULT(ic);
12825 //operand *left = IC_LEFT(ic);
12826 operand *right = IC_RIGHT(ic);
12829 /* copy common part */
12830 int max, size = AOP_SIZE(result);
12831 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12832 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12837 pic16_mov2w (AOP(right), size);
12838 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12841 /* upcast into generic pointer type? */
12842 if (IS_GENPTR(restype)
12843 && !PIC_IS_TAGGED(rtype)
12844 && (AOP_SIZE(result) > max))
12846 /* determine appropriate tag for right */
12847 if (PIC_IS_DATA_PTR(rtype))
12848 tag = GPTR_TAG_DATA;
12849 else if (IS_CODEPTR(rtype))
12850 tag = GPTR_TAG_CODE;
12851 else if (PIC_IS_DATA_PTR(ctype)) {
12852 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12853 tag = GPTR_TAG_DATA;
12854 } else if (IS_CODEPTR(ctype)) {
12855 //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12856 tag = GPTR_TAG_CODE;
12857 } else if (IS_PTR(rtype)) {
12858 PERFORM_ONCE(weirdcast,
12859 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12861 tag = GPTR_TAG_DATA;
12863 PERFORM_ONCE(weirdcast,
12864 fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12866 tag = GPTR_TAG_DATA;
12869 assert (AOP_SIZE(result) == 3);
12870 /* zero-extend address... */
12871 for (size = max; size < AOP_SIZE(result)-1; size++)
12872 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12873 /* ...and add tag */
12874 pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12875 } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12876 //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12877 for (size = max; size < AOP_SIZE(result)-1; size++)
12878 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12879 /* add __code tag */
12880 pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12881 } else if (AOP_SIZE(result) > max) {
12882 /* extend non-pointers */
12883 //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12884 pic16_addSign(result, max, 0);
12889 /* if they are the same size : or less */
12890 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12892 /* if they are in the same place */
12893 if (pic16_sameRegs(AOP(right),AOP(result)))
12896 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12898 if (IS_PTR_CONST(rtype))
12900 if (IS_CODEPTR(rtype))
12902 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12905 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12907 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12909 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12912 if(AOP_TYPE(right) == AOP_IMMD) {
12913 pCodeOp *pcop0, *pcop1, *pcop2;
12914 symbol *sym = OP_SYMBOL( right );
12916 size = AOP_SIZE(result);
12918 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12920 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12922 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12925 pic16_emitpcode(POC_MOVLW, pcop0);
12926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12927 pic16_emitpcode(POC_MOVLW, pcop1);
12928 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12929 pic16_emitpcode(POC_MOVLW, pcop2);
12930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12933 pic16_emitpcode(POC_MOVLW, pcop0);
12934 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12935 pic16_emitpcode(POC_MOVLW, pcop1);
12936 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12938 pic16_emitpcode(POC_MOVLW, pcop0);
12939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12943 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12944 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12946 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12948 if(AOP_SIZE(result) <2)
12949 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12951 /* if they in different places then copy */
12952 size = AOP_SIZE(result);
12955 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12963 /* if the result is of type pointer */
12964 if (IS_PTR(ctype)) {
12966 sym_link *type = operandType(right);
12967 sym_link *etype = getSpec(type);
12969 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12971 /* pointer to generic pointer */
12972 if (IS_GENPTR(ctype)) {
12976 p_type = DCL_TYPE(type);
12978 /* we have to go by the storage class */
12979 p_type = PTR_TYPE(SPEC_OCLS(etype));
12981 /* if (SPEC_OCLS(etype)->codesp ) */
12982 /* p_type = CPOINTER ; */
12984 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12985 /* p_type = FPOINTER ; */
12987 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12988 /* p_type = PPOINTER; */
12990 /* if (SPEC_OCLS(etype) == idata ) */
12991 /* p_type = IPOINTER ; */
12993 /* p_type = POINTER ; */
12996 /* the first two bytes are known */
12997 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12998 size = GPTRSIZE - 1;
13001 if(offset < AOP_SIZE(right)) {
13002 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13003 pic16_mov2f(AOP(result), AOP(right), offset);
13005 if ((AOP_TYPE(right) == AOP_PCODE) &&
13006 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13007 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13011 pic16_aopPut(AOP(result),
13012 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13017 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13020 /* the last byte depending on type */
13025 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13029 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13033 pic16_emitcode(";BUG!? ","%d",__LINE__);
13038 if (GPTRSIZE > AOP_SIZE(right)) {
13039 // assume __data pointer... THIS MIGHT BE WRONG!
13040 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13042 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13047 /* this should never happen */
13048 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13049 "got unknown pointer type");
13052 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13058 /* just copy the pointers */
13059 size = AOP_SIZE(result);
13062 pic16_aopPut(AOP(result),
13063 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13072 /* so we now know that the size of destination is greater
13073 than the size of the source.
13074 Now, if the next iCode is an operator then we might be
13075 able to optimize the operation without performing a cast.
13077 if(genMixedOperation(ic))
13080 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13082 /* we move to result for the size of source */
13083 size = AOP_SIZE(right);
13088 pic16_mov2f(AOP(result), AOP(right), offset);
13092 /* now depending on the sign of the destination */
13093 size = AOP_SIZE(result) - AOP_SIZE(right);
13094 /* if unsigned or not an integral type */
13095 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13097 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13099 /* we need to extend the sign :( */
13102 /* Save one instruction of casting char to int */
13103 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13104 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13105 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13107 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13110 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13112 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13114 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13117 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13122 pic16_freeAsmop(right,NULL,ic,TRUE);
13123 pic16_freeAsmop(result,NULL,ic,TRUE);
13127 /*-----------------------------------------------------------------*/
13128 /* genDjnz - generate decrement & jump if not zero instrucion */
13129 /*-----------------------------------------------------------------*/
13130 static int genDjnz (iCode *ic, iCode *ifx)
13132 symbol *lbl, *lbl1;
13133 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13138 /* if the if condition has a false label
13139 then we cannot save */
13143 /* if the minus is not of the form
13145 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13146 !IS_OP_LITERAL(IC_RIGHT(ic)))
13149 if (operandLitValue(IC_RIGHT(ic)) != 1)
13152 /* if the size of this greater than one then no
13154 if (getSize(operandType(IC_RESULT(ic))) > 1)
13157 /* otherwise we can save BIG */
13158 lbl = newiTempLabel(NULL);
13159 lbl1= newiTempLabel(NULL);
13161 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13163 if (IS_AOP_PREG(IC_RESULT(ic))) {
13164 pic16_emitcode("dec","%s",
13165 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13166 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13167 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13171 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13172 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13174 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13175 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13179 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13180 ifx->generated = 1;
13184 /*-----------------------------------------------------------------*/
13185 /* genReceive - generate code for a receive iCode */
13186 /*-----------------------------------------------------------------*/
13187 static void genReceive (iCode *ic)
13193 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13194 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13196 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13198 if (isOperandInFarSpace(IC_RESULT(ic))
13199 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13200 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13202 int size = getSize(operandType(IC_RESULT(ic)));
13203 int offset = pic16_fReturnSizePic - size;
13207 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13208 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13212 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13214 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13215 size = AOP_SIZE(IC_RESULT(ic));
13218 pic16_emitcode ("pop","acc");
13219 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13222 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13224 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13227 /* set pseudo stack pointer to where it should be - dw*/
13228 GpsuedoStkPtr = ic->parmBytes;
13230 /* setting GpsuedoStkPtr has side effects here: */
13231 assignResultValue(IC_RESULT(ic), 0);
13234 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13237 /*-----------------------------------------------------------------*/
13238 /* genDummyRead - generate code for dummy read of volatiles */
13239 /*-----------------------------------------------------------------*/
13241 genDummyRead (iCode * ic)
13247 if (op && IS_SYMOP(op)) {
13248 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13249 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13252 pic16_aopOp (op, ic, FALSE);
13253 for (i=0; i < AOP_SIZE(op); i++) {
13254 // may need to protect this from the peepholer -- this is not nice but works...
13255 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13256 pic16_mov2w (AOP(op),i);
13257 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13259 pic16_freeAsmop (op, NULL, ic, TRUE);
13261 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13265 /*-----------------------------------------------------------------*/
13266 /* genpic16Code - generate code for pic16 based controllers */
13267 /*-----------------------------------------------------------------*/
13269 * At this point, ralloc.c has gone through the iCode and attempted
13270 * to optimize in a way suitable for a PIC. Now we've got to generate
13271 * PIC instructions that correspond to the iCode.
13273 * Once the instructions are generated, we'll pass through both the
13274 * peep hole optimizer and the pCode optimizer.
13275 *-----------------------------------------------------------------*/
13277 void genpic16Code (iCode *lic)
13282 lineHead = lineCurr = NULL;
13284 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13285 pic16_addpBlock(pb);
13288 /* if debug information required */
13289 if (options.debug && currFunc) {
13291 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13296 for (ic = lic ; ic ; ic = ic->next ) {
13298 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13299 if ( cln != ic->lineno ) {
13300 if ( options.debug ) {
13301 debugFile->writeCLine (ic);
13304 if(!options.noCcodeInAsm) {
13305 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13306 printCLine(ic->filename, ic->lineno)));
13312 if(options.iCodeInAsm) {
13315 /* insert here code to print iCode as comment */
13316 l = Safe_strdup(printILine(ic));
13317 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13320 /* if the result is marked as
13321 * spilt and rematerializable or code for
13322 * this has already been generated then
13324 if (resultRemat(ic) || ic->generated )
13327 /* depending on the operation */
13346 /* IPOP happens only when trying to restore a
13347 * spilt live range, if there is an ifx statement
13348 * following this pop then the if statement might
13349 * be using some of the registers being popped which
13350 * would destroy the contents of the register so
13351 * we need to check for this condition and handle it */
13353 && ic->next->op == IFX
13354 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13355 genIfx (ic->next,ic);
13373 genEndFunction (ic);
13389 pic16_genPlus (ic) ;
13393 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13394 pic16_genMinus (ic);
13410 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13414 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13420 /* note these two are xlated by algebraic equivalence
13421 * during parsing SDCC.y */
13422 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13423 "got '>=' or '<=' shouldn't have come here");
13427 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13439 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13443 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13447 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13471 genRightShift (ic);
13474 case GET_VALUE_AT_ADDRESS:
13479 if (POINTER_SET(ic))
13506 addSet(&_G.sendSet,ic);
13509 case DUMMY_READ_VOLATILE:
13519 /* now we are ready to call the
13520 peep hole optimizer */
13521 if (!options.nopeep)
13522 peepHole (&lineHead);
13524 /* now do the actual printing */
13525 printLine (lineHead, codeOutFile);
13528 DFPRINTF((stderr,"printing pBlock\n\n"));
13529 pic16_printpBlock(stdout,pb);