* src/pic16/gen.c (pic16_mov2w_volatile): NEW, read volatile operands,
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
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 AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   Bug Fixes  -  Borut Razem <borut.razem AT siol.net> (2007)
12
13   This program is free software; you can redistribute it and/or modify it
14   under the terms of the GNU General Public License as published by the
15   Free Software Foundation; either version 2, or (at your option) any
16   later version.
17
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27   In other words, you are welcome to use, share and improve this program.
28   You are forbidden to forbid anyone else to use, share and improve
29   what you give them.   Help stamp out software-hoarding!
30
31   Notes:
32   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
33                 Made everything static
34 -------------------------------------------------------------------------*/
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include "SDCCglobl.h"
41 #include "newalloc.h"
42
43 #include "common.h"
44 #include "SDCCpeeph.h"
45 #include "ralloc.h"
46 #include "pcode.h"
47 #include "gen.h"
48 #include "genutils.h"
49 #include "device.h"
50 #include "main.h"
51 #include "glue.h"
52
53 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
54 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
55 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
57 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
58
59 /* If you change these, you also have to update the library files
60  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
61 #define GPTR_TAG_DATA   0x80
62 #define GPTR_TAG_EEPROM 0x40
63 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
64
65 /* Wrapper to execute `code' at most once. */
66 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
67
68 void pic16_genMult8X8_n (operand *, operand *,operand *);
69 extern void pic16_printpBlock(FILE *of, pBlock *pb);
70 static asmop *newAsmop (short type);
71 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
72 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
73 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
74 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75
76 int pic16_labelOffset=0;
77 extern int pic16_debug_verbose;
78
79 extern set *externs;
80
81 /* max_key keeps track of the largest label number used in
82    a function. This is then used to adjust the label offset
83    for the next function.
84 */
85 static int max_key=0;
86 static int GpsuedoStkPtr=0;
87
88 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
89
90 const char *pic16_AopType(short type);
91 static iCode *ifxForOp ( operand *op, iCode *ic );
92
93 void pic16_pushpCodeOp(pCodeOp *pcop);
94 void pic16_poppCodeOp(pCodeOp *pcop);
95
96
97 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
98
99 /* set the following macro to 1 to enable passing the
100  * first byte of functions parameters via WREG */
101 #define USE_WREG_IN_FUNC_PARAMS 0
102
103
104 /* this is the down and dirty file with all kinds of
105    kludgy & hacky stuff. This is what it is all about
106    CODE GENERATION for a specific MCU . some of the
107    routines may be reusable, will have to see */
108 static char *zero = "#0x00";
109 static char *one  = "#0x01";
110
111
112 /*
113  * Function return value policy (MSB-->LSB):
114  *  8 bits      -> WREG
115  * 16 bits      -> PRODL:WREG
116  * 24 bits      -> PRODH:PRODL:WREG
117  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
118  * >32 bits     -> on stack, and FSR0 points to the beginning
119  */
120 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
121 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
122 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
123 static char **fReturn = fReturnpic16;
124
125 static char *accUse[] = {"WREG"};
126
127 static struct {
128     short accInUse;
129     short inLine;
130     short debugLine;
131     short nRegsSaved;
132     set *sendSet;
133     set *stackRegSet;
134     int usefastretfie;
135     bitVect *fregsUsed;                 /* registers used in function */
136     bitVect *sregsAlloc;
137     set *sregsAllocSet;                 /* registers used to store stack variables */
138     int stack_lat;                      /* stack offset latency */
139     int resDirect;
140     int useWreg;                        /* flag when WREG is used to pass function parameter */
141 } _G;
142
143 extern struct dbuf_s *codeOutBuf;
144
145 static lineNode *lineHead = NULL;
146 static lineNode *lineCurr = NULL;
147
148 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
149 0xE0, 0xC0, 0x80, 0x00};
150 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
151 0x07, 0x03, 0x01, 0x00};
152
153 static  pBlock *pb;
154
155 /*-----------------------------------------------------------------*/
156 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
157 /*                 exponent of 2 is returned, otherwise -1 is      */
158 /*                 returned.                                       */
159 /* note that this is similar to the function `powof2' in SDCCsymt  */
160 /* if(n == 2^y)                                                    */
161 /*   return y;                                                     */
162 /* return -1;                                                      */
163 /*-----------------------------------------------------------------*/
164 int pic16_my_powof2 (unsigned long num)
165 {
166   if(num) {
167     if( (num & (num-1)) == 0) {
168       int nshifts = -1;
169       while(num) {
170         num>>=1;
171         nshifts++;
172       }
173       return nshifts;
174     }
175   }
176
177   return -1;
178 }
179
180 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
181 {
182   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
183                        line_no,
184                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
185                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
186                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
187                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
188                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
189                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
190                        ((result) ? AOP_SIZE(result) : 0));
191 }
192
193 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
194 {
195
196   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
197                        line_no,
198                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
199                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
200                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
201                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
202                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
203                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
204
205 }
206
207 void pic16_emitpcomment (char *fmt, ...)
208 {
209     va_list ap;
210     char lb[INITIAL_INLINEASM];
211     unsigned char *lbp = (unsigned char *)lb;
212
213     va_start(ap,fmt);
214
215     lb[0] = ';';
216     vsprintf(lb+1,fmt,ap);
217
218     while (isspace(*lbp)) lbp++;
219
220     if (lbp && *lbp)
221         lineCurr = (lineCurr ?
222                     connectLine(lineCurr,newLineNode(lb)) :
223                     (lineHead = newLineNode(lb)));
224     lineCurr->isInline = _G.inLine;
225     lineCurr->isDebug  = _G.debugLine;
226     lineCurr->isComment = 1;
227
228     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
229     va_end(ap);
230
231 //      fprintf(stderr, "%s\n", lb);
232 }
233
234 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
235 {
236     va_list ap;
237     char lb[INITIAL_INLINEASM];
238     unsigned char *lbp = (unsigned char *)lb;
239
240     if(!pic16_debug_verbose)
241       return;
242
243     va_start(ap,fmt);
244
245     if (inst && *inst) {
246         if (fmt && *fmt)
247             sprintf(lb,"%s\t",inst);
248         else
249             sprintf(lb,"%s",inst);
250         vsprintf(lb+(strlen(lb)),fmt,ap);
251     }  else
252         vsprintf(lb,fmt,ap);
253
254     while (isspace(*lbp)) lbp++;
255
256     if (lbp && *lbp)
257         lineCurr = (lineCurr ?
258                     connectLine(lineCurr,newLineNode(lb)) :
259                     (lineHead = newLineNode(lb)));
260     lineCurr->isInline = _G.inLine;
261     lineCurr->isDebug  = _G.debugLine;
262
263     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
264     va_end(ap);
265
266 //      fprintf(stderr, "%s\n", lb);
267 }
268
269
270
271 void pic16_emitpLabel(int key)
272 {
273   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
274 }
275
276 void pic16_emitpLabelFORCE(int key)
277 {
278   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
279 }
280
281 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
282  * NEVER call pic16_emitpcode_real directly, please... */
283 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
284 {
285
286   if(pcop)
287     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
288   else
289     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
290 }
291
292 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
293 {
294   if(pcop)
295     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
296   else
297     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
298 }
299
300 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
301 {
302
303   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
304
305 }
306
307
308 #if 1
309 #define pic16_emitcode  DEBUGpic16_emitcode
310 #else
311 /*-----------------------------------------------------------------*/
312 /* pic16_emitcode - writes the code into a file : for now it is simple    */
313 /*-----------------------------------------------------------------*/
314 void pic16_emitcode (char *inst,char *fmt, ...)
315 {
316     va_list ap;
317     char lb[INITIAL_INLINEASM];
318     unsigned char *lbp = lb;
319
320     va_start(ap,fmt);
321
322     if (inst && *inst) {
323         if (fmt && *fmt)
324             sprintf(lb,"%s\t",inst);
325         else
326             sprintf(lb,"%s",inst);
327         vsprintf(lb+(strlen(lb)),fmt,ap);
328     }  else
329         vsprintf(lb,fmt,ap);
330
331     while (isspace(*lbp)) lbp++;
332
333     if (lbp && *lbp)
334         lineCurr = (lineCurr ?
335                     connectLine(lineCurr,newLineNode(lb)) :
336                     (lineHead = newLineNode(lb)));
337     lineCurr->isInline = _G.inLine;
338     lineCurr->isDebug  = _G.debugLine;
339     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
340     lineCurr->isComment = (*lbp == ';');
341
342 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
343
344 //    if(pic16_debug_verbose)
345 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
346
347     va_end(ap);
348 }
349 #endif
350
351
352 /*-----------------------------------------------------------------*/
353 /* pic16_emitDebuggerSymbol - associate the current code location  */
354 /*   with a debugger symbol                                        */
355 /*-----------------------------------------------------------------*/
356 void
357 pic16_emitDebuggerSymbol (char * debugSym)
358 {
359   _G.debugLine = 1;
360   pic16_emitcode (";", "%s ==.", debugSym);
361   _G.debugLine = 0;
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* newAsmop - creates a new asmOp                                  */
366 /*-----------------------------------------------------------------*/
367 static asmop *newAsmop (short type)
368 {
369     asmop *aop;
370
371     aop = Safe_calloc(1,sizeof(asmop));
372     aop->type = type;
373     return aop;
374 }
375
376 /*-----------------------------------------------------------------*/
377 /* resolveIfx - converts an iCode ifx into a form more useful for  */
378 /*              generating code                                    */
379 /*-----------------------------------------------------------------*/
380 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
381 {
382   FENTRY2;
383
384 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
385
386   if(!resIfx)
387     return;
388
389
390   resIfx->condition = 1;    /* assume that the ifx is true */
391   resIfx->generated = 0;    /* indicate that the ifx has not been used */
392
393   if(!ifx) {
394     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
395
396 #if 1
397     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
398                         __FUNCTION__,__LINE__,resIfx->lbl->key);
399 #endif
400
401   } else {
402     if(IC_TRUE(ifx)) {
403       resIfx->lbl = IC_TRUE(ifx);
404     } else {
405       resIfx->lbl = IC_FALSE(ifx);
406       resIfx->condition = 0;
407     }
408
409 #if 1
410     if(IC_TRUE(ifx))
411       DEBUGpic16_emitcode("; +++","ifx true is non-null");
412     else
413       DEBUGpic16_emitcode("; +++","ifx true is null");
414     if(IC_FALSE(ifx))
415       DEBUGpic16_emitcode("; +++","ifx false is non-null");
416     else
417       DEBUGpic16_emitcode("; +++","ifx false is null");
418 #endif
419   }
420
421   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
422
423 }
424 #if 0
425 /*-----------------------------------------------------------------*/
426 /* pointerCode - returns the code for a pointer type               */
427 /*-----------------------------------------------------------------*/
428 static int pointerCode (sym_link *etype)
429 {
430
431     return PTR_TYPE(SPEC_OCLS(etype));
432
433 }
434 #endif
435
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol                                   */
438 /*-----------------------------------------------------------------*/
439 static asmop *aopForSym (iCode *ic, operand *op, bool result)
440 {
441     symbol *sym=OP_SYMBOL(op);
442     asmop *aop;
443     memmap *space= SPEC_OCLS(sym->etype);
444
445     FENTRY2;
446
447     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
448
449 //    sym = OP_SYMBOL(op);
450
451     /* if already has one */
452     if (sym->aop) {
453             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
454         return sym->aop;
455     }
456
457 #if 0
458     /* if symbol was initially placed onStack then we must re-place it
459      * to direct memory, since pic16 does not have a specific stack */
460     if(sym->onStack) {
461         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
462     }
463 #endif
464
465
466 #if 0
467     if(sym->iaccess) {
468       if(space->paged) {
469         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
470
471         sym->aop = aop = newAsmop (AOP_PAGED);
472         aop->aopu.aop_dir = sym->rname ;
473         aop->size = getSize(sym->type);
474         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
475         pic16_allocDirReg( IC_LEFT(ic) );
476         return aop;
477       }
478       assert( 0 );
479     }
480 #endif
481
482 #if 1
483     /* assign depending on the storage class */
484     /* if it is on the stack or indirectly addressable */
485     /* space we need to assign either r0 or r1 to it   */
486     if (sym->onStack)   // || sym->iaccess)
487     {
488       pCodeOp *pcop[4];
489       int i;
490
491         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
492                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
493
494         /* acquire a temporary register -- it is saved in function */
495
496         sym->aop = aop = newAsmop(AOP_STA);
497         aop->aopu.stk.stk = sym->stack;
498         aop->size = getSize(sym->type);
499
500
501         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
502         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
503           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
504 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
505
506           for(i=0;i<aop->size;i++)
507             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
508             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
509         } else
510         if(1 && ic->op == SEND) {
511
512           /* if SEND do the send here */
513           _G.resDirect = 1;
514         } else {
515 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
516           for(i=0;i<aop->size;i++) {
517             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
518             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
519           }
520         }
521
522
523 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
524
525 #if 1
526         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
527
528         // we do not need to load the value if it is to be defined...
529         if (result) return aop;
530
531         if(_G.accInUse) {
532                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
533         }
534
535         for(i=0;i<aop->size;i++) {
536
537           /* initialise for stack access via frame pointer */
538           // operands on stack are accessible via "{FRAME POINTER} + index" with index
539           // starting at 2 for arguments and growing from 0 downwards for
540           // local variables (index == 0 is not assigned so we add one here)
541           {
542             int soffs = sym->stack;
543             if (soffs <= 0) {
544               assert (soffs < 0);
545               soffs++;
546             } // if
547
548             if(1 && ic->op == SEND) {
549               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
550               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
551                     pic16_popCopyReg( pic16_frame_plusw ),
552                     pic16_popCopyReg(pic16_stack_postdec )));
553             } else {
554               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
555               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
556                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
557             }
558           }
559         }
560
561         if(_G.accInUse) {
562                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
563         }
564
565         return (aop);
566 #endif
567
568 #if 0
569         /* now assign the address of the variable to
570         the pointer register */
571         if (aop->type != AOP_STK) {
572
573             if (sym->onStack) {
574                     if ( _G.accInUse )
575                         pic16_emitcode("push","acc");
576
577                     pic16_emitcode("mov","a,_bp");
578                     pic16_emitcode("add","a,#0x%02x",
579                              ((sym->stack < 0) ?
580                               ((char)(sym->stack - _G.nRegsSaved )) :
581                               ((char)sym->stack)) & 0xff);
582                     pic16_emitcode("mov","%s,a",
583                              aop->aopu.aop_ptr->name);
584
585                     if ( _G.accInUse )
586                         pic16_emitcode("pop","acc");
587             } else
588                 pic16_emitcode("mov","%s,#%s",
589                          aop->aopu.aop_ptr->name,
590                          sym->rname);
591             aop->paged = space->paged;
592         } else
593             aop->aopu.aop_stk = sym->stack;
594         return aop;
595 #endif
596
597     }
598 #endif
599
600 #if 1
601     /* special case for a function */
602     if (IS_FUNC(sym->type)) {
603         sym->aop = aop = newAsmop(AOP_PCODE);
604         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
605         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
606         PCOI(aop->aopu.pcop)->index = 0;
607         aop->size = FPTRSIZE;
608         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
609         return aop;
610     }
611 #endif
612
613
614
615     //DEBUGpic16_emitcode(";","%d",__LINE__);
616     /* if in bit space */
617     if (IN_BITSPACE(space)) {
618         sym->aop = aop = newAsmop (AOP_CRY);
619         aop->aopu.aop_dir = sym->rname ;
620         aop->size = getSize(sym->type);
621         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
622         return aop;
623     }
624     /* if it is in direct space */
625     if (IN_DIRSPACE(space)) {
626                 if(!strcmp(sym->rname, "_WREG")) {
627                         sym->aop = aop = newAsmop (AOP_ACC);
628                         aop->size = getSize(sym->type);         /* should always be 1 */
629                         assert(aop->size == 1);
630                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
631                         return (aop);
632                 } else {
633                         sym->aop = aop = newAsmop (AOP_DIR);
634                 aop->aopu.aop_dir = sym->rname ;
635             aop->size = getSize(sym->type);
636                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
637                         pic16_allocDirReg( IC_LEFT(ic) );
638                         return (aop);
639                 }
640         }
641
642     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
643         sym->aop = aop = newAsmop (AOP_DIR);
644         aop->aopu.aop_dir = sym->rname ;
645         aop->size = getSize(sym->type);
646         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
647         pic16_allocDirReg( IC_LEFT(ic) );
648         return aop;
649     }
650
651
652     /* only remaining is far space */
653     sym->aop = aop = newAsmop(AOP_PCODE);
654
655 /* change the next if to 1 to revert to good old immediate code */
656         if(IN_CODESPACE(space)) {
657                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
658                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
659                 PCOI(aop->aopu.pcop)->index = 0;
660         } else {
661                 /* try to allocate via direct register */
662                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
663 //              aop->size = getSize( sym->type );
664         }
665
666         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
667                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
668
669 #if 0
670         if(!pic16_allocDirReg (IC_LEFT(ic)))
671                 return NULL;
672 #endif
673
674         if(IN_DIRSPACE( space ))
675                 aop->size = PTRSIZE;
676         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
677                 aop->size = FPTRSIZE;
678         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
679         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
680         else if(sym->onStack) {
681                 aop->size = PTRSIZE;
682         } else {
683           if(SPEC_SCLS(sym->etype) == S_PDATA) {
684             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
685             aop->size = FPTRSIZE;
686           } else
687                 assert( 0 );
688         }
689
690     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
691
692     /* if it is in code space */
693     if (IN_CODESPACE(space))
694         aop->code = 1;
695
696     return aop;
697 }
698
699 /*-----------------------------------------------------------------*/
700 /* aopForRemat - rematerialzes an object                           */
701 /*-----------------------------------------------------------------*/
702 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
703 {
704   symbol *sym = OP_SYMBOL(op);
705   operand *refop;
706   iCode *ic = NULL, *oldic;
707   asmop *aop = newAsmop(AOP_PCODE);
708   int val = 0;
709   int offset = 0;
710   int viaimmd=0;
711
712     FENTRY2;
713
714         ic = sym->rematiCode;
715
716         if(IS_OP_POINTER(op)) {
717                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
718         }
719
720 //    if(!result)               /* fixme-vr */
721         for (;;) {
722                 oldic = ic;
723
724 //              chat *iLine = printILine(ic);
725 //              pic16_emitpcomment("ic: %s\n", iLine);
726 //              dbuf_free(iLine);
727
728                 if (ic->op == '+') {
729                         val += (int) operandLitValue(IC_RIGHT(ic));
730                 } else if (ic->op == '-') {
731                         val -= (int) operandLitValue(IC_RIGHT(ic));
732                 } else
733                         break;
734
735                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
736         }
737
738         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
739         refop = IC_LEFT(ic);
740
741         if(!op->isaddr)viaimmd++; else viaimmd=0;
742
743 /* set the following if to 1 to revert to good old immediate code */
744         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
745                 || viaimmd) {
746
747                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
748
749                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
750
751 #if 0
752                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
753 #else
754                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
755 #endif
756
757                 PCOI(aop->aopu.pcop)->index = val;
758
759                 aop->size = getSize( sym->type );
760         } else {
761                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
762
763                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
764                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
765
766                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
767         }
768
769
770         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
771                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
772 #if 0
773                 val, IS_PTR_CONST(operandType(op)));
774 #else
775                 val, IS_CODEPTR(operandType(op)));
776 #endif
777
778 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
779
780         pic16_allocDirReg (IC_LEFT(ic));
781
782         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
783                 aop->code = 1;
784
785   return aop;
786 }
787
788 #if 0
789 static int aopIdx (asmop *aop, int offset)
790 {
791   if(!aop)
792     return -1;
793
794   if(aop->type !=  AOP_REG)
795     return -2;
796
797   return aop->aopu.aop_reg[offset]->rIdx;
798
799 }
800 #endif
801
802 /*-----------------------------------------------------------------*/
803 /* regsInCommon - two operands have some registers in common       */
804 /*-----------------------------------------------------------------*/
805 static bool regsInCommon (operand *op1, operand *op2)
806 {
807     symbol *sym1, *sym2;
808     int i;
809
810     /* if they have registers in common */
811     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
812         return FALSE ;
813
814     sym1 = OP_SYMBOL(op1);
815     sym2 = OP_SYMBOL(op2);
816
817     if (sym1->nRegs == 0 || sym2->nRegs == 0)
818         return FALSE ;
819
820     for (i = 0 ; i < sym1->nRegs ; i++) {
821         int j;
822         if (!sym1->regs[i])
823             continue ;
824
825         for (j = 0 ; j < sym2->nRegs ;j++ ) {
826             if (!sym2->regs[j])
827                 continue ;
828
829             if (sym2->regs[j] == sym1->regs[i])
830                 return TRUE ;
831         }
832     }
833
834     return FALSE ;
835 }
836
837 /*-----------------------------------------------------------------*/
838 /* operandsEqu - equivalent                                        */
839 /*-----------------------------------------------------------------*/
840 static bool operandsEqu ( operand *op1, operand *op2)
841 {
842     symbol *sym1, *sym2;
843
844     /* if they not symbols */
845     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
846         return FALSE;
847
848     sym1 = OP_SYMBOL(op1);
849     sym2 = OP_SYMBOL(op2);
850
851     /* if both are itemps & one is spilt
852        and the other is not then false */
853     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
854         sym1->isspilt != sym2->isspilt )
855         return FALSE ;
856
857     /* if they are the same */
858     if (sym1 == sym2)
859         return TRUE ;
860
861     if (sym1->rname[0] && sym2->rname[0]
862         && strcmp (sym1->rname, sym2->rname) == 0)
863         return TRUE;
864
865
866     /* if left is a tmp & right is not */
867     if (IS_ITEMP(op1)  &&
868         !IS_ITEMP(op2) &&
869         sym1->isspilt  &&
870         (sym1->usl.spillLoc == sym2))
871         return TRUE;
872
873     if (IS_ITEMP(op2)  &&
874         !IS_ITEMP(op1) &&
875         sym2->isspilt  &&
876         sym1->level > 0 &&
877         (sym2->usl.spillLoc == sym1))
878         return TRUE ;
879
880     return FALSE ;
881 }
882
883 /*-----------------------------------------------------------------*/
884 /* pic16_sameRegs - two asmops have the same registers                   */
885 /*-----------------------------------------------------------------*/
886 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
887 {
888     int i;
889
890     if (aop1 == aop2)
891         return TRUE ;
892
893     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
894                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
895
896     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
897
898     if (aop1->type != AOP_REG ||
899         aop2->type != AOP_REG )
900         return FALSE ;
901
902     /* This is a bit too restrictive if one is a subset of the other...
903     if (aop1->size != aop2->size )
904         return FALSE ;
905     */
906
907     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
908 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
909
910 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
911         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
912             return FALSE ;
913     }
914
915     return TRUE ;
916 }
917
918 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
919 {
920     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
921                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
922
923     if(aop1 == aop2)return TRUE;
924     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
925
926       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
927
928   return TRUE;
929 }
930
931
932 /*-----------------------------------------------------------------*/
933 /* pic16_aopOp - allocates an asmop for an operand  :                    */
934 /*-----------------------------------------------------------------*/
935 void pic16_aopOp (operand *op, iCode *ic, bool result)
936 {
937     asmop *aop;
938     symbol *sym;
939     int i;
940
941     if (!op)
942         return ;
943
944     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
945
946     /* if this a literal */
947     if (IS_OP_LITERAL(op)) {
948         op->aop = aop = newAsmop(AOP_LIT);
949         aop->aopu.aop_lit = op->operand.valOperand;
950         aop->size = getSize(operandType(op));
951         return;
952     }
953
954     {
955       sym_link *type = operandType(op);
956 #if 0
957       if(IS_PTR_CONST(type))
958 #else
959       if(IS_CODEPTR(type))
960 #endif
961         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
962     }
963
964     /* if already has a asmop then continue */
965     if (op->aop)
966         return ;
967
968     /* if the underlying symbol has a aop */
969     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
970       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
971         op->aop = OP_SYMBOL(op)->aop;
972         return;
973     }
974
975     /* if this is a true symbol */
976     if (IS_TRUE_SYMOP(op)) {
977         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
978       op->aop = aopForSym(ic, op, result);
979       return ;
980     }
981
982     /* this is a temporary : this has
983     only four choices :
984     a) register
985     b) spillocation
986     c) rematerialize
987     d) conditional
988     e) can be a return use only */
989
990     sym = OP_SYMBOL(op);
991
992     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
993     /* if the type is a conditional */
994     if (sym->regType == REG_CND) {
995         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
996         aop->size = 0;
997         return;
998     }
999
1000     /* if it is spilt then two situations
1001     a) is rematerialize
1002     b) has a spill location */
1003     if (sym->isspilt || sym->nRegs == 0) {
1004
1005 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1006       DEBUGpic16_emitcode(";","%d",__LINE__);
1007         /* rematerialize it NOW */
1008         if (sym->remat) {
1009
1010             sym->aop = op->aop = aop = aopForRemat (op, result);
1011             return;
1012         }
1013
1014 #if 1
1015         if (sym->accuse) {
1016             int i;
1017             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1018             aop->size = getSize(sym->type);
1019             for ( i = 0 ; i < 1 ; i++ ) {
1020                 aop->aopu.aop_str[i] = accUse[i];
1021 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1022             }
1023             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1024             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1025             return;
1026         }
1027 #endif
1028
1029 #if 1
1030         if (sym->ruonly) {
1031           /*
1032           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1033           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1034           //pic16_allocDirReg (IC_LEFT(ic));
1035           aop->size = getSize(sym->type);
1036           */
1037
1038           unsigned i;
1039
1040           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1041           aop->size = getSize(sym->type);
1042           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1043             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1044
1045           DEBUGpic16_emitcode(";","%d",__LINE__);
1046           return;
1047         }
1048 #endif
1049         /* else spill location  */
1050         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1051             /* force a new aop if sizes differ */
1052             sym->usl.spillLoc->aop = NULL;
1053         }
1054
1055 #if 0
1056         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1057                             __FUNCTION__,__LINE__,
1058                             sym->usl.spillLoc->rname,
1059                             sym->rname, sym->usl.spillLoc->offset);
1060 #endif
1061
1062         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1063         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1064           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1065           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1066                                                   getSize(sym->type),
1067                                                   sym->usl.spillLoc->offset, op);
1068         } else if (getSize(sym->type) <= 1) {
1069           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1070           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1071           assert (getSize(sym->type) <= 1);
1072           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1073           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1074         } else {
1075           /* We need some kind of dummy area for getSize(sym->type) byte,
1076            * use WREG for all storage locations.
1077            * XXX: This only works if we are implementing a `dummy read',
1078            *      the stored value will not be retrievable...
1079            *      See #1503234 for a case requiring this. */
1080           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1081           aop->size = getSize(sym->type);
1082           for ( i = 0 ; i < aop->size ;i++)
1083             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1084         }
1085         aop->size = getSize(sym->type);
1086
1087         return;
1088     }
1089
1090     {
1091       sym_link *type = operandType(op);
1092 #if 0
1093       if(IS_PTR_CONST(type))
1094 #else
1095       if(IS_CODEPTR(type))
1096 #endif
1097         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1098     }
1099
1100     /* must be in a register */
1101     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1102     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1103     aop->size = sym->nRegs;
1104     for ( i = 0 ; i < sym->nRegs ;i++)
1105         aop->aopu.aop_reg[i] = sym->regs[i];
1106 }
1107
1108 /*-----------------------------------------------------------------*/
1109 /* pic16_freeAsmop - free up the asmop given to an operand               */
1110 /*----------------------------------------------------------------*/
1111 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1112 {
1113     asmop *aop ;
1114
1115     if (!op)
1116         aop = aaop;
1117     else
1118         aop = op->aop;
1119
1120     if (!aop)
1121         return ;
1122
1123     if (aop->freed)
1124         goto dealloc;
1125
1126     aop->freed = 1;
1127
1128 #if 1
1129     switch (aop->type) {
1130         case AOP_STA:
1131           {
1132             int i;
1133
1134               /* we must store the result on stack */
1135               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1136                 // operands on stack are accessible via "FSR2 + index" with index
1137                 // starting at 2 for arguments and growing from 0 downwards for
1138                 // local variables (index == 0 is not assigned so we add one here)
1139                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1140                 if (soffs <= 0) {
1141                   assert (soffs < 0);
1142                   soffs++;
1143                 } // if
1144                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1145                 for(i=0;i<aop->size;i++) {
1146                   /* initialise for stack access via frame pointer */
1147                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1148                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1149                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1150                 }
1151
1152                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1153               }
1154
1155               if(!_G.resDirect) {
1156                 for(i=0;i<aop->size;i++) {
1157                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1158
1159                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1160                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1161 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1162                   }
1163                 }
1164
1165                 {
1166                   regs *sr;
1167
1168                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1169                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1170                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1171                       deleteSetItem( &_G.sregsAllocSet, sr );
1172                     }
1173                 }
1174               }
1175               _G.resDirect = 0;
1176           }
1177           break;
1178 #if 0
1179         case AOP_STK :
1180         {
1181             int sz = aop->size;
1182             int stk = aop->aopu.aop_stk + aop->size;
1183             bitVectUnSetBit(ic->rUsed,R0_IDX);
1184             bitVectUnSetBit(ic->rUsed,R1_IDX);
1185
1186             getFreePtr(ic,&aop,FALSE);
1187
1188             if (options.stack10bit)
1189             {
1190                 /* I'm not sure what to do here yet... */
1191                 /* #STUB */
1192                 fprintf(stderr,
1193                         "*** Warning: probably generating bad code for "
1194                         "10 bit stack mode.\n");
1195             }
1196
1197             if (stk) {
1198                 pic16_emitcode ("mov","a,_bp");
1199                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1200                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1201             } else {
1202                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1203             }
1204
1205             while (sz--) {
1206                 pic16_emitcode("pop","acc");
1207                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1208                 if (!sz) break;
1209                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1210             }
1211             op->aop = aop;
1212             pic16_freeAsmop(op,NULL,ic,TRUE);
1213             if (_G.r0Pushed) {
1214                 pic16_emitcode("pop","ar0");
1215                 _G.r0Pushed--;
1216             }
1217
1218             if (_G.r1Pushed) {
1219                 pic16_emitcode("pop","ar1");
1220                 _G.r1Pushed--;
1221             }
1222         }
1223 #endif
1224
1225     }
1226 #endif
1227
1228 dealloc:
1229     /* all other cases just dealloc */
1230     if (op ) {
1231         op->aop = NULL;
1232         if (IS_SYMOP(op)) {
1233             OP_SYMBOL(op)->aop = NULL;
1234             /* if the symbol has a spill */
1235             if (SPIL_LOC(op))
1236                 SPIL_LOC(op)->aop = NULL;
1237         }
1238     }
1239 }
1240
1241 /*-----------------------------------------------------------------*/
1242 /* pic16_aopGet - for fetching value of the aop                          */
1243 /*-----------------------------------------------------------------*/
1244 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1245 {
1246     char *s = buffer ;
1247     char *rs;
1248
1249     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1250
1251     /* offset is greater than size then zero */
1252     if (offset > (aop->size - 1) &&
1253         aop->type != AOP_LIT)
1254         return zero;
1255
1256     /* depending on type */
1257     switch (aop->type) {
1258     case AOP_DIR:
1259       if (offset) {
1260         sprintf(s,"(%s + %d)",
1261                 aop->aopu.aop_dir,
1262                 offset);
1263         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1264       } else
1265             sprintf(s,"%s",aop->aopu.aop_dir);
1266         rs = Safe_calloc(1,strlen(s)+1);
1267         strcpy(rs,s);
1268         return rs;
1269
1270     case AOP_REG:
1271       return aop->aopu.aop_reg[offset]->name;
1272
1273     case AOP_CRY:
1274       return aop->aopu.aop_dir;
1275
1276     case AOP_ACC:
1277         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1278 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1279 //        assert( 0 );
1280 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1281         rs = Safe_strdup("WREG");
1282         return (rs);
1283
1284     case AOP_LIT:
1285         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1286         rs = Safe_calloc(1,strlen(s)+1);
1287         strcpy(rs,s);
1288         return rs;
1289
1290     case AOP_STR:
1291         aop->coff = offset ;
1292
1293 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1294 //          dname)
1295 //          return "acc";
1296         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1297           aop->type = AOP_ACC;
1298           return Safe_strdup("_WREG");
1299         }
1300         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1301
1302         return aop->aopu.aop_str[offset];
1303
1304     case AOP_PCODE:
1305       {
1306         pCodeOp *pcop = aop->aopu.pcop;
1307         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1308         if(pcop->name) {
1309           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1310           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1311           if (offset) {
1312             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1313           } else {
1314             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1315           }
1316         } else
1317           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1318
1319       }
1320       rs = Safe_calloc(1,strlen(s)+1);
1321       strcpy(rs,s);
1322       return rs;
1323
1324 #if 0
1325     case AOP_PAGED:
1326       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1327       if (offset) {
1328         sprintf(s,"(%s + %d)",
1329                 aop->aopu.aop_dir,
1330                 offset);
1331       } else
1332             sprintf(s,"%s",aop->aopu.aop_dir);
1333       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1334       rs = Safe_calloc(1,strlen(s)+1);
1335       strcpy(rs,s);
1336       return rs;
1337 #endif
1338
1339     case AOP_STA:
1340         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1341         return (rs);
1342
1343     case AOP_STK:
1344 //        pCodeOp *pcop = aop->aop
1345         break;
1346
1347     }
1348
1349     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1350     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1351            "aopget got unsupported aop->type");
1352     exit(0);
1353 }
1354
1355
1356
1357 /* lock has the following meaning: When allocating temporary registers
1358  * for stack variables storage, the value of the temporary register is
1359  * saved on stack. Its value is restored at the end. This procedure is
1360  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1361  * a possibility that before a call to pic16_aopOp, a temporary register
1362  * is allocated for a while and it is freed after some time, this will
1363  * mess the stack and values will not be restored properly. So use lock=1
1364  * to allocate temporary registers used internally by the programmer, and
1365  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1366  * to inform the compiler developer about a possible bug. This is an internal
1367  * feature for developing the compiler -- VR */
1368
1369 int _TempReg_lock = 0;
1370 /*-----------------------------------------------------------------*/
1371 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *pic16_popGetTempReg(int lock)
1374 {
1375   pCodeOp *pcop=NULL;
1376   symbol *cfunc;
1377
1378 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1379     if(_TempReg_lock) {
1380 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1381     }
1382
1383     _TempReg_lock += lock;
1384
1385     cfunc = currFunc;
1386     currFunc = NULL;
1387
1388     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1389     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1390       PCOR(pcop)->r->wasUsed=1;
1391       PCOR(pcop)->r->isFree=0;
1392
1393       /* push value on stack */
1394       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1395     }
1396
1397     currFunc = cfunc;
1398
1399   return pcop;
1400 }
1401
1402 /*-----------------------------------------------------------------*/
1403 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1404 /*                           is not part of f, but don't save if   */
1405 /*                           inside v                              */
1406 /*-----------------------------------------------------------------*/
1407 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1408 {
1409   pCodeOp *pcop=NULL;
1410   symbol *cfunc;
1411   int i;
1412
1413 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1414
1415     if(_TempReg_lock) {
1416 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1417     }
1418
1419     _TempReg_lock += lock;
1420
1421     cfunc = currFunc;
1422     currFunc = NULL;
1423
1424     i = bitVectFirstBit(f);
1425     while(i < 128) {
1426
1427       /* bypass registers that are used by function */
1428       if(!bitVectBitValue(f, i)) {
1429
1430         /* bypass registers that are already allocated for stack access */
1431         if(!bitVectBitValue(v, i))  {
1432
1433 //          debugf("getting register rIdx = %d\n", i);
1434           /* ok, get the operand */
1435           pcop = pic16_newpCodeOpReg( i );
1436
1437           /* should never by NULL */
1438           assert( pcop != NULL );
1439
1440
1441           /* sanity check */
1442           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1443             int found=0;
1444
1445               PCOR(pcop)->r->wasUsed=1;
1446               PCOR(pcop)->r->isFree=0;
1447
1448
1449               {
1450                 regs *sr;
1451
1452                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1453
1454                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1455                       /* already used in previous steps, break */
1456                       found=1;
1457                       break;
1458                     }
1459                   }
1460               }
1461
1462               /* caller takes care of the following */
1463 //              bitVectSetBit(v, i);
1464
1465               if(!found) {
1466                 /* push value on stack */
1467                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1468                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1469               }
1470
1471             break;
1472           }
1473         }
1474       }
1475       i++;
1476     }
1477
1478     currFunc = cfunc;
1479
1480   return pcop;
1481 }
1482
1483
1484 /*-----------------------------------------------------------------*/
1485 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1486 /*-----------------------------------------------------------------*/
1487 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1488 {
1489   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1490
1491   _TempReg_lock -= lock;
1492
1493   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1494     PCOR(pcop)->r->isFree = 1;
1495
1496     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1497   }
1498 }
1499 /*-----------------------------------------------------------------*/
1500 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1501 /*-----------------------------------------------------------------*/
1502 pCodeOp *pic16_popGetLabel(int key)
1503 {
1504
1505   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1506
1507   if(key>max_key)
1508     max_key = key;
1509
1510   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1511 }
1512
1513 /*-----------------------------------------------------------------*/
1514 /* pic16_popCopyReg - copy a pcode operator                              */
1515 /*-----------------------------------------------------------------*/
1516 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1517 {
1518   pCodeOpReg *pcor;
1519
1520   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1521   memcpy (pcor, pc, sizeof (pCodeOpReg));
1522   pcor->r->wasUsed = 1;
1523
1524   //pcor->pcop.type = pc->pcop.type;
1525   if(pc->pcop.name) {
1526     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1527       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1528   } else
1529     pcor->pcop.name = NULL;
1530
1531   //pcor->r = pc->r;
1532   //pcor->rIdx = pc->rIdx;
1533   //pcor->r->wasUsed=1;
1534   //pcor->instance = pc->instance;
1535
1536 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1537
1538   return PCOP(pcor);
1539 }
1540
1541 /*-----------------------------------------------------------------*/
1542 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1543 /*-----------------------------------------------------------------*/
1544 pCodeOp *pic16_popGetLit(int lit)
1545 {
1546   return pic16_newpCodeOpLit(lit);
1547 }
1548
1549 /* Allow for 12 bit literals (LFSR x, <here!>). */
1550 pCodeOp *pic16_popGetLit12(int lit)
1551 {
1552   return pic16_newpCodeOpLit12(lit);
1553 }
1554
1555 /*-----------------------------------------------------------------*/
1556 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1557 /*-----------------------------------------------------------------*/
1558 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1559 {
1560   return pic16_newpCodeOpLit2(lit, arg2);
1561 }
1562
1563
1564 /*-----------------------------------------------------------------*/
1565 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1566 /*-----------------------------------------------------------------*/
1567 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1568 {
1569   return pic16_newpCodeOpImmd(name, offset,index, 0);
1570 }
1571
1572
1573 /*-----------------------------------------------------------------*/
1574 /* pic16_popGet - asm operator to pcode operator conversion              */
1575 /*-----------------------------------------------------------------*/
1576 pCodeOp *pic16_popGetWithString(char *str)
1577 {
1578   pCodeOp *pcop;
1579
1580
1581   if(!str) {
1582     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1583     exit (1);
1584   }
1585
1586   pcop = pic16_newpCodeOp(str,PO_STR);
1587
1588   return pcop;
1589 }
1590
1591 /*-----------------------------------------------------------------*/
1592 /* pic16_popRegFromString -                                        */
1593 /*-----------------------------------------------------------------*/
1594 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1595 {
1596
1597   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1598   pcop->type = PO_DIR;
1599
1600   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1601   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1602
1603   if(!str)
1604     str = "BAD_STRING";
1605
1606   pcop->name = Safe_calloc(1,strlen(str)+1);
1607   strcpy(pcop->name,str);
1608
1609   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1610
1611   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1612 //  PCOR(pcop)->r->wasUsed = 1;
1613
1614   /* make sure that register doesn't exist,
1615    * and operand isn't NULL
1616    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1617   if((PCOR(pcop)->r == NULL)
1618     && (op)
1619     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1620 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1621 //              __FUNCTION__, __LINE__, str, size, offset);
1622
1623     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1624     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1625
1626   }
1627   PCOR(pcop)->instance = offset;
1628
1629   return pcop;
1630 }
1631
1632 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1633 {
1634   pCodeOp *pcop;
1635
1636 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1637 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1638
1639         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1640         PCOR(pcop)->rIdx = rIdx;
1641         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1642         if(!PCOR(pcop)->r)
1643                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1644
1645         PCOR(pcop)->r->isFree = 0;
1646         PCOR(pcop)->r->wasUsed = 1;
1647
1648         pcop->type = PCOR(pcop)->r->pc_type;
1649
1650   return pcop;
1651 }
1652
1653 /*---------------------------------------------------------------------------------*/
1654 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1655 /*                 VR 030601                                                       */
1656 /*---------------------------------------------------------------------------------*/
1657 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1658 {
1659   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1660         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1661   return PCOP(pcop2);
1662 }
1663
1664
1665
1666 /*--------------------------------------------------------------------------------.-*/
1667 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1668 /*                  VR 030601 , adapted by Hans Dorn                                */
1669 /*--------------------------------------------------------------------------------.-*/
1670 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1671 {
1672   pCodeOp2 *pcop2;
1673   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1674   return PCOP(pcop2);
1675 }
1676
1677 /*---------------------------------------------------------------------------------*/
1678 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1679 /*                     movff instruction                                           */
1680 /*---------------------------------------------------------------------------------*/
1681 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1682 {
1683   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1684         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1685
1686   return PCOP(pcop2);
1687 }
1688
1689
1690 /*-----------------------------------------------------------------*/
1691 /* pic16_popGet - asm operator to pcode operator conversion              */
1692 /*-----------------------------------------------------------------*/
1693 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1694 {
1695 //  char *s = buffer ;
1696 //  char *rs;
1697   pCodeOp *pcop;
1698
1699     FENTRY2;
1700
1701       /* offset is greater than size then zero */
1702
1703 //    if (offset > (aop->size - 1) &&
1704 //        aop->type != AOP_LIT)
1705 //      return NULL;  //zero;
1706
1707     /* depending on type */
1708     switch (aop->type) {
1709                 case AOP_STA:
1710                         /* pCodeOp is already allocated from aopForSym */
1711                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1712                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1713                         return (pcop);
1714
1715                 case AOP_ACC:
1716                         {
1717                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
1718
1719                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1720
1721                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1722
1723                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1724                                 PCOR(pcop)->rIdx = rIdx;
1725                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1726                                 PCOR(pcop)->r->wasUsed=1;
1727                                 PCOR(pcop)->r->isFree=0;
1728
1729                                 PCOR(pcop)->instance = offset;
1730                                 pcop->type = PCOR(pcop)->r->pc_type;
1731 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1732                                 return pcop;
1733
1734
1735 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1736 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1737
1738 //      assert( 0 );
1739                         }
1740
1741     case AOP_DIR:
1742       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1743       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1744
1745 #if 0
1746     case AOP_PAGED:
1747       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1748       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1749 #endif
1750
1751     case AOP_REG:
1752       {
1753         int rIdx;
1754
1755 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
1756 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
1757         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1758
1759         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1760
1761         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1762 //      pcop->type = PO_GPR_REGISTER;
1763         PCOR(pcop)->rIdx = rIdx;
1764         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1765         PCOR(pcop)->r->wasUsed=1;
1766         PCOR(pcop)->r->isFree=0;
1767
1768         PCOR(pcop)->instance = offset;
1769         pcop->type = PCOR(pcop)->r->pc_type;
1770
1771         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1772 //      rs = aop->aopu.aop_reg[offset]->name;
1773 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1774         return pcop;
1775       }
1776
1777     case AOP_CRY:
1778         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1779
1780       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1781       PCOR(pcop)->instance = offset;
1782       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1783       //if(PCOR(pcop)->r == NULL)
1784       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1785       return pcop;
1786
1787     case AOP_LIT:
1788         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1789       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1790
1791     case AOP_STR:
1792       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1793       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1794
1795       /*
1796       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1797       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1798       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1799       pcop->type = PCOR(pcop)->r->pc_type;
1800       pcop->name = PCOR(pcop)->r->name;
1801
1802       return pcop;
1803       */
1804
1805     case AOP_PCODE:
1806       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1807                           __LINE__,
1808                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1809       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1810       switch( aop->aopu.pcop->type ) {
1811         case PO_DIR: PCOR(pcop)->instance += offset; break;
1812         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1813         case PO_WREG:
1814             assert (offset==0);
1815             break;
1816         default:
1817           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1818           assert( 0 );  /* should never reach here */;
1819       }
1820       return pcop;
1821     }
1822
1823     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1824            "pic16_popGet got unsupported aop->type");
1825     exit(0);
1826 }
1827 /*-----------------------------------------------------------------*/
1828 /* pic16_aopPut - puts a string for a aop                                */
1829 /*-----------------------------------------------------------------*/
1830 void pic16_aopPut (asmop *aop, char *s, int offset)
1831 {
1832     char *d = buffer ;
1833     symbol *lbl ;
1834
1835     return;
1836
1837     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1838
1839     if (aop->size && offset > ( aop->size - 1)) {
1840         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1841                "pic16_aopPut got offset > aop->size");
1842         exit(0);
1843     }
1844
1845     /* will assign value to value */
1846     /* depending on where it is ofcourse */
1847     switch (aop->type) {
1848     case AOP_DIR:
1849       if (offset) {
1850         sprintf(d,"(%s + %d)",
1851                 aop->aopu.aop_dir,offset);
1852         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1853
1854       } else
1855             sprintf(d,"%s",aop->aopu.aop_dir);
1856
1857         if (strcmp(d,s)) {
1858           DEBUGpic16_emitcode(";","%d",__LINE__);
1859           if(strcmp(s,"W"))
1860             pic16_emitcode("movf","%s,w",s);
1861           pic16_emitcode("movwf","%s",d);
1862
1863           if(strcmp(s,"W")) {
1864             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1865             if(offset >= aop->size) {
1866               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1867               break;
1868             } else
1869               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1870           }
1871
1872           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1873
1874
1875         }
1876         break;
1877
1878     case AOP_REG:
1879       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1880         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1881           /*
1882             if (*s == '@'           ||
1883                 strcmp(s,"r0") == 0 ||
1884                 strcmp(s,"r1") == 0 ||
1885                 strcmp(s,"r2") == 0 ||
1886                 strcmp(s,"r3") == 0 ||
1887                 strcmp(s,"r4") == 0 ||
1888                 strcmp(s,"r5") == 0 ||
1889                 strcmp(s,"r6") == 0 ||
1890                 strcmp(s,"r7") == 0 )
1891                 pic16_emitcode("mov","%s,%s  ; %d",
1892                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1893             else
1894           */
1895
1896           if(strcmp(s,"W")==0 )
1897             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1898
1899           pic16_emitcode("movwf","%s",
1900                    aop->aopu.aop_reg[offset]->name);
1901
1902           if(strcmp(s,zero)==0) {
1903             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1904
1905           } else if(strcmp(s,"W")==0) {
1906             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907             pcop->type = PO_GPR_REGISTER;
1908
1909             PCOR(pcop)->rIdx = -1;
1910             PCOR(pcop)->r = NULL;
1911
1912             DEBUGpic16_emitcode(";","%d",__LINE__);
1913             pcop->name = Safe_strdup(s);
1914             pic16_emitpcode(POC_MOVFW,pcop);
1915             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1916           } else if(strcmp(s,one)==0) {
1917             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1918             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1919           } else {
1920             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1921           }
1922         }
1923         break;
1924
1925     case AOP_STK:
1926         if (strcmp(s,"a") == 0)
1927             pic16_emitcode("push","acc");
1928         else
1929             pic16_emitcode("push","%s",s);
1930
1931         break;
1932
1933     case AOP_CRY:
1934         /* if bit variable */
1935         if (!aop->aopu.aop_dir) {
1936             pic16_emitcode("clr","a");
1937             pic16_emitcode("rlc","a");
1938         } else {
1939             if (s == zero)
1940                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1941             else
1942                 if (s == one)
1943                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1944                 else
1945                     if (!strcmp(s,"c"))
1946                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1947                     else {
1948                         lbl = newiTempLabel(NULL);
1949
1950                         if (strcmp(s,"a")) {
1951                             MOVA(s);
1952                         }
1953                         pic16_emitcode("clr","c");
1954                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1955                         pic16_emitcode("cpl","c");
1956                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1957                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1958                     }
1959         }
1960         break;
1961
1962     case AOP_STR:
1963         aop->coff = offset;
1964         if (strcmp(aop->aopu.aop_str[offset],s))
1965             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1966         break;
1967
1968     case AOP_ACC:
1969         aop->coff = offset;
1970         if (!offset && (strcmp(s,"acc") == 0))
1971             break;
1972
1973         if (strcmp(aop->aopu.aop_str[offset],s))
1974             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1975         break;
1976
1977     default :
1978         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1979 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1980 //             "pic16_aopPut got unsupported aop->type");
1981 //      exit(0);
1982     }
1983
1984 }
1985
1986 /*-----------------------------------------------------------------*/
1987 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
1988 /*-----------------------------------------------------------------*/
1989 void pic16_mov2w (asmop *aop, int offset)
1990 {
1991   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1992
1993   if(pic16_isLitAop(aop))
1994     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1995   else
1996     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1997 }
1998
1999 void pic16_mov2w_volatile (asmop *aop)
2000 {
2001   int i;
2002
2003   if(!pic16_isLitAop(aop)) {
2004     // may need to protect this from the peepholer -- this is not nice but works...
2005     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2006     for (i = 0; i < aop->size; i++) {
2007       if (i > 0) {
2008         pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2009       } // if
2010       pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2011     } // for
2012     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2013   }
2014 }
2015
2016 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2017 {
2018   if(pic16_isLitAop(src)) {
2019     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2020     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2021   } else {
2022     if(pic16_sameRegsOfs(src, dst, offset))return;
2023     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2024                       pic16_popGet(dst, offset)));
2025   }
2026 }
2027
2028 static void pic16_movLit2f(pCodeOp *pc, int lit)
2029 {
2030   if (0 == (lit & 0x00ff))
2031   {
2032     pic16_emitpcode (POC_CLRF, pc);
2033   } else if (0xff == (lit & 0x00ff))
2034   {
2035     pic16_emitpcode (POC_SETF, pc);
2036   } else {
2037     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2038     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2039   }
2040 }
2041
2042 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2043 {
2044   if(pic16_isLitAop(src)) {
2045     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2046     pic16_emitpcode(POC_MOVWF, dst);
2047   } else {
2048     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2049   }
2050 }
2051
2052 void pic16_testStackOverflow(void)
2053 {
2054 #define GSTACK_TEST_NAME        "_gstack_test"
2055
2056   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2057
2058   {
2059     symbol *sym;
2060
2061       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2062       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2063 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2064       checkAddSym(&externs, sym);
2065   }
2066
2067 }
2068
2069 /* push pcop into stack */
2070 void pic16_pushpCodeOp(pCodeOp *pcop)
2071 {
2072 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2073   if (pcop->type == PO_LITERAL) {
2074     pic16_emitpcode(POC_MOVLW, pcop);
2075     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2076   } else {
2077     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2078   }
2079   if(pic16_options.gstack)
2080     pic16_testStackOverflow();
2081
2082 }
2083
2084 /* pop pcop from stack */
2085 void pic16_poppCodeOp(pCodeOp *pcop)
2086 {
2087   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2088   if(pic16_options.gstack)
2089     pic16_testStackOverflow();
2090 }
2091
2092
2093 /*-----------------------------------------------------------------*/
2094 /* pushw - pushes wreg to stack                                    */
2095 /*-----------------------------------------------------------------*/
2096 void pushw(void)
2097 {
2098   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2099   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2100   if(pic16_options.gstack)
2101     pic16_testStackOverflow();
2102 }
2103
2104
2105 /*-----------------------------------------------------------------*/
2106 /* pushaop - pushes aop to stack                                   */
2107 /*-----------------------------------------------------------------*/
2108 void pushaop(asmop *aop, int offset)
2109 {
2110   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2111
2112   if(_G.resDirect)return;
2113
2114   if(pic16_isLitAop(aop)) {
2115     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2116     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2117   } else {
2118     pic16_emitpcode(POC_MOVFF,
2119       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2120   }
2121
2122   if(pic16_options.gstack)
2123     pic16_testStackOverflow();
2124 }
2125
2126 /*-----------------------------------------------------------------*/
2127 /* popaop - pops aop from stack                                    */
2128 /*-----------------------------------------------------------------*/
2129 void popaop(asmop *aop, int offset)
2130 {
2131   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2132   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2133   if(pic16_options.gstack)
2134     pic16_testStackOverflow();
2135 }
2136
2137 void popaopidx(asmop *aop, int offset, int index)
2138 {
2139   int ofs=1;
2140
2141     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2142
2143     if(STACK_MODEL_LARGE)ofs++;
2144
2145     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2146     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2147     if(pic16_options.gstack)
2148       pic16_testStackOverflow();
2149 }
2150
2151 /*-----------------------------------------------------------------*/
2152 /* pic16_getDataSize - get the operand data size                         */
2153 /*-----------------------------------------------------------------*/
2154 int pic16_getDataSize(operand *op)
2155 {
2156     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2157
2158
2159     return AOP_SIZE(op);
2160
2161     // tsd- in the pic port, the genptr size is 1, so this code here
2162     // fails. ( in the 8051 port, the size was 4).
2163 #if 0
2164     int size;
2165     size = AOP_SIZE(op);
2166     if (size == GPTRSIZE)
2167     {
2168         sym_link *type = operandType(op);
2169         if (IS_GENPTR(type))
2170         {
2171             /* generic pointer; arithmetic operations
2172              * should ignore the high byte (pointer type).
2173              */
2174             size--;
2175     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2176         }
2177     }
2178     return size;
2179 #endif
2180 }
2181
2182 /*-----------------------------------------------------------------*/
2183 /* pic16_outAcc - output Acc                                             */
2184 /*-----------------------------------------------------------------*/
2185 void pic16_outAcc(operand *result)
2186 {
2187   int size,offset;
2188   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2189   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2190
2191
2192   size = pic16_getDataSize(result);
2193   if(size){
2194     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2195     size--;
2196     offset = 1;
2197     /* unsigned or positive */
2198     while(size--)
2199       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2200   }
2201
2202 }
2203
2204 /*-----------------------------------------------------------------*/
2205 /* pic16_outBitC - output a bit C                                  */
2206 /*                 Move to result the value of Carry flag -- VR    */
2207 /*-----------------------------------------------------------------*/
2208 void pic16_outBitC(operand *result)
2209 {
2210   int i;
2211
2212     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2213
2214     /* if the result is bit */
2215     if (AOP_TYPE(result) == AOP_CRY) {
2216         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2217         pic16_aopPut(AOP(result),"c",0);
2218     } else {
2219
2220         i = AOP_SIZE(result);
2221         while(i--) {
2222                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2223         }
2224         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2225     }
2226 }
2227
2228 /*-----------------------------------------------------------------*/
2229 /* pic16_outBitOp - output a bit from Op                           */
2230 /*                 Move to result the value of set/clr op -- VR    */
2231 /*-----------------------------------------------------------------*/
2232 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2233 {
2234   int i;
2235
2236     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2237
2238     /* if the result is bit */
2239     if (AOP_TYPE(result) == AOP_CRY) {
2240         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2241         pic16_aopPut(AOP(result),"c",0);
2242     } else {
2243
2244         i = AOP_SIZE(result);
2245         while(i--) {
2246                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2247         }
2248         pic16_emitpcode(POC_RRCF, pcop);
2249         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2250     }
2251 }
2252
2253 /*-----------------------------------------------------------------*/
2254 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2255 /*-----------------------------------------------------------------*/
2256 void pic16_toBoolean(operand *oper)
2257 {
2258     int size = AOP_SIZE(oper) - 1;
2259     int offset = 1;
2260
2261     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2262
2263     if ( AOP_TYPE(oper) != AOP_ACC) {
2264       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2265     }
2266     while (size--) {
2267       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2268     }
2269 }
2270
2271 /*-----------------------------------------------------------------*/
2272 /* genUminusFloat - unary minus for floating points                */
2273 /*-----------------------------------------------------------------*/
2274 static void genUminusFloat(operand *op,operand *result)
2275 {
2276   int size ,offset =0 ;
2277
2278     FENTRY;
2279     /* for this we just need to flip the
2280     first it then copy the rest in place */
2281     size = AOP_SIZE(op);
2282     assert( size == AOP_SIZE(result) );
2283
2284     while(size--) {
2285       pic16_mov2f(AOP(result), AOP(op), offset);
2286       offset++;
2287     }
2288
2289     /* toggle the MSB's highest bit */
2290     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2291 }
2292
2293 /*-----------------------------------------------------------------*/
2294 /* genUminus - unary minus code generation                         */
2295 /*-----------------------------------------------------------------*/
2296 static void genUminus (iCode *ic)
2297 {
2298   int size, i;
2299   sym_link *optype, *rtype;
2300   symbol *label;
2301   int needLabel=0;
2302
2303     FENTRY;
2304
2305     /* assign asmops */
2306     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2307     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2308
2309     /* if both in bit space then special case */
2310     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2311       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2312
2313         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2314         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2315         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2316         goto release;
2317     }
2318
2319     optype = operandType(IC_LEFT(ic));
2320     rtype = operandType(IC_RESULT(ic));
2321
2322
2323     /* if float then do float stuff */
2324     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2325       if(IS_FIXED(optype))
2326         debugf("implement fixed16x16 type\n", 0);
2327
2328         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2329         goto release;
2330     }
2331
2332     /* otherwise subtract from zero by taking the 2's complement */
2333     size = AOP_SIZE(IC_LEFT(ic));
2334     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2335     label = newiTempLabel ( NULL );
2336
2337     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2338       for (i=size-1; i > 0; i--) {
2339         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2340       } // for
2341       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2342       for (i=1; i < size; i++) {
2343         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2344         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2345       } // for
2346     } else {
2347       for (i=size-1; i >= 0; i--) {
2348         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2349         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2350       } // for
2351       if (size > 1) {
2352         for (i=0; i < size-2; i++) {
2353           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2354           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2355         } // for
2356         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2357       } // if
2358       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2359     }
2360     if (needLabel)
2361       pic16_emitpLabel (label->key);
2362
2363 release:
2364     /* release the aops */
2365     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2366     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2367 }
2368
2369 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2370 {
2371   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2372     pic16_emitpcode(POC_MOVFW, src);
2373     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2374   } else {
2375     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2376         src, pic16_popGet(AOP(op), offset)));
2377   }
2378 }
2379
2380
2381 /*-----------------------------------------------------------------*/
2382 /* assignResultValue - assign results to oper, rescall==1 is       */
2383 /*                     called from genCall() or genPcall()         */
2384 /*-----------------------------------------------------------------*/
2385 static void assignResultValue(operand * oper, int res_size, int rescall)
2386 {
2387   int size = AOP_SIZE(oper);
2388   int offset=0;
2389
2390     FENTRY2;
2391 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2392     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2393
2394     if(rescall) {
2395       /* assign result from a call/pcall function() */
2396
2397       /* function results are stored in a special order,
2398        * see top of file with Function return policy, or manual */
2399
2400       if(size <= 4) {
2401         /* 8-bits, result in WREG */
2402         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2403
2404         if(size > 1 && res_size > 1) {
2405           /* 16-bits, result in PRODL:WREG */
2406           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2407         }
2408
2409         if(size > 2 && res_size > 2) {
2410           /* 24-bits, result in PRODH:PRODL:WREG */
2411           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2412         }
2413
2414         if(size > 3 && res_size > 3) {
2415           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2416           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2417         }
2418
2419         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2420
2421       } else {
2422         /* >32-bits, result on stack, and FSR0 points to beginning.
2423          * Fix stack when done */
2424         /* FIXME FIXME */
2425 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2426         while (size--) {
2427 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2428 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2429
2430           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2431           GpsuedoStkPtr++;
2432         }
2433
2434         /* fix stack */
2435         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2436         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2437         if(STACK_MODEL_LARGE) {
2438           emitSKPNC;
2439           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2440         }
2441       }
2442     } else {
2443       int areg = 0;             /* matching argument register */
2444
2445 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2446       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2447
2448
2449       /* its called from genReceive (probably) -- VR */
2450       /* I hope this code will not be called from somewhere else in the future!
2451        * We manually set the pseudo stack pointer in genReceive. - dw
2452        */
2453       if(!GpsuedoStkPtr && _G.useWreg) {
2454 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2455
2456         /* The last byte in the assignment is in W */
2457         if(areg <= GpsuedoStkPtr) {
2458           size--;
2459           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2460           offset++;
2461 //          debugf("receive from WREG\n", 0);
2462         }
2463         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2464       }
2465 //      GpsuedoStkPtr++;
2466       _G.stack_lat = AOP_SIZE(oper)-1;
2467
2468       while (size) {
2469         size--;
2470         GpsuedoStkPtr++;
2471         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2472 //        debugf("receive from STACK\n", 0);
2473         offset++;
2474       }
2475     }
2476 }
2477
2478
2479 /*-----------------------------------------------------------------*/
2480 /* genIpush - generate code for pushing this gets a little complex */
2481 /*-----------------------------------------------------------------*/
2482 static void genIpush (iCode *ic)
2483 {
2484 //  int size, offset=0;
2485
2486   FENTRY;
2487   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2488
2489   if(ic->parmPush) {
2490     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2491
2492     /* send to stack as normal */
2493     addSet(&_G.sendSet,ic);
2494 //    addSetHead(&_G.sendSet,ic);
2495     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2496   }
2497
2498
2499 #if 0
2500     int size, offset = 0 ;
2501     char *l;
2502
2503
2504     /* if this is not a parm push : ie. it is spill push
2505     and spill push is always done on the local stack */
2506     if (!ic->parmPush) {
2507
2508         /* and the item is spilt then do nothing */
2509         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2510             return ;
2511
2512         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2513         size = AOP_SIZE(IC_LEFT(ic));
2514         /* push it on the stack */
2515         while(size--) {
2516             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2517             if (*l == '#') {
2518                 MOVA(l);
2519                 l = "acc";
2520             }
2521             pic16_emitcode("push","%s",l);
2522         }
2523         return ;
2524     }
2525
2526     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2527 #endif
2528 }
2529
2530 /*-----------------------------------------------------------------*/
2531 /* genIpop - recover the registers: can happen only for spilling   */
2532 /*-----------------------------------------------------------------*/
2533 static void genIpop (iCode *ic)
2534 {
2535   FENTRY;
2536   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2537 #if 0
2538     int size,offset ;
2539
2540
2541     /* if the temp was not pushed then */
2542     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2543         return ;
2544
2545     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2546     size = AOP_SIZE(IC_LEFT(ic));
2547     offset = (size-1);
2548     while (size--)
2549         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2550                                    FALSE,TRUE));
2551
2552     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2553 #endif
2554 }
2555
2556 static int wparamCmp(void *p1, void *p2)
2557 {
2558   return (!strcmp((char *)p1, (char *)p2));
2559 }
2560
2561 int inWparamList(char *s)
2562 {
2563   return isinSetWith(wparamList, s, wparamCmp);
2564 }
2565
2566
2567 /*-----------------------------------------------------------------*/
2568 /* genCall - generates a call statement                            */
2569 /*-----------------------------------------------------------------*/
2570 static void genCall (iCode *ic)
2571 {
2572   sym_link *ftype;
2573   int stackParms=0;
2574   int use_wreg=0;
2575   int inwparam=0;
2576   char *fname;
2577
2578     FENTRY;
2579
2580     ftype = OP_SYM_TYPE(IC_LEFT(ic));
2581     /* if caller saves & we have not saved then */
2582 //    if (!ic->regsSaved)
2583 //      saveRegisters(ic);
2584
2585         /* initialise stackParms for IPUSH pushes */
2586 //      stackParms = psuedoStkPtr;
2587 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2588     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2589     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2590
2591 #if 0
2592     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2593 #endif
2594
2595     /* if send set is not empty the assign */
2596     if (_G.sendSet) {
2597       iCode *sic;
2598       int psuedoStkPtr=-1;
2599       int firstTimeThruLoop = 1;
2600
2601
2602         /* reverse sendSet if function is not reentrant */
2603         if(!IFFUNC_ISREENT(ftype))
2604           _G.sendSet = reverseSet(_G.sendSet);
2605
2606         /* First figure how many parameters are getting passed */
2607         stackParms = 0;
2608         use_wreg = 0;
2609
2610         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2611           int size;
2612 //          int offset = 0;
2613
2614             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2615             size = AOP_SIZE(IC_LEFT(sic));
2616
2617             stackParms += size;
2618
2619             /* pass the last byte through WREG */
2620             if(inwparam) {
2621
2622               while (size--) {
2623                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2624                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2625                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2626
2627                 if(!firstTimeThruLoop) {
2628                   /* If this is not the first time we've been through the loop
2629                    * then we need to save the parameter in a temporary
2630                    * register. The last byte of the last parameter is
2631                    * passed in W. */
2632
2633                   pushw();
2634 //                  --psuedoStkPtr;             // sanity check
2635                   use_wreg = 1;
2636                 }
2637
2638                 firstTimeThruLoop=0;
2639
2640                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2641
2642 //                offset++;
2643               }
2644             } else {
2645               /* all arguments are passed via stack */
2646               use_wreg = 0;
2647
2648               while (size--) {
2649                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2650                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2651                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2652
2653 //                pushaop(AOP(IC_LEFT(sic)), size);
2654                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2655
2656                 if(!_G.resDirect)
2657                   pushw();
2658               }
2659             }
2660
2661             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2662           }
2663
2664           if(inwparam) {
2665             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2666               pushw();  /* save last parameter to stack if functions has varargs */
2667               use_wreg = 0;
2668             } else
2669               use_wreg = 1;
2670           } else use_wreg = 0;
2671
2672           _G.stackRegSet = _G.sendSet;
2673           _G.sendSet = NULL;
2674     }
2675
2676     /* make the call */
2677     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2678
2679     GpsuedoStkPtr=0;
2680
2681     /* if we need to assign a result value */
2682     if ((IS_ITEMP(IC_RESULT(ic))
2683           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2684               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2685         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2686
2687       _G.accInUse++;
2688       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2689       _G.accInUse--;
2690
2691       /* Must not assign an 8-bit result to a 16-bit variable;
2692        * this would use (used...) the uninitialized PRODL! */
2693       /* FIXME: Need a proper way to obtain size of function result type,
2694        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2695       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2696
2697       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2698                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2699
2700       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2701     }
2702
2703     if(!stackParms && ic->parmBytes) {
2704       stackParms = ic->parmBytes;
2705     }
2706
2707     stackParms -= use_wreg;
2708
2709     if(stackParms>0) {
2710       if(stackParms == 1) {
2711         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
2712       } else {
2713         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2714         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2715       }
2716       if(STACK_MODEL_LARGE) {
2717         emitSKPNC;
2718         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
2719       }
2720     }
2721
2722 #if 0
2723     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2724 #endif
2725
2726     /* adjust the stack for parameters if required */
2727 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2728
2729 #if 0
2730       /* if register bank was saved then pop them */
2731       if (ic->bankSaved)
2732         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2733
2734       /* if we hade saved some registers then unsave them */
2735       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2736         unsaveRegisters (ic);
2737 #endif
2738 }
2739
2740
2741
2742 /*-----------------------------------------------------------------*/
2743 /* genPcall - generates a call by pointer statement                */
2744 /*            new version, created from genCall - HJD              */
2745 /*-----------------------------------------------------------------*/
2746 static void genPcall (iCode *ic)
2747 {
2748   sym_link *fntype;
2749   int stackParms=0;
2750   symbol *retlbl = newiTempLabel(NULL);
2751   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2752
2753     FENTRY;
2754
2755     fntype = operandType( IC_LEFT(ic) )->next;
2756
2757     /* if send set is not empty the assign */
2758     if (_G.sendSet) {
2759       iCode *sic;
2760       int psuedoStkPtr=-1;
2761
2762       /* reverse sendSet if function is not reentrant */
2763       if(!IFFUNC_ISREENT(fntype))
2764         _G.sendSet = reverseSet(_G.sendSet);
2765
2766       stackParms = 0;
2767
2768       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2769         int size;
2770
2771           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2772           size = AOP_SIZE(IC_LEFT(sic));
2773           stackParms += size;
2774
2775           /* all parameters are passed via stack, since WREG is clobbered
2776            * by the calling sequence */
2777           while (size--) {
2778             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2779             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2780             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2781
2782             pic16_mov2w (AOP(IC_LEFT(sic)), size);
2783             pushw();
2784           }
2785
2786           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2787       }
2788
2789       _G.stackRegSet = _G.sendSet;
2790       _G.sendSet = NULL;
2791     }
2792
2793     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2794
2795     // push return address
2796     // push $ on return stack, then replace with retlbl
2797
2798     /* Thanks to Thorsten Klose for pointing out that the following
2799      * snippet should be interrupt safe */
2800     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2801     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2802
2803     pic16_emitpcodeNULLop(POC_PUSH);
2804
2805     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2806     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2807     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2808     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2809     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2810     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2811
2812
2813     /* restore interrupt control register */
2814     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2815     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2816
2817     /* make the call by writing the pointer into pc */
2818     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2819     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2820
2821     // note: MOVFF to PCL not allowed
2822     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2823     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2824
2825
2826     /* return address is here: (X) */
2827     pic16_emitpLabelFORCE(retlbl->key);
2828
2829     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2830
2831     GpsuedoStkPtr=0;
2832     /* if we need assign a result value */
2833     if ((IS_ITEMP(IC_RESULT(ic))
2834           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2835               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2836         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2837
2838       _G.accInUse++;
2839       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2840       _G.accInUse--;
2841
2842       /* FIXME: Need proper way to obtain the function result's type.
2843        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2844       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2845
2846       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2847               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2848
2849       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2850     }
2851
2852 //    stackParms -= use_wreg;
2853
2854     if(stackParms>0) {
2855       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2856       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2857       if(STACK_MODEL_LARGE) {
2858         emitSKPNC;
2859         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2860       }
2861     }
2862 }
2863
2864 /*-----------------------------------------------------------------*/
2865 /* resultRemat - result  is rematerializable                       */
2866 /*-----------------------------------------------------------------*/
2867 static int resultRemat (iCode *ic)
2868 {
2869   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2870   if (SKIP_IC(ic) || ic->op == IFX)
2871     return 0;
2872
2873   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2874     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2875     if (sym->remat && !POINTER_SET(ic))
2876       return 1;
2877   }
2878
2879   return 0;
2880 }
2881
2882 #if 0
2883 /*-----------------------------------------------------------------*/
2884 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2885 /*-----------------------------------------------------------------*/
2886 static bool inExcludeList(char *s)
2887 {
2888   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2889     int i =0;
2890
2891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2892     if (options.excludeRegs[i] &&
2893     STRCASECMP(options.excludeRegs[i],"none") == 0)
2894         return FALSE ;
2895
2896     for ( i = 0 ; options.excludeRegs[i]; i++) {
2897         if (options.excludeRegs[i] &&
2898         STRCASECMP(s,options.excludeRegs[i]) == 0)
2899             return TRUE;
2900     }
2901     return FALSE ;
2902 }
2903 #endif
2904
2905 /*-----------------------------------------------------------------*/
2906 /* genFunction - generated code for function entry                 */
2907 /*-----------------------------------------------------------------*/
2908 static void genFunction (iCode *ic)
2909 {
2910   symbol *sym;
2911   sym_link *ftype;
2912
2913     FENTRY;
2914     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2915
2916     pic16_labelOffset += (max_key+4);
2917     max_key=0;
2918     GpsuedoStkPtr=0;
2919     _G.nRegsSaved = 0;
2920
2921     ftype = operandType(IC_LEFT(ic));
2922     sym = OP_SYMBOL(IC_LEFT(ic));
2923
2924     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2925       /* create an absolute section at the interrupt vector:
2926        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2927       symbol *asym;
2928       char asymname[128];
2929       pBlock *apb;
2930
2931 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2932
2933         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2934           sprintf(asymname, "ivec_%s", sym->name);
2935         else
2936           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2937
2938         /* when an interrupt is declared as naked, do not emit the special
2939          * wrapper segment at vector address. The user should take care for
2940          * this instead. -- VR */
2941
2942         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2943           asym = newSymbol(asymname, 0);
2944           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2945           pic16_addpBlock( apb );
2946
2947           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2948           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2949           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2950           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2951           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2952
2953           /* mark the end of this tiny function */
2954           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2955         } else {
2956           sprintf(asymname, "%s", sym->rname);
2957         }
2958
2959         {
2960           absSym *abSym;
2961
2962             abSym = Safe_calloc(1, sizeof(absSym));
2963             strcpy(abSym->name, asymname);
2964
2965             switch( FUNC_INTNO(sym->type) ) {
2966               case 0: abSym->address = 0x000000; break;
2967               case 1: abSym->address = 0x000008; break;
2968               case 2: abSym->address = 0x000018; break;
2969
2970               default:
2971 //                fprintf(stderr, "no interrupt number is given\n");
2972                 abSym->address = -1; break;
2973             }
2974
2975             /* relocate interrupt vectors if needed */
2976             if(abSym->address != -1)
2977               abSym->address += pic16_options.ivt_loc;
2978
2979             addSet(&absSymSet, abSym);
2980         }
2981     }
2982
2983     /* create the function header */
2984     pic16_emitcode(";","-----------------------------------------");
2985     pic16_emitcode(";"," function %s",sym->name);
2986     pic16_emitcode(";","-----------------------------------------");
2987
2988     /* prevent this symbol from being emitted as 'extern' */
2989     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2990
2991     pic16_emitcode("","%s:",sym->rname);
2992     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2993
2994     {
2995       absSym *ab;
2996
2997         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2998           if(!strcmp(ab->name, sym->rname)) {
2999             pic16_pBlockConvert2Absolute(pb);
3000             break;
3001           }
3002         }
3003     }
3004
3005     if(IFFUNC_ISNAKED(ftype)) {
3006       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3007       return;
3008     }
3009
3010     /* if critical function then turn interrupts off */
3011     if (IFFUNC_ISCRITICAL(ftype)) {
3012       //pic16_emitcode("clr","ea");
3013     }
3014
3015     currFunc = sym;             /* update the currFunc symbol */
3016     _G.fregsUsed = sym->regsUsed;
3017     _G.sregsAlloc = newBitVect(128);
3018
3019
3020     /* if this is an interrupt service routine then
3021      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3022     if (IFFUNC_ISISR(sym->type)) {
3023         _G.usefastretfie = 1;   /* use shadow registers by default */
3024
3025         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3026         if(!FUNC_ISSHADOWREGS(sym->type)) {
3027           /* do not save WREG,STATUS,BSR for high priority interrupts
3028            * because they are stored in the hardware shadow registers already */
3029           _G.usefastretfie = 0;
3030           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3031           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3032           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3033         }
3034
3035         /* these should really be optimized somehow, because not all
3036          * interrupt handlers modify them */
3037         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3038         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3039         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3040         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3041         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3042         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3043
3044 //        pic16_pBlockConvert2ISR(pb);
3045     }
3046
3047     /* emit code to setup stack frame if user enabled,
3048      * and function is not main() */
3049
3050 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3051     if(strcmp(sym->name, "main")) {
3052       if(0
3053         || !options.ommitFramePtr
3054 //        || sym->regsUsed
3055         || IFFUNC_ARGS(sym->type)
3056         || FUNC_HASSTACKPARM(sym->etype)
3057         ) {
3058         /* setup the stack frame */
3059         if(STACK_MODEL_LARGE)
3060           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3061         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3062
3063         if(STACK_MODEL_LARGE)
3064           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3065         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3066       }
3067     }
3068
3069     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3070           && sym->stack) {
3071
3072       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3073
3074       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3075       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3076       emitSKPC;
3077       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3078     }
3079
3080     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3081       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3082         _G.useWreg = 0;
3083       else
3084         _G.useWreg = 1;
3085     } else
3086       _G.useWreg = 0;
3087
3088     /* if callee-save to be used for this function
3089      * then save the registers being used in this function */
3090 //    if (IFFUNC_CALLEESAVES(sym->type))
3091     if(strcmp(sym->name, "main")) {
3092       int i;
3093
3094         /* if any registers used */
3095         if (sym->regsUsed) {
3096                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3097
3098           if(!xinst) {
3099             /* save the registers used */
3100             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3101             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3102               if (bitVectBitValue(sym->regsUsed,i)) {
3103 #if 0
3104                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3105 #endif
3106                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3107                 _G.nRegsSaved++;
3108
3109                 if(!pic16_regWithIdx(i)->wasUsed) {
3110                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3111                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3112                   pic16_regWithIdx(i)->wasUsed = 1;
3113                 }
3114               }
3115             }
3116           } else {
3117
3118             /* xinst */
3119             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3120             for(i=0;i<sym->regsUsed->size;i++) {
3121               if(bitVectBitValue(sym->regsUsed, i)) {
3122                 _G.nRegsSaved++;
3123               }
3124             }
3125
3126 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3127           }
3128
3129           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3130
3131         }
3132     }
3133
3134     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3135 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3136 }
3137
3138 /*-----------------------------------------------------------------*/
3139 /* genEndFunction - generates epilogue for functions               */
3140 /*-----------------------------------------------------------------*/
3141 static void genEndFunction (iCode *ic)
3142 {
3143   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3144
3145     FENTRY;
3146
3147     if(IFFUNC_ISNAKED(sym->type)) {
3148       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3149       return;
3150     }
3151
3152     _G.stack_lat = 0;
3153
3154     /* add code for ISCRITICAL */
3155     if(IFFUNC_ISCRITICAL(sym->type)) {
3156       /* if critical function, turn on interrupts */
3157
3158       /* TODO: add code here -- VR */
3159     }
3160
3161 //    sym->regsUsed = _G.fregsUsed;
3162
3163     /* now we need to restore the registers */
3164     /* if any registers used */
3165
3166     /* first restore registers that might be used for stack access */
3167     if(_G.sregsAllocSet) {
3168     regs *sr;
3169
3170       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3171       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3172         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3173       }
3174     }
3175
3176     if (strcmp(sym->name, "main") && sym->regsUsed) {
3177       int i;
3178
3179         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3180         /* restore registers used */
3181         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3182         for ( i = sym->regsUsed->size; i >= 0; i--) {
3183           if (bitVectBitValue(sym->regsUsed,i)) {
3184             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3185             _G.nRegsSaved--;
3186           }
3187         }
3188         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3189     }
3190
3191
3192
3193     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3194           && sym->stack) {
3195       if (sym->stack == 1) {
3196         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3197         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3198       } else {
3199         // we have to add more than one...
3200         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3201         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3202         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3203         emitSKPNC;
3204         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3205         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3206         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3207       }
3208     }
3209
3210     if(strcmp(sym->name, "main")) {
3211       if(0
3212         || !options.ommitFramePtr
3213 //        || sym->regsUsed
3214         || IFFUNC_ARGS(sym->type)
3215         || FUNC_HASSTACKPARM(sym->etype)
3216         ) {
3217         /* restore stack frame */
3218         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3219         if(STACK_MODEL_LARGE)
3220           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3221       }
3222     }
3223
3224     _G.useWreg = 0;
3225
3226     if (IFFUNC_ISISR(sym->type)) {
3227       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3228       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3229       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3230       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3231       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3232       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3233
3234       if(!FUNC_ISSHADOWREGS(sym->type)) {
3235         /* do not restore interrupt vector for WREG,STATUS,BSR
3236          * for high priority interrupt, see genFunction */
3237         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3238         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3239         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3240       }
3241 //      _G.interruptvector = 0;         /* sanity check */
3242
3243
3244       /* if debug then send end of function */
3245 /*      if (options.debug && currFunc)  */
3246       if (currFunc) {
3247         debugFile->writeEndFunction (currFunc, ic, 1);
3248       }
3249
3250       if(_G.usefastretfie)
3251         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3252       else
3253         pic16_emitpcodeNULLop(POC_RETFIE);
3254
3255       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3256
3257       _G.usefastretfie = 0;
3258       return;
3259     }
3260
3261     if (IFFUNC_ISCRITICAL(sym->type)) {
3262       pic16_emitcode("setb","ea");
3263     }
3264
3265     /* if debug then send end of function */
3266     if (currFunc) {
3267       debugFile->writeEndFunction (currFunc, ic, 1);
3268     }
3269
3270     /* insert code to restore stack frame, if user enabled it
3271      * and function is not main() */
3272
3273
3274     pic16_emitpcodeNULLop(POC_RETURN);
3275
3276     /* Mark the end of a function */
3277     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3278 }
3279
3280
3281 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3282 {
3283   unsigned long lit=1;
3284   operand *op;
3285
3286     op = IC_LEFT(ic);
3287
3288     // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3289     if(AOP_TYPE(op) == AOP_LIT) {
3290       if(!IS_FLOAT(operandType( op ))) {
3291         lit = ulFromVal (AOP(op)->aopu.aop_lit);
3292       } else {
3293         union {
3294           unsigned long lit_int;
3295           float lit_float;
3296         } info;
3297
3298         /* take care if literal is a float */
3299         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3300         lit = info.lit_int;
3301       }
3302     }
3303
3304     if (AOP_TYPE(op) == AOP_LIT) {
3305       /* FIXME: broken for
3306        *   char __at(0x456) foo;
3307        *   return &foo;
3308        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3309       pic16_movLit2f(dest, (lit >> (8ul*offset)));
3310     } else if (AOP_TYPE(op) == AOP_PCODE
3311                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3312       /* char *s= "aaa"; return s; */
3313       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3314        *      that the generic pointer is interpreted correctly
3315        *      as referring to __code space, but this is fragile! */
3316       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3317       /* XXX: should check that dest != WREG */
3318       pic16_emitpcode(POC_MOVWF, dest);
3319     } else {
3320       if(dest->type == PO_WREG && (offset == 0)) {
3321         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3322         return;
3323       }
3324       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3325     }
3326 }
3327
3328 /*-----------------------------------------------------------------*/
3329 /* genRet - generate code for return statement                     */
3330 /*-----------------------------------------------------------------*/
3331 static void genRet (iCode *ic)
3332 {
3333   int size;
3334   operand *left;
3335
3336     FENTRY;
3337         /* if we have no return value then
3338          * just generate the "ret" */
3339
3340         if (!IC_LEFT(ic))
3341                 goto jumpret;
3342
3343         /* we have something to return then
3344          * move the return value into place */
3345         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3346         size = AOP_SIZE(IC_LEFT(ic));
3347
3348         if(size <= 4) {
3349           if(size>3)
3350             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3351
3352           if(size>2)
3353             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3354
3355           if(size>1)
3356             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3357
3358           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3359
3360         } else {
3361                 /* >32-bits, setup stack and FSR0 */
3362                 while (size--) {
3363 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3364 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3365
3366                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3367
3368 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3369                         GpsuedoStkPtr++;
3370                 }
3371
3372                 /* setup FSR0 */
3373                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3374                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3375
3376                 if(STACK_MODEL_LARGE) {
3377                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3378                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3379                 } else {
3380                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3381                 }
3382         }
3383
3384         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3385
3386 jumpret:
3387         /* generate a jump to the return label
3388          * if the next is not the return statement */
3389         if (!(ic->next && ic->next->op == LABEL
3390                 && IC_LABEL(ic->next) == returnLabel)) {
3391
3392                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3393                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3394         }
3395 }
3396
3397 /*-----------------------------------------------------------------*/
3398 /* genLabel - generates a label                                    */
3399 /*-----------------------------------------------------------------*/
3400 static void genLabel (iCode *ic)
3401 {
3402   FENTRY;
3403
3404   /* special case never generate */
3405   if (IC_LABEL(ic) == entryLabel)
3406     return ;
3407
3408   pic16_emitpLabel(IC_LABEL(ic)->key);
3409 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3410 }
3411
3412 /*-----------------------------------------------------------------*/
3413 /* genGoto - generates a goto                                      */
3414 /*-----------------------------------------------------------------*/
3415 //tsd
3416 static void genGoto (iCode *ic)
3417 {
3418   FENTRY;
3419   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3420 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3421 }
3422
3423
3424 /*-----------------------------------------------------------------*/
3425 /* genMultbits :- multiplication of bits                           */
3426 /*-----------------------------------------------------------------*/
3427 static void genMultbits (operand *left,
3428                          operand *right,
3429                          operand *result)
3430 {
3431   FENTRY;
3432
3433   if(!pic16_sameRegs(AOP(result),AOP(right)))
3434     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3435
3436   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3437   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3438   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3439
3440 }
3441
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genMultOneByte : 8 bit multiplication & division                */
3445 /*-----------------------------------------------------------------*/
3446 static void genMultOneByte (operand *left,
3447                             operand *right,
3448                             operand *result)
3449 {
3450
3451   FENTRY;
3452   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3453   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3454
3455   /* (if two literals, the value is computed before) */
3456   /* if one literal, literal on the right */
3457   if (AOP_TYPE(left) == AOP_LIT){
3458     operand *t = right;
3459     right = left;
3460     left = t;
3461   }
3462
3463         /* size is already checked in genMult == 1 */
3464 //      size = AOP_SIZE(result);
3465
3466         if (AOP_TYPE(right) == AOP_LIT){
3467                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3468                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3469                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3470                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3471         } else {
3472                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3473                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3474                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3475                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3476         }
3477
3478         pic16_genMult8X8_n (left, right,result);
3479 }
3480
3481 #if 0
3482 /*-----------------------------------------------------------------*/
3483 /* genMultOneWord : 16 bit multiplication                          */
3484 /*-----------------------------------------------------------------*/
3485 static void genMultOneWord (operand *left,
3486                             operand *right,
3487                             operand *result)
3488 {
3489   FENTRY;
3490   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3491   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3492
3493   /* (if two literals, the value is computed before)
3494    * if one literal, literal on the right */
3495   if (AOP_TYPE(left) == AOP_LIT){
3496     operand *t = right;
3497     right = left;
3498     left = t;
3499   }
3500
3501   /* size is checked already == 2 */
3502 //  size = AOP_SIZE(result);
3503
3504   if (AOP_TYPE(right) == AOP_LIT) {
3505     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3506       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3507       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3508       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3509   } else {
3510     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3511       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3512       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3513       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3514   }
3515
3516   pic16_genMult16X16_16(left, right,result);
3517 }
3518 #endif
3519
3520 #if 0
3521 /*-----------------------------------------------------------------*/
3522 /* genMultOneLong : 32 bit multiplication                          */
3523 /*-----------------------------------------------------------------*/
3524 static void genMultOneLong (operand *left,
3525                             operand *right,
3526                             operand *result)
3527 {
3528   FENTRY;
3529   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3530   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3531
3532   /* (if two literals, the value is computed before)
3533    * if one literal, literal on the right */
3534   if (AOP_TYPE(left) == AOP_LIT){
3535     operand *t = right;
3536     right = left;
3537     left = t;
3538   }
3539
3540   /* size is checked already == 4 */
3541 //  size = AOP_SIZE(result);
3542
3543   if (AOP_TYPE(right) == AOP_LIT) {
3544     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3545         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3546         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3547         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3548   } else {
3549     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3550         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3551         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3552         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3553   }
3554
3555   pic16_genMult32X32_32(left, right,result);
3556 }
3557 #endif
3558
3559
3560
3561 /*-----------------------------------------------------------------*/
3562 /* genMult - generates code for multiplication                     */
3563 /*-----------------------------------------------------------------*/
3564 static void genMult (iCode *ic)
3565 {
3566   operand *left = IC_LEFT(ic);
3567   operand *right = IC_RIGHT(ic);
3568   operand *result= IC_RESULT(ic);
3569
3570     FENTRY;
3571         /* assign the amsops */
3572         pic16_aopOp (left,ic,FALSE);
3573         pic16_aopOp (right,ic,FALSE);
3574         pic16_aopOp (result,ic,TRUE);
3575
3576         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3577
3578         /* special cases first *
3579         * both are bits */
3580         if (AOP_TYPE(left) == AOP_CRY
3581                 && AOP_TYPE(right)== AOP_CRY) {
3582                 genMultbits(left,right,result);
3583           goto release ;
3584         }
3585
3586         /* if both are of size == 1 */
3587         if(AOP_SIZE(left) == 1
3588                 && AOP_SIZE(right) == 1) {
3589                 genMultOneByte(left,right,result);
3590           goto release ;
3591         }
3592
3593 #if 0
3594         /* if both are of size == 2 */
3595         if(AOP_SIZE(left) == 2
3596                 && AOP_SIZE(right) == 2) {
3597                 genMultOneWord(left, right, result);
3598           goto release;
3599         }
3600
3601         /* if both are of size == 4 */
3602         if(AOP_SIZE(left) == 4
3603                 && AOP_SIZE(right) == 4) {
3604                 genMultOneLong(left, right, result);
3605           goto release;
3606         }
3607 #endif
3608
3609         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3610         assert( !"Multiplication should have been transformed into function call!" );
3611
3612         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3613
3614
3615         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3616         /* should have been converted to function call */
3617         assert(0) ;
3618
3619 release :
3620         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3621         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3622         pic16_freeAsmop(result,NULL,ic,TRUE);
3623 }
3624
3625 #if 0
3626 /*-----------------------------------------------------------------*/
3627 /* genDivbits :- division of bits                                  */
3628 /*-----------------------------------------------------------------*/
3629 static void genDivbits (operand *left,
3630                         operand *right,
3631                         operand *result)
3632 {
3633   char *l;
3634
3635     FENTRY;
3636     /* the result must be bit */
3637     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3638     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3639
3640     MOVA(l);
3641
3642     pic16_emitcode("div","ab");
3643     pic16_emitcode("rrc","a");
3644     pic16_aopPut(AOP(result),"c",0);
3645 }
3646
3647 /*-----------------------------------------------------------------*/
3648 /* genDivOneByte : 8 bit division                                  */
3649 /*-----------------------------------------------------------------*/
3650 static void genDivOneByte (operand *left,
3651                            operand *right,
3652                            operand *result)
3653 {
3654   sym_link *opetype = operandType(result);
3655   char *l ;
3656   symbol *lbl ;
3657   int size,offset;
3658
3659         /* result = divident / divisor
3660          * - divident may be a register or a literal,
3661          * - divisor may be a register or a literal,
3662          * so there are 3 cases (literal / literal is optimized
3663          * by the front-end) to handle.
3664          * In addition we must handle signed and unsigned, which
3665          * result in 6 final different cases -- VR */
3666
3667     FENTRY;
3668
3669     size = AOP_SIZE(result) - 1;
3670     offset = 1;
3671     /* signed or unsigned */
3672     if (SPEC_USIGN(opetype)) {
3673       pCodeOp *pct1,    /* count */
3674                 *pct2,  /* reste */
3675                 *pct3;  /* temp */
3676       symbol *label1, *label2, *label3;;
3677
3678
3679         /* unsigned is easy */
3680
3681         pct1 = pic16_popGetTempReg(1);
3682         pct2 = pic16_popGetTempReg(1);
3683         pct3 = pic16_popGetTempReg(1);
3684
3685         label1 = newiTempLabel(NULL);
3686         label2 = newiTempLabel(NULL);
3687         label3 = newiTempLabel(NULL);
3688
3689         /* the following algorithm is extracted from divuint.c */
3690
3691         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3692         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3693
3694         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3695
3696         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3697
3698         pic16_emitpLabel(label1->key);
3699
3700         emitCLRC;
3701         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3702
3703
3704         emitCLRC;
3705         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3706
3707
3708         emitSKPNC;
3709         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3710
3711         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3712         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3713
3714         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3715         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3716         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3717
3718         pic16_emitpLabel( label3->key );
3719         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3720         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3721
3722
3723
3724         pic16_emitpLabel(label2->key);
3725         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3726         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3727         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3728
3729         /* result is in wreg */
3730         if(AOP_TYPE(result) != AOP_ACC)
3731                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3732
3733         pic16_popReleaseTempReg( pct3, 1);
3734         pic16_popReleaseTempReg( pct2, 1);
3735         pic16_popReleaseTempReg( pct1, 1);
3736
3737         return ;
3738     }
3739
3740     /* signed is a little bit more difficult */
3741
3742     /* save the signs of the operands */
3743     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3744     MOVA(l);
3745     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3746     pic16_emitcode("push","acc"); /* save it on the stack */
3747
3748     /* now sign adjust for both left & right */
3749     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
3750     MOVA(l);
3751     lbl = newiTempLabel(NULL);
3752     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3753     pic16_emitcode("cpl","a");
3754     pic16_emitcode("inc","a");
3755     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3756     pic16_emitcode("mov","b,a");
3757
3758     /* sign adjust left side */
3759     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
3760     MOVA(l);
3761
3762     lbl = newiTempLabel(NULL);
3763     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3764     pic16_emitcode("cpl","a");
3765     pic16_emitcode("inc","a");
3766     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3767
3768     /* now the division */
3769     pic16_emitcode("div","ab");
3770     /* we are interested in the lower order
3771     only */
3772     pic16_emitcode("mov","b,a");
3773     lbl = newiTempLabel(NULL);
3774     pic16_emitcode("pop","acc");
3775     /* if there was an over flow we don't
3776     adjust the sign of the result */
3777     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3778     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3779     CLRC;
3780     pic16_emitcode("clr","a");
3781     pic16_emitcode("subb","a,b");
3782     pic16_emitcode("mov","b,a");
3783     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3784
3785     /* now we are done */
3786     pic16_aopPut(AOP(result),"b",0);
3787     if(size > 0){
3788         pic16_emitcode("mov","c,b.7");
3789         pic16_emitcode("subb","a,acc");
3790     }
3791     while (size--)
3792         pic16_aopPut(AOP(result),"a",offset++);
3793
3794 }
3795 #endif
3796
3797 /*-----------------------------------------------------------------*/
3798 /* genDiv - generates code for division                            */
3799 /*-----------------------------------------------------------------*/
3800 static void genDiv (iCode *ic)
3801 {
3802     operand *left = IC_LEFT(ic);
3803     operand *right = IC_RIGHT(ic);
3804     operand *result= IC_RESULT(ic);
3805     int negated = 0;
3806     int leftVal = 0, rightVal = 0;
3807     int signedLits = 0;
3808     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3809     int op = 0;
3810
3811         /* Division is a very lengthy algorithm, so it is better
3812          * to call support routines than inlining algorithm.
3813          * Division functions written here just in case someone
3814          * wants to inline and not use the support libraries -- VR */
3815
3816     FENTRY;
3817
3818     /* assign the amsops */
3819     pic16_aopOp (left,ic,FALSE);
3820     pic16_aopOp (right,ic,FALSE);
3821     pic16_aopOp (result,ic,TRUE);
3822
3823     if (ic->op == '/')
3824       op = 0;
3825     else if (ic->op == '%')
3826       op = 1;
3827     else
3828       assert( !"invalid operation requested in genDivMod" );
3829
3830     /* get literal values */
3831     if (IS_VALOP(left)) {
3832       leftVal = (int) ulFromVal ( OP_VALUE(left) );
3833       assert( leftVal >= -128 && leftVal < 256 );
3834       if (leftVal < 0) { signedLits++; }
3835     }
3836     if (IS_VALOP(right)) {
3837       rightVal = (int) ulFromVal ( OP_VALUE(right) );
3838       assert( rightVal >= -128 && rightVal < 256 );
3839       if (rightVal < 0) { signedLits++; }
3840     }
3841
3842     /* We should only come here to convert all
3843      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3844      * with exactly one operand being s8_t into
3845      * u8_t x u8_t -> u8_t. All other cases should have been
3846      * turned into calls to support routines beforehand... */
3847     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3848         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3849     {
3850       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3851           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3852       {
3853         /* Both operands are signed or negative, use _divschar
3854          * instead of _divuchar */
3855         pushaop(AOP(right), 0);
3856         pushaop(AOP(left), 0);
3857
3858         /* call _divschar */
3859         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3860
3861         {
3862           symbol *sym;
3863           sym = newSymbol( functions[op][0], 0 );
3864           sym->used++;
3865           strcpy(sym->rname, functions[op][0]);
3866           checkAddSym(&externs, sym);
3867         }
3868
3869         /* assign result */
3870         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3871         if (AOP_SIZE(result) > 1)
3872         {
3873           pic16_emitpcode(POC_MOVFF,
3874               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3875                 pic16_popGet(AOP(result), 1)));
3876           /* sign extend */
3877           pic16_addSign(result, 2, 1);
3878         }
3879
3880         /* clean up stack */
3881         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3882         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3883
3884         goto release;
3885       }
3886
3887       /* push right operand */
3888       if (IS_VALOP(right)) {
3889         if (rightVal < 0) {
3890           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3891           negated++;
3892         } else {
3893           pushaop(AOP(right), 0);
3894         }
3895       } else if (!IS_UNSIGNED(operandType(right))) {
3896         pic16_mov2w(AOP(right), 0);
3897         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3898         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3899         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3900         negated++;
3901       } else {
3902         pushaop(AOP(right), 0);
3903       }
3904
3905       /* push left operand */
3906       if (IS_VALOP(left)) {
3907         if (leftVal < 0) {
3908           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3909           negated++;
3910         } else {
3911           pushaop(AOP(left), 0);
3912         }
3913       } else if (!IS_UNSIGNED(operandType(left))) {
3914         pic16_mov2w(AOP(left),0);
3915         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3916         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3917         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3918         negated++;
3919       } else {
3920         pushaop(AOP(left), 0);
3921       }
3922
3923       /* call _divuchar */
3924       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3925
3926       {
3927         symbol *sym;
3928         sym = newSymbol( functions[op][1], 0 );
3929         sym->used++;
3930         strcpy(sym->rname, functions[op][1]);
3931         checkAddSym(&externs, sym);
3932       }
3933
3934       /* Revert negation(s) from above.
3935        * This is inefficient: if both operands are negative, this
3936        * should not touch WREG. However, determining that exactly
3937        * one operand was negated costs at least 3 instructions,
3938        * so there is nothing to be gained here, is there?
3939        *
3940        * I negate WREG because either operand might share registers with
3941        * result, so assigning first might destroy an operand. */
3942
3943       /* For the modulus operator, (a/b)*b == a shall hold.
3944        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3945        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
3946        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
3947        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
3948        * Only invert the result if the left operand is negative (sigh).
3949        */
3950       if (AOP_SIZE(result) <= 1 || !negated)
3951       {
3952         if (ic->op == '/')
3953         {
3954           if (IS_VALOP(right)) {
3955             if (rightVal < 0) {
3956               /* we negated this operand above */
3957               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3958             }
3959           } else if (!IS_UNSIGNED(operandType(right))) {
3960             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3961             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3962           }
3963         }
3964
3965         if (IS_VALOP(left)) {
3966           if (leftVal < 0) {
3967             /* we negated this operand above */
3968             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3969           }
3970         } else if (!IS_UNSIGNED(operandType(left))) {
3971           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3972           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3973         }
3974
3975         /* Move result to destination. */
3976         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3977
3978         /* Zero-extend:  no operand was signed (or result is just a byte). */
3979         pic16_addSign(result, 1, 0);
3980       } else {
3981         assert( AOP_SIZE(result) > 1 );
3982         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3983         if (ic->op == '/')
3984         {
3985           if (IS_VALOP(right)) {
3986             if (rightVal < 0) {
3987               /* we negated this operand above */
3988               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3989             }
3990           } else if (!IS_UNSIGNED(operandType(right))) {
3991             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3992             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3993           }
3994         }
3995
3996         if (IS_VALOP(left)) {
3997           if (leftVal < 0) {
3998             /* we negated this operand above */
3999             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4000           }
4001         } else if (!IS_UNSIGNED(operandType(left))) {
4002           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4003           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4004         }
4005
4006         /* Move result to destination. */
4007         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4008
4009         /* Negate result if required. */
4010         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4011         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4012
4013         /* Sign-extend. */
4014         pic16_addSign(result, 2, 1);
4015       }
4016
4017       /* clean up stack */
4018       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4019       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4020       goto release;
4021     }
4022
4023 #if 0
4024     /* special cases first */
4025     /* both are bits */
4026     if (AOP_TYPE(left) == AOP_CRY &&
4027         AOP_TYPE(right)== AOP_CRY) {
4028         genDivbits(left,right,result);
4029         goto release ;
4030     }
4031
4032     /* if both are of size == 1 */
4033     if (AOP_SIZE(left) == 1 &&
4034         AOP_SIZE(right) == 1 ) {
4035         genDivOneByte(left,right,result);
4036         goto release ;
4037     }
4038 #endif
4039
4040     /* should have been converted to function call */
4041     assert(0);
4042 release :
4043     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4044     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4045     pic16_freeAsmop(result,NULL,ic,TRUE);
4046 }
4047
4048 #if 0
4049 /*-----------------------------------------------------------------*/
4050 /* genModbits :- modulus of bits                                   */
4051 /*-----------------------------------------------------------------*/
4052 static void genModbits (operand *left,
4053                         operand *right,
4054                         operand *result)
4055 {
4056   char *l;
4057
4058     FENTRY;
4059
4060     werror(W_POSSBUG2, __FILE__, __LINE__);
4061     /* the result must be bit */
4062     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4063     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4064
4065     MOVA(l);
4066
4067     pic16_emitcode("div","ab");
4068     pic16_emitcode("mov","a,b");
4069     pic16_emitcode("rrc","a");
4070     pic16_aopPut(AOP(result),"c",0);
4071 }
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genModOneByte : 8 bit modulus                                   */
4075 /*-----------------------------------------------------------------*/
4076 static void genModOneByte (operand *left,
4077                            operand *right,
4078                            operand *result)
4079 {
4080   sym_link *opetype = operandType(result);
4081   char *l ;
4082   symbol *lbl ;
4083
4084     FENTRY;
4085     werror(W_POSSBUG2, __FILE__, __LINE__);
4086
4087     /* signed or unsigned */
4088     if (SPEC_USIGN(opetype)) {
4089         /* unsigned is easy */
4090         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4091         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4092         MOVA(l);
4093         pic16_emitcode("div","ab");
4094         pic16_aopPut(AOP(result),"b",0);
4095         return ;
4096     }
4097
4098     /* signed is a little bit more difficult */
4099
4100     /* save the signs of the operands */
4101     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4102     MOVA(l);
4103
4104     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4105     pic16_emitcode("push","acc"); /* save it on the stack */
4106
4107     /* now sign adjust for both left & right */
4108     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4109     MOVA(l);
4110
4111     lbl = newiTempLabel(NULL);
4112     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4113     pic16_emitcode("cpl","a");
4114     pic16_emitcode("inc","a");
4115     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4116     pic16_emitcode("mov","b,a");
4117
4118     /* sign adjust left side */
4119     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4120     MOVA(l);
4121
4122     lbl = newiTempLabel(NULL);
4123     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4124     pic16_emitcode("cpl","a");
4125     pic16_emitcode("inc","a");
4126     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4127
4128     /* now the multiplication */
4129     pic16_emitcode("div","ab");
4130     /* we are interested in the lower order
4131     only */
4132     lbl = newiTempLabel(NULL);
4133     pic16_emitcode("pop","acc");
4134     /* if there was an over flow we don't
4135     adjust the sign of the result */
4136     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4137     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4138     CLRC ;
4139     pic16_emitcode("clr","a");
4140     pic16_emitcode("subb","a,b");
4141     pic16_emitcode("mov","b,a");
4142     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4143
4144     /* now we are done */
4145     pic16_aopPut(AOP(result),"b",0);
4146
4147 }
4148 #endif
4149
4150 /*-----------------------------------------------------------------*/
4151 /* genMod - generates code for division                            */
4152 /*-----------------------------------------------------------------*/
4153 static void genMod (iCode *ic)
4154 {
4155   /* Task deferred to genDiv */
4156   genDiv(ic);
4157 #if 0
4158   operand *left = IC_LEFT(ic);
4159   operand *right = IC_RIGHT(ic);
4160   operand *result= IC_RESULT(ic);
4161
4162     FENTRY;
4163
4164     /* assign the amsops */
4165     pic16_aopOp (left,ic,FALSE);
4166     pic16_aopOp (right,ic,FALSE);
4167     pic16_aopOp (result,ic,TRUE);
4168
4169     /* special cases first */
4170     /* both are bits */
4171     if (AOP_TYPE(left) == AOP_CRY &&
4172         AOP_TYPE(right)== AOP_CRY) {
4173         genModbits(left,right,result);
4174         goto release ;
4175     }
4176
4177     /* if both are of size == 1 */
4178     if (AOP_SIZE(left) == 1 &&
4179         AOP_SIZE(right) == 1 ) {
4180         genModOneByte(left,right,result);
4181         goto release ;
4182     }
4183
4184     /* should have been converted to function call */
4185     assert(0);
4186
4187 release :
4188     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4189     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4190     pic16_freeAsmop(result,NULL,ic,TRUE);
4191 #endif
4192 }
4193
4194 /*-----------------------------------------------------------------*/
4195 /* genIfxJump :- will create a jump depending on the ifx           */
4196 /*-----------------------------------------------------------------*/
4197 /*
4198   note: May need to add parameter to indicate when a variable is in bit space.
4199 */
4200 static void genIfxJump (iCode *ic, char *jval)
4201 {
4202   FENTRY;
4203
4204     /* if true label then we jump if condition
4205     supplied is true */
4206     if ( IC_TRUE(ic) ) {
4207
4208         if(strcmp(jval,"a") == 0)
4209           emitSKPZ;
4210         else if (strcmp(jval,"c") == 0)
4211           emitSKPNC;
4212         else {
4213           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4214           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4215         }
4216
4217         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4218         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4219
4220     }
4221     else {
4222         /* false label is present */
4223         if(strcmp(jval,"a") == 0)
4224           emitSKPNZ;
4225         else if (strcmp(jval,"c") == 0)
4226           emitSKPC;
4227         else {
4228           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4229           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4230         }
4231
4232         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4233         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4234
4235     }
4236
4237
4238     /* mark the icode as generated */
4239     ic->generated = 1;
4240 }
4241
4242 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4243 {
4244   FENTRY;
4245
4246     /* if true label then we jump if condition
4247     supplied is true */
4248     if ( IC_TRUE(ic) ) {
4249       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4250       pic16_emitpcode(POC_BTFSC, jop);
4251
4252       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4253       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4254
4255     } else {
4256       /* false label is present */
4257       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4258       pic16_emitpcode(POC_BTFSS, jop);
4259
4260       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4261       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4262     }
4263
4264
4265     /* mark the icode as generated */
4266     ic->generated = 1;
4267 }
4268
4269 #if 0
4270 // not needed ATM
4271
4272 /*-----------------------------------------------------------------*/
4273 /* genSkip                                                         */
4274 /*-----------------------------------------------------------------*/
4275 static void genSkip(iCode *ifx,int status_bit)
4276 {
4277   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4278   if(!ifx)
4279     return;
4280
4281   if ( IC_TRUE(ifx) ) {
4282     switch(status_bit) {
4283     case 'z':
4284       emitSKPNZ;
4285       break;
4286
4287     case 'c':
4288       emitSKPNC;
4289       break;
4290
4291     case 'd':
4292       emitSKPDC;
4293       break;
4294
4295     }
4296
4297     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4298     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4299
4300   } else {
4301
4302     switch(status_bit) {
4303
4304     case 'z':
4305       emitSKPZ;
4306       break;
4307
4308     case 'c':
4309       emitSKPC;
4310       break;
4311
4312     case 'd':
4313       emitSKPDC;
4314       break;
4315     }
4316     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4317     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4318
4319   }
4320
4321 }
4322 #endif
4323
4324 /*-----------------------------------------------------------------*/
4325 /* genSkipc                                                        */
4326 /*-----------------------------------------------------------------*/
4327 static void genSkipc(resolvedIfx *rifx)
4328 {
4329   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4330
4331   if(!rifx)
4332     return;
4333
4334   if(rifx->condition)
4335     emitSKPNC;
4336   else
4337     emitSKPC;
4338
4339   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4340   rifx->generated = 1;
4341 }
4342
4343 /*-----------------------------------------------------------------*/
4344 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4345 /*                  aop (if it's NOT a literal) or from lit (if    */
4346 /*                  aop is a literal)                              */
4347 /*-----------------------------------------------------------------*/
4348 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4349   if (aop->type == AOP_LIT) {
4350     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4351   } else {
4352     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4353   }
4354 }
4355
4356 /*-----------------------------------------------------------------*/
4357 /* genCmp :- greater or less than comparison                       */
4358 /*-----------------------------------------------------------------*/
4359
4360 /* genCmp performs a left < right comparison, stores
4361  * the outcome in result (if != NULL) and generates
4362  * control flow code for the ifx (if != NULL).
4363  *
4364  * This version leaves in sequences like
4365  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4366  * which should be optmized by the peephole
4367  * optimizer - RN 2005-01-01 */
4368 static void genCmp (operand *left,operand *right,
4369                     operand *result, iCode *ifx, int sign)
4370 {
4371   resolvedIfx rIfx;
4372   int size;
4373   int offs;
4374   symbol *templbl;
4375   operand *dummy;
4376   unsigned long lit;
4377   unsigned long mask;
4378   int performedLt;
4379
4380   FENTRY;
4381
4382   assert (left && right);
4383   assert (AOP_SIZE(left) == AOP_SIZE(right));
4384
4385   size = AOP_SIZE(right) - 1;
4386   mask = (0x100UL << (size*8)) - 1;
4387   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4388   performedLt = 1;
4389   templbl = NULL;
4390   lit = 0;
4391
4392   resolveIfx (&rIfx, ifx);
4393
4394   /* handle for special cases */
4395   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4396       return;
4397
4398   /**********************************************************************
4399    * handle bits - bit compares are promoted to int compares seemingly! *
4400    **********************************************************************/
4401 #if 0
4402   // THIS IS COMPLETELY UNTESTED!
4403   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4404     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4405     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4406     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4407
4408     emitSETC;
4409     // 1 < {0,1} is false --> clear C by skipping the next instruction
4410     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4411     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4412     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4413     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4414     emitCLRC; // only skipped for left=0 && right=1
4415
4416     goto correct_result_in_carry;
4417   } // if
4418 #endif
4419
4420   /*************************************************
4421    * make sure that left is register (or the like) *
4422    *************************************************/
4423   if (!isAOP_REGlike(left)) {
4424     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4425     assert (isAOP_LIT(left));
4426     assert (isAOP_REGlike(right));
4427     // swap left and right
4428     // left < right <==> right > left <==> (right >= left + 1)
4429     lit = ulFromVal (AOP(left)->aopu.aop_lit);
4430
4431     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4432       // MAXVALUE < right? always false
4433       if (performedLt) emitCLRC; else emitSETC;
4434       goto correct_result_in_carry;
4435     } // if
4436
4437     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4438     // that's why we handled it above.
4439     lit++;
4440
4441     dummy = left;
4442     left = right;
4443     right = dummy;
4444
4445     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4446   } else if (isAOP_LIT(right)) {
4447     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4448   } // if
4449
4450   assert (isAOP_REGlike(left)); // left must be register or the like
4451   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4452
4453   /*************************************************
4454    * special cases go here                         *
4455    *************************************************/
4456
4457   if (isAOP_LIT(right)) {
4458     if (!sign) {
4459       // unsigned comparison to a literal
4460       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4461       if (lit == 0) {
4462         // unsigned left < 0? always false
4463         if (performedLt) emitCLRC; else emitSETC;
4464         goto correct_result_in_carry;
4465       }
4466     } else {
4467       // signed comparison to a literal
4468       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4469       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4470         // signed left < 0x80000000? always false
4471         if (performedLt) emitCLRC; else emitSETC;
4472         goto correct_result_in_carry;
4473       } else if (lit == 0) {
4474         // compare left < 0; set CARRY if SIGNBIT(left) is set
4475         if (performedLt) emitSETC; else emitCLRC;
4476         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4477         if (performedLt) emitCLRC; else emitSETC;
4478         goto correct_result_in_carry;
4479       }
4480     } // if (!sign)
4481   } // right is literal
4482
4483   /*************************************************
4484    * perform a general case comparison             *
4485    * make sure we get CARRY==1 <==> left >= right  *
4486    *************************************************/
4487   // compare most significant bytes
4488   //DEBUGpc ("comparing bytes at offset %d", size);
4489   if (!sign) {
4490     // unsigned comparison
4491     mov2w_regOrLit (AOP(right), lit, size);
4492     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4493   } else {
4494     // signed comparison
4495     // (add 2^n to both operands then perform an unsigned comparison)
4496     if (isAOP_LIT(right)) {
4497       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4498       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4499
4500       if (litbyte == 0x80) {
4501         // left >= 0x80 -- always true, but more bytes to come
4502         pic16_mov2w (AOP(left), size);
4503         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4504         emitSETC;
4505       } else {
4506         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4507         pic16_mov2w (AOP(left), size);
4508         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4509         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4510       } // if
4511     } else {
4512       /* using PRODL as a temporary register here */
4513       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4514       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4515       pic16_mov2w (AOP(left), size);
4516       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4517       pic16_emitpcode (POC_MOVWF, pctemp);
4518       pic16_mov2w (AOP(right), size);
4519       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4520       pic16_emitpcode (POC_SUBFW, pctemp);
4521       //pic16_popReleaseTempReg(pctemp, 1);
4522     }
4523   } // if (!sign)
4524
4525   // compare remaining bytes (treat as unsigned case from above)
4526   templbl = newiTempLabel ( NULL );
4527   offs = size;
4528   while (offs--) {
4529     //DEBUGpc ("comparing bytes at offset %d", offs);
4530     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4531     mov2w_regOrLit (AOP(right), lit, offs);
4532     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4533   } // while (offs)
4534   pic16_emitpLabel (templbl->key);
4535   goto result_in_carry;
4536
4537 result_in_carry:
4538
4539   /****************************************************
4540    * now CARRY contains the result of the comparison: *
4541    * SUBWF sets CARRY iff                             *
4542    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4543    * (F=left, W=right)                                *
4544    ****************************************************/
4545
4546   if (performedLt) {
4547     if (result && AOP_TYPE(result) != AOP_CRY) {
4548       // value will be stored
4549       emitTOGC;
4550     } else {
4551       // value wil only be used in the following genSkipc()
4552       rIfx.condition ^= 1;
4553     }
4554   } // if
4555
4556 correct_result_in_carry:
4557
4558   // assign result to variable (if neccessary)
4559   if (result && AOP_TYPE(result) != AOP_CRY) {
4560     //DEBUGpc ("assign result");
4561     size = AOP_SIZE(result);
4562     while (size--) {
4563       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4564     } // while
4565     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4566   } // if (result)
4567
4568   // perform conditional jump
4569   if (ifx) {
4570     //DEBUGpc ("generate control flow");
4571     genSkipc (&rIfx);
4572     ifx->generated = 1;
4573   } // if
4574 }
4575
4576 /*-----------------------------------------------------------------*/
4577 /* genCmpGt :- greater than comparison                             */
4578 /*-----------------------------------------------------------------*/
4579 static void genCmpGt (iCode *ic, iCode *ifx)
4580 {
4581   operand *left, *right, *result;
4582   sym_link *letype , *retype;
4583   int sign ;
4584
4585     FENTRY;
4586
4587     left = IC_LEFT(ic);
4588     right= IC_RIGHT(ic);
4589     result = IC_RESULT(ic);
4590
4591     letype = getSpec(operandType(left));
4592     retype =getSpec(operandType(right));
4593     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4594     /* assign the amsops */
4595     pic16_aopOp (left,ic,FALSE);
4596     pic16_aopOp (right,ic,FALSE);
4597     pic16_aopOp (result,ic,TRUE);
4598
4599     genCmp(right, left, result, ifx, sign);
4600
4601     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4602     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4603     pic16_freeAsmop(result,NULL,ic,TRUE);
4604 }
4605
4606 /*-----------------------------------------------------------------*/
4607 /* genCmpLt - less than comparisons                                */
4608 /*-----------------------------------------------------------------*/
4609 static void genCmpLt (iCode *ic, iCode *ifx)
4610 {
4611   operand *left, *right, *result;
4612   sym_link *letype , *retype;
4613   int sign ;
4614
4615     FENTRY;
4616
4617     left = IC_LEFT(ic);
4618     right= IC_RIGHT(ic);
4619     result = IC_RESULT(ic);
4620
4621     letype = getSpec(operandType(left));
4622     retype =getSpec(operandType(right));
4623     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4624
4625     /* assign the amsops */
4626     pic16_aopOp (left,ic,FALSE);
4627     pic16_aopOp (right,ic,FALSE);
4628     pic16_aopOp (result,ic,TRUE);
4629
4630     genCmp(left, right, result, ifx, sign);
4631
4632     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4633     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4634     pic16_freeAsmop(result,NULL,ic,TRUE);
4635 }
4636
4637 /*-----------------------------------------------------------------*/
4638 /* pic16_isLitOp - check if operand has to be treated as literal   */
4639 /*-----------------------------------------------------------------*/
4640 bool pic16_isLitOp(operand *op)
4641 {
4642   return ((AOP_TYPE(op) == AOP_LIT)
4643       || ( (AOP_TYPE(op) == AOP_PCODE)
4644           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4645               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4646 }
4647
4648 /*-----------------------------------------------------------------*/
4649 /* pic16_isLitAop - check if operand has to be treated as literal  */
4650 /*-----------------------------------------------------------------*/
4651 bool pic16_isLitAop(asmop *aop)
4652 {
4653   return ((aop->type == AOP_LIT)
4654       || ( (aop->type == AOP_PCODE)
4655           && ( (aop->aopu.pcop->type == PO_LITERAL)
4656               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4657 }
4658
4659
4660
4661 /*-----------------------------------------------------------------*/
4662 /* genCmpEq - generates code for equal to                          */
4663 /*-----------------------------------------------------------------*/
4664 static void genCmpEq (iCode *ic, iCode *ifx)
4665 {
4666   operand *left, *right, *result;
4667   symbol *falselbl = newiTempLabel(NULL);
4668   symbol *donelbl = newiTempLabel(NULL);
4669
4670   int preserve_result = 0;
4671   int generate_result = 0;
4672   int i=0;
4673   unsigned long lit = -1;
4674
4675   FENTRY;
4676
4677   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4678   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4679   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4680
4681   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4682
4683   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4684     {
4685       werror(W_POSSBUG2, __FILE__, __LINE__);
4686       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4687       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4688       goto release;
4689     }
4690
4691   if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4692     {
4693       operand *tmp = right ;
4694       right = left;
4695       left = tmp;
4696     }
4697
4698   if (AOP_TYPE(right) == AOP_LIT) {
4699     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4700   }
4701
4702   if ( regsInCommon(left, result) || regsInCommon(right, result) )
4703     preserve_result = 1;
4704
4705   if(result && AOP_SIZE(result))
4706     generate_result = 1;
4707
4708   if(generate_result && !preserve_result)
4709     {
4710       for(i = 0; i < AOP_SIZE(result); i++)
4711         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4712     }
4713
4714   assert( AOP_SIZE(left) == AOP_SIZE(right) );
4715   for(i=0; i < AOP_SIZE(left); i++)
4716     {
4717       if(AOP_TYPE(left) != AOP_ACC)
4718         {
4719           if(pic16_isLitOp(left))
4720             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4721           else
4722             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4723         }
4724       if(pic16_isLitOp(right)) {
4725         if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4726           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4727         }
4728       } else
4729         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4730
4731       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4732     }
4733
4734   // result == true
4735
4736   if(generate_result && preserve_result)
4737     {
4738       for(i = 0; i < AOP_SIZE(result); i++)
4739         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4740     }
4741
4742   if(generate_result)
4743     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4744
4745   if(generate_result && preserve_result)
4746     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4747
4748   if(ifx && IC_TRUE(ifx))
4749     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4750
4751   if(ifx && IC_FALSE(ifx))
4752     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4753
4754   pic16_emitpLabel(falselbl->key);
4755
4756   // result == false
4757
4758   if(ifx && IC_FALSE(ifx))
4759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4760
4761   if(generate_result && preserve_result)
4762     {
4763       for(i = 0; i < AOP_SIZE(result); i++)
4764         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4765     }
4766
4767   pic16_emitpLabel(donelbl->key);
4768
4769   if(ifx)
4770     ifx->generated = 1;
4771
4772 release:
4773   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4774   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4775   pic16_freeAsmop(result,NULL,ic,TRUE);
4776
4777 }
4778
4779
4780 #if 0
4781 // old version kept for reference
4782
4783 /*-----------------------------------------------------------------*/
4784 /* genCmpEq - generates code for equal to                          */
4785 /*-----------------------------------------------------------------*/
4786 static void genCmpEq (iCode *ic, iCode *ifx)
4787 {
4788     operand *left, *right, *result;
4789     unsigned long lit = 0L;
4790     int size,offset=0;
4791     symbol *falselbl  = newiTempLabel(NULL);
4792
4793
4794     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4795
4796     if(ifx)
4797       DEBUGpic16_emitcode ("; ifx is non-null","");
4798     else
4799       DEBUGpic16_emitcode ("; ifx is null","");
4800
4801     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4802     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4803     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4804
4805     size = max(AOP_SIZE(left),AOP_SIZE(right));
4806
4807     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4808
4809     /* if literal, literal on the right or
4810     if the right is in a pointer register and left
4811     is not */
4812     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4813       operand *tmp = right ;
4814       right = left;
4815       left = tmp;
4816     }
4817
4818
4819     if(ifx && !AOP_SIZE(result)){
4820         symbol *tlbl;
4821         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
4822         /* if they are both bit variables */
4823         if (AOP_TYPE(left) == AOP_CRY &&
4824             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4825                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
4826             if(AOP_TYPE(right) == AOP_LIT){
4827                 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4828                 if(lit == 0L){
4829                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4830                     pic16_emitcode("cpl","c");
4831                 } else if(lit == 1L) {
4832                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4833                 } else {
4834                     pic16_emitcode("clr","c");
4835                 }
4836                 /* AOP_TYPE(right) == AOP_CRY */
4837             } else {
4838                 symbol *lbl = newiTempLabel(NULL);
4839                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4840                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4841                 pic16_emitcode("cpl","c");
4842                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4843             }
4844             /* if true label then we jump if condition
4845             supplied is true */
4846             tlbl = newiTempLabel(NULL);
4847             if ( IC_TRUE(ifx) ) {
4848                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4849                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4850             } else {
4851                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4852                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4853             }
4854             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4855
4856                 {
4857                 /* left and right are both bit variables, result is carry */
4858                         resolvedIfx rIfx;
4859
4860                         resolveIfx(&rIfx,ifx);
4861
4862                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4863                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4864                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4865                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4866                         genSkipz2(&rIfx,0);
4867                 }
4868         } else {
4869
4870                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
4871
4872                         /* They're not both bit variables. Is the right a literal? */
4873                         if(AOP_TYPE(right) == AOP_LIT) {
4874                         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4875
4876                         switch(size) {
4877
4878                                 case 1:
4879                                         switch(lit & 0xff) {
4880                                                 case 1:
4881                                                                 if ( IC_TRUE(ifx) ) {
4882                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4883                                                                         emitSKPNZ;
4884                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4885                                                                 } else {
4886                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4887                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4888                                                                 }
4889                                                                 break;
4890                                                 case 0xff:
4891                                                                 if ( IC_TRUE(ifx) ) {
4892                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4893                                                                         emitSKPNZ;
4894                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4895                                                                 } else {
4896                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4897                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4898                                                                 }
4899                                                                 break;
4900                                                 default:
4901                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4902                                                                 if(lit)
4903                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4904                                                                 genSkip(ifx,'z');
4905                                         } // switch lit
4906
4907
4908                                         /* end of size == 1 */
4909                                         break;
4910
4911                                 case 2:
4912                                         genc16bit2lit(left,lit,offset);
4913                                         genSkip(ifx,'z');
4914                                         break;
4915                                         /* end of size == 2 */
4916
4917                                 default:
4918                                         /* size is 4 */
4919                                         if(lit==0) {
4920                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4921                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4922                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4923                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4924                                                 genSkip(ifx,'z');
4925                                         } else {
4926                                                 /* search for patterns that can be optimized */
4927
4928                                                 genc16bit2lit(left,lit,0);
4929                                                 lit >>= 16;
4930                                                 if(lit) {
4931                                                                 if(IC_TRUE(ifx))
4932                                                                 emitSKPZ; // if hi word unequal
4933                                                                 else
4934                                                                 emitSKPNZ; // if hi word equal
4935                                                                 // fail early
4936                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4937                                                         genc16bit2lit(left,lit,2);
4938                                                         genSkip(ifx,'z');
4939                                                 } else {
4940                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4941                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4942                                                         genSkip(ifx,'z');
4943                                                 }
4944                                         }
4945                                                 pic16_emitpLabel(falselbl->key);
4946                                                 break;
4947
4948                         } // switch size
4949
4950                         ifx->generated = 1;
4951                         goto release ;
4952
4953
4954           } else if(AOP_TYPE(right) == AOP_CRY ) {
4955             /* we know the left is not a bit, but that the right is */
4956             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4957             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4958                       pic16_popGet(AOP(right),offset));
4959             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4960
4961             /* if the two are equal, then W will be 0 and the Z bit is set
4962              * we could test Z now, or go ahead and check the high order bytes if
4963              * the variable we're comparing is larger than a byte. */
4964
4965             while(--size)
4966               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4967
4968             if ( IC_TRUE(ifx) ) {
4969               emitSKPNZ;
4970               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4971               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4972             } else {
4973               emitSKPZ;
4974               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4975               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4976             }
4977
4978           } else {
4979             /* They're both variables that are larger than bits */
4980             int s = size;
4981
4982             tlbl = newiTempLabel(NULL);
4983
4984             while(size--) {
4985               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4986               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4987
4988               if ( IC_TRUE(ifx) ) {
4989                 if(size) {
4990                   emitSKPZ;
4991
4992                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4993
4994                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4995                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4996                 } else {
4997                   emitSKPNZ;
4998
4999                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5000
5001
5002                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5003                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5004                 }
5005               } else {
5006                 emitSKPZ;
5007
5008                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5009
5010                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5011                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5012               }
5013               offset++;
5014             }
5015             if(s>1 && IC_TRUE(ifx)) {
5016               pic16_emitpLabel(tlbl->key);
5017               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5018             }
5019           }
5020         }
5021         /* mark the icode as generated */
5022         ifx->generated = 1;
5023         goto release ;
5024     }
5025
5026     /* if they are both bit variables */
5027     if (AOP_TYPE(left) == AOP_CRY &&
5028         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5029         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5030         if(AOP_TYPE(right) == AOP_LIT){
5031             unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5032             if(lit == 0L){
5033                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5034                 pic16_emitcode("cpl","c");
5035             } else if(lit == 1L) {
5036                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5037             } else {
5038                 pic16_emitcode("clr","c");
5039             }
5040             /* AOP_TYPE(right) == AOP_CRY */
5041         } else {
5042             symbol *lbl = newiTempLabel(NULL);
5043             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5044             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5045             pic16_emitcode("cpl","c");
5046             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5047         }
5048         /* c = 1 if egal */
5049         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5050             pic16_outBitC(result);
5051             goto release ;
5052         }
5053         if (ifx) {
5054             genIfxJump (ifx,"c");
5055             goto release ;
5056         }
5057         /* if the result is used in an arithmetic operation
5058         then put the result in place */
5059         pic16_outBitC(result);
5060     } else {
5061
5062       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5063       gencjne(left,right,result,ifx);
5064 /*
5065       if(ifx)
5066         gencjne(left,right,newiTempLabel(NULL));
5067       else {
5068         if(IC_TRUE(ifx)->key)
5069           gencjne(left,right,IC_TRUE(ifx)->key);
5070         else
5071           gencjne(left,right,IC_FALSE(ifx)->key);
5072         ifx->generated = 1;
5073         goto release ;
5074       }
5075       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5076         pic16_aopPut(AOP(result),"a",0);
5077         goto release ;
5078       }
5079
5080       if (ifx) {
5081         genIfxJump (ifx,"a");
5082         goto release ;
5083       }
5084 */
5085       /* if the result is used in an arithmetic operation
5086          then put the result in place */
5087 /*
5088       if (AOP_TYPE(result) != AOP_CRY)
5089         pic16_outAcc(result);
5090 */
5091       /* leave the result in acc */
5092     }
5093
5094 release:
5095     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5096     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5097     pic16_freeAsmop(result,NULL,ic,TRUE);
5098 }
5099 #endif
5100
5101 /*-----------------------------------------------------------------*/
5102 /* ifxForOp - returns the icode containing the ifx for operand     */
5103 /*-----------------------------------------------------------------*/
5104 static iCode *ifxForOp ( operand *op, iCode *ic )
5105 {
5106   FENTRY2;
5107
5108     /* if true symbol then needs to be assigned */
5109     if (IS_TRUE_SYMOP(op))
5110         return NULL ;
5111
5112     /* if this has register type condition and
5113     the next instruction is ifx with the same operand
5114     and live to of the operand is upto the ifx only then */
5115     if (ic->next
5116         && ic->next->op == IFX
5117         && IC_COND(ic->next)->key == op->key
5118         && OP_SYMBOL(op)->liveTo <= ic->next->seq
5119         ) {
5120                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5121           return ic->next;
5122     }
5123
5124     /*
5125     if (ic->next &&
5126         ic->next->op == IFX &&
5127         IC_COND(ic->next)->key == op->key) {
5128       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5129       return ic->next;
5130     }
5131     */
5132
5133     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5134     if (ic->next &&
5135         ic->next->op == IFX)
5136       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5137
5138     if (ic->next &&
5139         ic->next->op == IFX &&
5140         IC_COND(ic->next)->key == op->key) {
5141       DEBUGpic16_emitcode ("; "," key is okay");
5142       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5143                            OP_SYMBOL(op)->liveTo,
5144                            ic->next->seq);
5145     }
5146
5147 #if 0
5148     /* the code below is completely untested
5149      * it just allows ulong2fs.c compile -- VR */
5150
5151     ic = ic->next;
5152     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5153                                         __FILE__, __FUNCTION__, __LINE__);
5154
5155     /* if this has register type condition and
5156     the next instruction is ifx with the same operand
5157     and live to of the operand is upto the ifx only then */
5158     if (ic->next &&
5159         ic->next->op == IFX &&
5160         IC_COND(ic->next)->key == op->key &&
5161         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5162         return ic->next;
5163
5164     if (ic->next &&
5165         ic->next->op == IFX &&
5166         IC_COND(ic->next)->key == op->key) {
5167       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5168       return ic->next;
5169     }
5170
5171     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5172                                         __FILE__, __FUNCTION__, __LINE__);
5173
5174 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5175 #endif
5176
5177     return NULL;
5178 }
5179 /*-----------------------------------------------------------------*/
5180 /* genAndOp - for && operation                                     */
5181 /*-----------------------------------------------------------------*/
5182 static void genAndOp (iCode *ic)
5183 {
5184   operand *left,*right, *result;
5185 /*     symbol *tlbl; */
5186
5187     FENTRY;
5188
5189     /* note here that && operations that are in an
5190     if statement are taken away by backPatchLabels
5191     only those used in arthmetic operations remain */
5192     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5193     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5194     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5195
5196     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5197
5198     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5199     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5200     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5201
5202     /* if both are bit variables */
5203 /*     if (AOP_TYPE(left) == AOP_CRY && */
5204 /*         AOP_TYPE(right) == AOP_CRY ) { */
5205 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5206 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5207 /*         pic16_outBitC(result); */
5208 /*     } else { */
5209 /*         tlbl = newiTempLabel(NULL); */
5210 /*         pic16_toBoolean(left);     */
5211 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5212 /*         pic16_toBoolean(right); */
5213 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5214 /*         pic16_outBitAcc(result); */
5215 /*     } */
5216
5217     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5218     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5219     pic16_freeAsmop(result,NULL,ic,TRUE);
5220 }
5221
5222
5223 /*-----------------------------------------------------------------*/
5224 /* genOrOp - for || operation                                      */
5225 /*-----------------------------------------------------------------*/
5226 /*
5227   tsd pic port -
5228   modified this code, but it doesn't appear to ever get called
5229 */
5230
5231 static void genOrOp (iCode *ic)
5232 {
5233   operand *left,*right, *result;
5234   symbol *tlbl;
5235
5236     FENTRY;
5237
5238   /* note here that || operations that are in an
5239     if statement are taken away by backPatchLabels
5240     only those used in arthmetic operations remain */
5241     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5242     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5243     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5244
5245     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5246
5247     /* if both are bit variables */
5248     if (AOP_TYPE(left) == AOP_CRY &&
5249         AOP_TYPE(right) == AOP_CRY ) {
5250       pic16_emitcode("clrc","");
5251       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5252                AOP(left)->aopu.aop_dir,
5253                AOP(left)->aopu.aop_dir);
5254       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5255                AOP(right)->aopu.aop_dir,
5256                AOP(right)->aopu.aop_dir);
5257       pic16_emitcode("setc","");
5258
5259     } else {
5260         tlbl = newiTempLabel(NULL);
5261         pic16_toBoolean(left);
5262         emitSKPZ;
5263         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5264         pic16_toBoolean(right);
5265         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5266
5267         pic16_outBitAcc(result);
5268     }
5269
5270     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5271     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5272     pic16_freeAsmop(result,NULL,ic,TRUE);
5273 }
5274
5275 /*-----------------------------------------------------------------*/
5276 /* isLiteralBit - test if lit == 2^n                               */
5277 /*-----------------------------------------------------------------*/
5278 static int isLiteralBit(unsigned long lit)
5279 {
5280     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5281     0x100L,0x200L,0x400L,0x800L,
5282     0x1000L,0x2000L,0x4000L,0x8000L,
5283     0x10000L,0x20000L,0x40000L,0x80000L,
5284     0x100000L,0x200000L,0x400000L,0x800000L,
5285     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5286     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5287     int idx;
5288
5289     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5290     for(idx = 0; idx < 32; idx++)
5291         if(lit == pw[idx])
5292             return idx+1;
5293     return 0;
5294 }
5295
5296 /*-----------------------------------------------------------------*/
5297 /* continueIfTrue -                                                */
5298 /*-----------------------------------------------------------------*/
5299 static void continueIfTrue (iCode *ic)
5300 {
5301   FENTRY;
5302   if(IC_TRUE(ic))
5303     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5304   ic->generated = 1;
5305 }
5306
5307 /*-----------------------------------------------------------------*/
5308 /* jmpIfTrue -                                                     */
5309 /*-----------------------------------------------------------------*/
5310 static void jumpIfTrue (iCode *ic)
5311 {
5312   FENTRY;
5313   if(!IC_TRUE(ic))
5314     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5315   ic->generated = 1;
5316 }
5317
5318 /*-----------------------------------------------------------------*/
5319 /* jmpTrueOrFalse -                                                */
5320 /*-----------------------------------------------------------------*/
5321 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5322 {
5323   // ugly but optimized by peephole
5324   FENTRY;
5325   if(IC_TRUE(ic)){
5326     symbol *nlbl = newiTempLabel(NULL);
5327       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5328       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5329       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5330       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5331   } else {
5332     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5333     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5334   }
5335   ic->generated = 1;
5336 }
5337
5338 /*-----------------------------------------------------------------*/
5339 /* genAnd  - code for and                                          */
5340 /*-----------------------------------------------------------------*/
5341 static void genAnd (iCode *ic, iCode *ifx)
5342 {
5343   operand *left, *right, *result;
5344   int size, offset = 0;
5345   unsigned long lit = 0L;
5346   resolvedIfx rIfx;
5347
5348   FENTRY;
5349
5350   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5351   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5352   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5353
5354   resolveIfx (&rIfx, ifx);
5355
5356   /* if left is a literal & right is not then exchange them */
5357   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5358       AOP_NEEDSACC (left))
5359     {
5360       operand *tmp = right;
5361       right = left;
5362       left = tmp;
5363     }
5364
5365   /* if result = right then exchange them */
5366   if (pic16_sameRegs (AOP (result), AOP (right)))
5367     {
5368       operand *tmp = right;
5369       right = left;
5370       left = tmp;
5371     }
5372
5373   /* if right is bit then exchange them */
5374   if (AOP_TYPE (right) == AOP_CRY &&
5375       AOP_TYPE (left) != AOP_CRY)
5376     {
5377       operand *tmp = right;
5378       right = left;
5379       left = tmp;
5380     }
5381
5382   if (AOP_TYPE (right) == AOP_LIT)
5383     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5384
5385   size = AOP_SIZE (result);
5386
5387   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5388
5389   // if(bit & yy)
5390   // result = bit & yy;
5391   if (AOP_TYPE(left) == AOP_CRY){
5392     // c = bit & literal;
5393     if(AOP_TYPE(right) == AOP_LIT){
5394       if(lit & 1) {
5395         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5396           // no change
5397           goto release;
5398         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5399       } else {
5400         // bit(result) = 0;
5401         if(size && (AOP_TYPE(result) == AOP_CRY)){
5402           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5403           goto release;
5404         }
5405         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5406           jumpIfTrue(ifx);
5407           goto release;
5408         }
5409         pic16_emitcode("clr","c");
5410       }
5411     } else {
5412       if (AOP_TYPE(right) == AOP_CRY){
5413         // c = bit & bit;
5414         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5415         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5416       } else {
5417         // c = bit & val;
5418         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5419         // c = lsb
5420         pic16_emitcode("rrc","a");
5421         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5422       }
5423     }
5424     // bit = c
5425     // val = c
5426     if(size)
5427       pic16_outBitC(result);
5428     // if(bit & ...)
5429     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5430       genIfxJump(ifx, "c");
5431     goto release ;
5432   }
5433
5434   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
5435   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5436   if ((AOP_TYPE (right) == AOP_LIT) &&
5437      (AOP_TYPE (result) == AOP_CRY) &&
5438      (AOP_TYPE (left) != AOP_CRY))
5439     {
5440       symbol *tlbl = newiTempLabel (NULL);
5441       int sizel = AOP_SIZE (left);
5442       int nonnull = 0;
5443       char emitBra;
5444
5445       if (size)
5446         emitSETC;
5447
5448       /* get number of non null bytes in literal */
5449       while (sizel--)
5450         {
5451           if (lit & (0xff << (sizel * 8)))
5452             ++nonnull;
5453         }
5454
5455       emitBra = nonnull || rIfx.condition;
5456
5457       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5458         {
5459           unsigned char bytelit = lit;
5460
5461           if (bytelit != 0)
5462             {
5463               int posbit;
5464
5465               --nonnull;
5466
5467               /* patch provided by Aaron Colwell */
5468               if ((posbit = isLiteralBit (bytelit)) != 0)
5469                 {
5470                   if (nonnull)
5471                     {
5472                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5473                       pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5474                     }
5475                   else
5476                     {
5477                       pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5478                     }
5479                 }
5480               else
5481                 {
5482                   if (bytelit == 0xff)
5483                     {
5484                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
5485                        * a peephole could optimize it out -- VR */
5486                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5487                     }
5488                   else
5489                     {
5490                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5491                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5492                     }
5493                   if (nonnull)
5494                     {
5495                       if (rIfx.condition)
5496                         {
5497                           emitSKPZ;
5498                           pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5499                         }
5500                       else
5501                         {
5502                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5503                         }
5504                     }
5505                   else
5506                     {
5507                       /* last non null byte */
5508                       if (rIfx.condition)
5509                         emitSKPZ;
5510                       else
5511                         emitSKPNZ;
5512                     }
5513                 }
5514             }
5515         }
5516
5517       // bit = left & literal
5518       if (size)
5519         {
5520           emitCLRC;
5521           pic16_emitpLabel (tlbl->key);
5522         }
5523
5524       // if(left & literal)
5525       else
5526         {
5527           if (ifx)
5528             {
5529               if (emitBra)
5530                 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
5531               ifx->generated = 1;
5532             }
5533           pic16_emitpLabel (tlbl->key);
5534           goto release;
5535         }
5536       pic16_outBitC (result);
5537       goto release;
5538     }
5539
5540   /* if left is same as result */
5541   if(pic16_sameRegs(AOP(result),AOP(left))){
5542     int know_W = -1;
5543     for(;size--; offset++,lit>>=8) {
5544       if(AOP_TYPE(right) == AOP_LIT){
5545         switch(lit & 0xff) {
5546         case 0x00:
5547           /*  and'ing with 0 has clears the result */
5548 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5549           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5550           break;
5551         case 0xff:
5552           /* and'ing with 0xff is a nop when the result and left are the same */
5553           break;
5554
5555         default:
5556           {
5557             int p = pic16_my_powof2( (~lit) & 0xff );
5558             if(p>=0) {
5559               /* only one bit is set in the literal, so use a bcf instruction */
5560 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5561               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5562
5563             } else {
5564               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5565               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5566               if(know_W != (lit&0xff))
5567                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5568               know_W = lit &0xff;
5569               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5570             }
5571           }
5572         }
5573       } else {
5574         if (AOP_TYPE(left) == AOP_ACC) {
5575           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5576         } else {
5577           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5578           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5579
5580         }
5581       }
5582     }
5583
5584   } else {
5585     // left & result in different registers
5586     if(AOP_TYPE(result) == AOP_CRY){
5587       // result = bit
5588       // if(size), result in bit
5589       // if(!size && ifx), conditional oper: if(left & right)
5590       symbol *tlbl = newiTempLabel(NULL);
5591       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5592       if(size)
5593         pic16_emitcode("setb","c");
5594       while(sizer--){
5595         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5596         pic16_emitcode("anl","a,%s",
5597                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5598         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5599         offset++;
5600       }
5601       if(size){
5602         CLRC;
5603         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5604         pic16_outBitC(result);
5605       } else if(ifx)
5606         jmpTrueOrFalse(ifx, tlbl);
5607     } else {
5608       for(;(size--);offset++) {
5609         // normal case
5610         // result = left & right
5611         if(AOP_TYPE(right) == AOP_LIT){
5612           int t = (lit >> (offset*8)) & 0x0FFL;
5613           switch(t) {
5614           case 0x00:
5615             pic16_emitcode("clrf","%s",
5616                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5617             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5618             break;
5619           case 0xff:
5620             pic16_emitcode("movf","%s,w",
5621                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5622             pic16_emitcode("movwf","%s",
5623                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5624             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5625             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5626             break;
5627           default:
5628             pic16_emitcode("movlw","0x%x",t);
5629             pic16_emitcode("andwf","%s,w",
5630                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5631             pic16_emitcode("movwf","%s",
5632                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5633
5634             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5635             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5636             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5637           }
5638           continue;
5639         }
5640
5641         if (AOP_TYPE(left) == AOP_ACC) {
5642           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5643           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5644         } else {
5645           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5646           pic16_emitcode("andwf","%s,w",
5647                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5648           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5649           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5650         }
5651         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5652         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5653       }
5654     }
5655   }
5656
5657 release :
5658   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5659   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5660   pic16_freeAsmop(result,NULL,ic,TRUE);
5661 }
5662
5663 /*-----------------------------------------------------------------*/
5664 /* genOr  - code for or                                            */
5665 /*-----------------------------------------------------------------*/
5666 static void genOr (iCode *ic, iCode *ifx)
5667 {
5668   operand *left, *right, *result;
5669   int size, offset = 0;
5670   unsigned long lit = 0L;
5671   resolvedIfx rIfx;
5672
5673   FENTRY;
5674
5675   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5676   pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5677   pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5678
5679   resolveIfx (&rIfx, ifx);
5680
5681   /* if left is a literal & right is not then exchange them */
5682   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5683       AOP_NEEDSACC (left))
5684     {
5685       operand *tmp = right;
5686       right = left;
5687       left = tmp;
5688     }
5689
5690   /* if result = right then exchange them */
5691   if (pic16_sameRegs (AOP (result), AOP (right)))
5692     {
5693       operand *tmp = right;
5694       right = left;
5695       left = tmp;
5696     }
5697
5698   /* if right is bit then exchange them */
5699   if (AOP_TYPE (right) == AOP_CRY &&
5700       AOP_TYPE (left) != AOP_CRY)
5701     {
5702       operand *tmp = right;
5703       right = left;
5704       left = tmp;
5705     }
5706
5707   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5708
5709   if (AOP_TYPE (right) == AOP_LIT)
5710       lit = ulFromVal (AOP (right)->aopu.aop_lit);
5711
5712   size = AOP_SIZE (result);
5713
5714   // if(bit | yy)
5715   // xx = bit | yy;
5716   if (AOP_TYPE(left) == AOP_CRY){
5717       if(AOP_TYPE(right) == AOP_LIT){
5718           // c = bit & literal;
5719           if(lit){
5720               // lit != 0 => result = 1
5721               if(AOP_TYPE(result) == AOP_CRY){
5722                 if(size)
5723                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5724                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5725                 //     AOP(result)->aopu.aop_dir,
5726                 //     AOP(result)->aopu.aop_dir);
5727                   else if(ifx)
5728                       continueIfTrue(ifx);
5729                   goto release;
5730               }
5731           } else {
5732               // lit == 0 => result = left
5733               if(size && pic16_sameRegs(AOP(result),AOP(left)))
5734                   goto release;
5735               pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5736           }
5737       } else {
5738           if (AOP_TYPE(right) == AOP_CRY){
5739             if(pic16_sameRegs(AOP(result),AOP(left))){
5740               // c = bit | bit;
5741               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5742               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5743               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5744
5745             } else {
5746               if( AOP_TYPE(result) == AOP_ACC) {
5747                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5748                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5749                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5750                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5751
5752               } else {
5753
5754                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5755                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5756                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5757                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5758
5759               }
5760             }
5761           } else {
5762               // c = bit | val;
5763               symbol *tlbl = newiTempLabel(NULL);
5764               pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5765
5766
5767               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5768               if( AOP_TYPE(right) == AOP_ACC) {
5769                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5770                 emitSKPNZ;
5771                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5772                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5773               }
5774
5775
5776
5777               if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5778                   pic16_emitcode(";XXX setb","c");
5779               pic16_emitcode(";XXX jb","%s,%05d_DS_",
5780                        AOP(left)->aopu.aop_dir,tlbl->key+100);
5781               pic16_toBoolean(right);
5782               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5783               if((AOP_TYPE(result) == AOP_CRY) && ifx){
5784                   jmpTrueOrFalse(ifx, tlbl);
5785                   goto release;
5786               } else {
5787                   CLRC;
5788                   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5789               }
5790           }
5791       }
5792       // bit = c
5793       // val = c
5794       if(size)
5795           pic16_outBitC(result);
5796       // if(bit | ...)
5797       else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5798           genIfxJump(ifx, "c");
5799       goto release ;
5800   }
5801
5802   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5803   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5804   if ((AOP_TYPE (right) == AOP_LIT) &&
5805      (AOP_TYPE (result) == AOP_CRY) &&
5806      (AOP_TYPE (left) != AOP_CRY))
5807     {
5808       if (IS_OP_VOLATILE(left)) {
5809           pic16_mov2w_volatile(AOP(left));
5810       } // if
5811       if (lit)
5812         {
5813           if (rIfx.condition)
5814             pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5815           ifx->generated = 1;
5816         }
5817       else
5818         wassert (0);
5819
5820       goto release;
5821   }
5822
5823   /* if left is same as result */
5824   if(pic16_sameRegs(AOP(result),AOP(left))){
5825     int know_W = -1;
5826     for(;size--; offset++,lit>>=8) {
5827       if(AOP_TYPE(right) == AOP_LIT){
5828         if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5829           /*  or'ing with 0 has no effect */
5830           continue;
5831         } else {
5832           int p = pic16_my_powof2(lit & 0xff);
5833           if(p>=0) {
5834             /* only one bit is set in the literal, so use a bsf instruction */
5835             pic16_emitpcode(POC_BSF,
5836                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5837           } else {
5838             if(know_W != (lit & 0xff))
5839               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5840             know_W = lit & 0xff;
5841             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5842           }
5843
5844         }
5845       } else {
5846         if (AOP_TYPE(left) == AOP_ACC) {
5847           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5848         } else {
5849           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5850           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5851         }
5852       }
5853     }
5854   } else {
5855       // left & result in different registers
5856       if(AOP_TYPE(result) == AOP_CRY){
5857           // result = bit
5858           // if(size), result in bit
5859           // if(!size && ifx), conditional oper: if(left | right)
5860           symbol *tlbl = newiTempLabel(NULL);
5861           int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5862           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5863
5864
5865           if(size)
5866               pic16_emitcode(";XXX setb","c");
5867           while(sizer--){
5868               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5869               pic16_emitcode(";XXX orl","a,%s",
5870                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5871               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5872               offset++;
5873           }
5874           if(size){
5875               CLRC;
5876               pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5877               pic16_outBitC(result);
5878           } else if(ifx)
5879               jmpTrueOrFalse(ifx, tlbl);
5880       } else for(;(size--);offset++){
5881         // normal case
5882         // result = left & right
5883         if(AOP_TYPE(right) == AOP_LIT){
5884           int t = (lit >> (offset*8)) & 0x0FFL;
5885           switch(t) {
5886           case 0x00:
5887             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5888             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5889             break;
5890           default:
5891             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5892             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5893             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5894           }
5895           continue;
5896         }
5897
5898         // faster than result <- left, anl result,right
5899         // and better if result is SFR
5900         if (AOP_TYPE(left) == AOP_ACC) {
5901           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5902         } else {
5903           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5904           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5905         }
5906         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5907       }
5908   }
5909
5910 release :
5911   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5912   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5913   pic16_freeAsmop(result,NULL,ic,TRUE);
5914 }
5915
5916 /*-----------------------------------------------------------------*/
5917 /* genXor - code for xclusive or                                   */
5918 /*-----------------------------------------------------------------*/
5919 static void genXor (iCode *ic, iCode *ifx)
5920 {
5921   operand *left, *right, *result;
5922   int size, offset = 0;
5923   unsigned long lit = 0L;
5924   resolvedIfx rIfx;
5925
5926   FENTRY;
5927
5928   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5929   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5930   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5931
5932   resolveIfx (&rIfx,ifx);
5933
5934   /* if left is a literal & right is not ||
5935      if left needs acc & right does not */
5936   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5937       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5938     {
5939       operand *tmp = right;
5940       right = left;
5941       left = tmp;
5942     }
5943
5944   /* if result = right then exchange them */
5945   if (pic16_sameRegs (AOP (result), AOP (right)))
5946     {
5947       operand *tmp = right ;
5948       right = left;
5949       left = tmp;
5950     }
5951
5952   /* if right is bit then exchange them */
5953   if (AOP_TYPE (right) == AOP_CRY &&
5954       AOP_TYPE (left) != AOP_CRY)
5955     {
5956       operand *tmp = right ;
5957       right = left;
5958       left = tmp;
5959     }
5960
5961   if (AOP_TYPE (right) == AOP_LIT)
5962     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5963
5964   size = AOP_SIZE (result);
5965
5966   // if(bit ^ yy)
5967   // xx = bit ^ yy;
5968   if (AOP_TYPE(left) == AOP_CRY)
5969     {
5970       if (AOP_TYPE(right) == AOP_LIT)
5971         {
5972           // c = bit & literal;
5973           if (lit >> 1)
5974             {
5975               // lit>>1  != 0 => result = 1
5976               if (AOP_TYPE(result) == AOP_CRY)
5977                 {
5978                   if (size)
5979                     {
5980                       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
5981                     }
5982                   else if (ifx)
5983                     continueIfTrue(ifx);
5984                   goto release;
5985                 }
5986               pic16_emitcode("setb", "c");
5987             }
5988           else
5989             {
5990               // lit == (0 or 1)
5991               if (lit == 0)
5992                 {
5993                   // lit == 0, result = left
5994                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
5995                     goto release;
5996                   pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
5997                 }
5998               else
5999                 {
6000                   // lit == 1, result = not(left)
6001                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
6002                     {
6003                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6004                       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6005                       pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6006                       goto release;
6007                     }
6008                   else
6009                     {
6010                       pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6011                       pic16_emitcode("cpl", "c");
6012                     }
6013                 }
6014             }
6015         }
6016       else
6017         {
6018           // right != literal
6019           symbol *tlbl = newiTempLabel(NULL);
6020           if (AOP_TYPE(right) == AOP_CRY)
6021             {
6022               // c = bit ^ bit;
6023               pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6024             }
6025           else
6026             {
6027               int sizer = AOP_SIZE(right);
6028               // c = bit ^ val
6029               // if val>>1 != 0, result = 1
6030               pic16_emitcode("setb", "c");
6031               while (sizer)
6032                 {
6033                   MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6034                   if (sizer == 1)
6035                     // test the msb of the lsb
6036                     pic16_emitcode("anl", "a,#0xfe");
6037                   pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6038                   sizer--;
6039                 }
6040               // val = (0,1)
6041               pic16_emitcode("rrc", "a");
6042             }
6043           pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6044           pic16_emitcode("cpl", "c");
6045           pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6046         }
6047       // bit = c
6048       // val = c
6049       if (size)
6050         pic16_outBitC(result);
6051       // if(bit | ...)
6052       else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6053         genIfxJump(ifx, "c");
6054       goto release;
6055     }
6056
6057   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
6058   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
6059   if ((AOP_TYPE (right) == AOP_LIT) &&
6060      (AOP_TYPE (result) == AOP_CRY) &&
6061      (AOP_TYPE (left) != AOP_CRY))
6062     {
6063       symbol *tlbl = newiTempLabel (NULL);
6064       int sizel;
6065
6066       if (size)
6067         emitSETC;
6068
6069       for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6070         {
6071           unsigned char bytelit = lit;
6072
6073           switch (bytelit)
6074             {
6075             case 0xff:
6076               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6077               break;
6078
6079             case 0x00:
6080               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6081               break;
6082
6083             default:
6084               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6085               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6086               break;
6087             }
6088           if (sizel)
6089             {
6090               if (rIfx.condition)
6091                 {
6092                   /* rIfx.lbl might be far away... */
6093                   emitSKPZ;
6094                   pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6095                 }
6096               else
6097                 {
6098                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6099                 }
6100             }
6101           else
6102             {
6103               /* last non null byte */
6104               if (rIfx.condition)
6105                 emitSKPZ;
6106               else
6107                 emitSKPNZ;
6108             }
6109         }
6110
6111       // bit = left ^ literal
6112       if (size)
6113         {
6114           emitCLRC;
6115           pic16_emitpLabel (tlbl->key);
6116         }
6117       // if (left ^ literal)
6118       else
6119         {
6120           if (ifx)
6121             {
6122               pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
6123               ifx->generated = 1;
6124             }
6125           pic16_emitpLabel (tlbl->key);
6126           goto release;
6127         }
6128
6129       pic16_outBitC (result);
6130       goto release;
6131   }
6132
6133   if (pic16_sameRegs(AOP(result), AOP(left)))
6134     {
6135       /* if left is same as result */
6136       for (; size--; offset++)
6137         {
6138           if (AOP_TYPE(right) == AOP_LIT)
6139             {
6140               int t  = (lit >> (offset * 8)) & 0x0FFL;
6141               if  (t == 0x00L)
6142                 continue;
6143               else
6144                 {
6145                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6146                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6147                 }
6148             }
6149           else
6150             {
6151               if (AOP_TYPE(left) == AOP_ACC)
6152                 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6153               else
6154                 {
6155                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6156                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6157                 }
6158             }
6159         }
6160     }
6161   else
6162     {
6163     // left ^ result in different registers
6164     if (AOP_TYPE(result) == AOP_CRY)
6165       {
6166         // result = bit
6167         // if(size), result in bit
6168         // if(!size && ifx), conditional oper: if(left ^ right)
6169         symbol *tlbl = newiTempLabel(NULL);
6170         int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6171         if (size)
6172           pic16_emitcode("setb", "c");
6173         while (sizer--)
6174           {
6175             if ((AOP_TYPE(right) == AOP_LIT) &&
6176               (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6177               {
6178                 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6179               }
6180             else
6181               {
6182                 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6183                 pic16_emitcode("xrl", "a,%s",
6184                                pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6185               }
6186             pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6187             offset++;
6188           }
6189         if (size)
6190           {
6191             CLRC;
6192             pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6193             pic16_outBitC(result);
6194           }
6195         else if (ifx)
6196           jmpTrueOrFalse(ifx, tlbl);
6197       }
6198     else
6199       {
6200         for (; (size--); offset++)
6201           {
6202             // normal case
6203             // result = left ^ right
6204             if (AOP_TYPE(right) == AOP_LIT)
6205               {
6206                 int t = (lit >> (offset * 8)) & 0x0FFL;
6207                 switch(t)
6208                   {
6209                   case 0x00:
6210                     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6211                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6212                     break;
6213
6214                   case 0xff:
6215                     pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6216                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6217                     break;
6218
6219                   default:
6220                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6221                     pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6222                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6223                   }
6224                 continue;
6225               }
6226
6227             // faster than result <- left, anl result,right
6228             // and better if result is SFR
6229             if (AOP_TYPE(left) == AOP_ACC)
6230               {
6231                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6232               }
6233             else
6234               {
6235                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6236                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6237               }
6238             if ( AOP_TYPE(result) != AOP_ACC)
6239               {
6240                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6241               }
6242           }
6243       }
6244   }
6245
6246 release :
6247   pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6248   pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6249   pic16_freeAsmop(result, NULL, ic, TRUE);
6250 }
6251
6252 /*-----------------------------------------------------------------*/
6253 /* genInline - write the inline code out                           */
6254 /*-----------------------------------------------------------------*/
6255 static void genInline (iCode *ic)
6256 {
6257   char *buffer, *bp, *bp1;
6258   bool inComment = FALSE;
6259
6260   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6261
6262   _G.inLine += (!options.asmpeep);
6263
6264   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6265
6266   while((bp1=strstr(bp, "\\n"))) {
6267     *bp1++ = '\n';
6268     *bp1++ = ' ';
6269     bp = bp1;
6270   }
6271   bp = bp1 = buffer;
6272
6273 #if 0
6274   /* This is an experimental code for #pragma inline
6275      and is temporarily disabled for 2.5.0 release */
6276   if(asmInlineMap)
6277   {
6278     symbol *sym;
6279     char *s;
6280     char *cbuf;
6281     int cblen;
6282
6283       cbuf = Safe_strdup(buffer);
6284       cblen = strlen(buffer)+1;
6285       memset(cbuf, 0, cblen);
6286
6287       bp = buffer;
6288       bp1 = cbuf;
6289       while(*bp) {
6290         if(*bp != '%')*bp1++ = *bp++;
6291         else {
6292           int i;
6293
6294             bp++;
6295             i = *bp - '0';
6296             if(i>elementsInSet(asmInlineMap))break;
6297
6298             bp++;
6299             s = indexSet(asmInlineMap, i);
6300             DEBUGpc("searching symbol s = `%s'", s);
6301             sym = findSym(SymbolTab, NULL, s);
6302
6303             if(sym->reqv) {
6304               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6305             } else {
6306               strcat(bp1, sym->rname);
6307             }
6308
6309             while(*bp1)bp1++;
6310         }
6311
6312         if(strlen(bp1) > cblen - 16) {
6313           int i = strlen(cbuf);
6314           cblen += 50;
6315           cbuf = realloc(cbuf, cblen);
6316           memset(cbuf+i, 0, 50);
6317           bp1 = cbuf + i;
6318         }
6319       }
6320
6321       free(buffer);
6322       buffer = Safe_strdup( cbuf );
6323       free(cbuf);
6324
6325       bp = bp1 = buffer;
6326   }
6327 #endif  /* 0 */
6328
6329   /* emit each line as a code */
6330   while (*bp)
6331     {
6332       switch (*bp)
6333         {
6334         case ';':
6335           inComment = TRUE;
6336           ++bp;
6337           break;
6338
6339         case '\n':
6340           inComment = FALSE;
6341           *bp++ = '\0';
6342           if (*bp1)
6343             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6344           bp1 = bp;
6345           break;
6346
6347         default:
6348           /* Add \n for labels, not dirs such as c:\mydir */
6349           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6350             {
6351               ++bp;
6352               *bp = '\0';
6353               ++bp;
6354               /* print label, use this special format with NULL directive
6355                * to denote that the argument should not be indented with tab */
6356               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6357               bp1 = bp;
6358             }
6359           else
6360             ++bp;
6361           break;
6362         }
6363     }
6364
6365   if ((bp1 != bp) && *bp1)
6366     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6367
6368   Safe_free (buffer);
6369
6370   _G.inLine -= (!options.asmpeep);
6371 }
6372
6373 /*-----------------------------------------------------------------*/
6374 /* genRRC - rotate right with carry                                */
6375 /*-----------------------------------------------------------------*/
6376 static void genRRC (iCode *ic)
6377 {
6378   operand *left , *result ;
6379   int size, offset = 0, same;
6380
6381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6382
6383   /* rotate right with carry */
6384   left = IC_LEFT(ic);
6385   result=IC_RESULT(ic);
6386   pic16_aopOp (left,ic,FALSE);
6387   pic16_aopOp (result,ic,TRUE);
6388
6389   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6390
6391   same = pic16_sameRegs(AOP(result),AOP(left));
6392
6393   size = AOP_SIZE(result);
6394
6395   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6396
6397   /* get the lsb and put it into the carry */
6398   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6399
6400   offset = 0 ;
6401
6402   while(size--) {
6403
6404     if(same) {
6405       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6406     } else {
6407       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6408       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6409     }
6410
6411     offset++;
6412   }
6413
6414   pic16_freeAsmop(left,NULL,ic,TRUE);
6415   pic16_freeAsmop(result,NULL,ic,TRUE);
6416 }
6417
6418 /*-----------------------------------------------------------------*/
6419 /* genRLC - generate code for rotate left with carry               */
6420 /*-----------------------------------------------------------------*/
6421 static void genRLC (iCode *ic)
6422 {
6423   operand *left , *result ;
6424   int size, offset = 0;
6425   int same;
6426
6427   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6428   /* rotate right with carry */
6429   left = IC_LEFT(ic);
6430   result=IC_RESULT(ic);
6431   pic16_aopOp (left,ic,FALSE);
6432   pic16_aopOp (result,ic,TRUE);
6433
6434   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6435
6436   same = pic16_sameRegs(AOP(result),AOP(left));
6437
6438   /* move it to the result */
6439   size = AOP_SIZE(result);
6440
6441   /* get the msb and put it into the carry */
6442   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6443
6444   offset = 0 ;
6445
6446   while(size--) {
6447
6448     if(same) {
6449       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6450     } else {
6451       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6452       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6453     }
6454
6455     offset++;
6456   }
6457
6458
6459   pic16_freeAsmop(left,NULL,ic,TRUE);
6460   pic16_freeAsmop(result,NULL,ic,TRUE);
6461 }
6462
6463
6464 /* gpasm can get the highest order bit with HIGH/UPPER
6465  * so the following probably is not needed -- VR */
6466
6467 /*-----------------------------------------------------------------*/
6468 /* genGetHbit - generates code get highest order bit               */
6469 /*-----------------------------------------------------------------*/
6470 static void genGetHbit (iCode *ic)
6471 {
6472     operand *left, *result;
6473     left = IC_LEFT(ic);
6474     result=IC_RESULT(ic);
6475     pic16_aopOp (left,ic,FALSE);
6476     pic16_aopOp (result,ic,FALSE);
6477
6478     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6479     /* get the highest order byte into a */
6480     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6481     if(AOP_TYPE(result) == AOP_CRY){
6482         pic16_emitcode("rlc","a");
6483         pic16_outBitC(result);
6484     }
6485     else{
6486         pic16_emitcode("rl","a");
6487         pic16_emitcode("anl","a,#0x01");
6488         pic16_outAcc(result);
6489     }
6490
6491
6492     pic16_freeAsmop(left,NULL,ic,TRUE);
6493     pic16_freeAsmop(result,NULL,ic,TRUE);
6494 }
6495
6496 #if 0
6497 /*-----------------------------------------------------------------*/
6498 /* AccRol - rotate left accumulator by known count                 */
6499 /*-----------------------------------------------------------------*/
6500 static void AccRol (int shCount)
6501 {
6502     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6503     shCount &= 0x0007;              // shCount : 0..7
6504     switch(shCount){
6505         case 0 :
6506             break;
6507         case 1 :
6508             pic16_emitcode("rl","a");
6509             break;
6510         case 2 :
6511             pic16_emitcode("rl","a");
6512             pic16_emitcode("rl","a");
6513             break;
6514         case 3 :
6515             pic16_emitcode("swap","a");
6516             pic16_emitcode("rr","a");
6517             break;
6518         case 4 :
6519             pic16_emitcode("swap","a");
6520             break;
6521         case 5 :
6522             pic16_emitcode("swap","a");
6523             pic16_emitcode("rl","a");
6524             break;
6525         case 6 :
6526             pic16_emitcode("rr","a");
6527             pic16_emitcode("rr","a");
6528             break;
6529         case 7 :
6530             pic16_emitcode("rr","a");
6531             break;
6532     }
6533 }
6534 #endif
6535
6536 /*-----------------------------------------------------------------*/
6537 /* AccLsh - left shift accumulator by known count                  */
6538 /*-----------------------------------------------------------------*/
6539 static void AccLsh (int shCount, int doMask)
6540 {
6541         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6542         switch(shCount){
6543                 case 0 :
6544                         return;
6545                         break;
6546                 case 1 :
6547                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6548                         break;
6549                 case 2 :
6550                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6551                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6552                         break;
6553                 case 3 :
6554                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6555                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6556                         break;
6557                 case 4 :
6558                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6559                         break;
6560                 case 5 :
6561                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6562                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6563                         break;
6564                 case 6 :
6565                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6566                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6567                         break;
6568                 case 7 :
6569                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6570                         break;
6571         }
6572         if (doMask) {
6573                 /* no masking is required in genPackBits */
6574                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6575         }
6576 }
6577
6578 /*-----------------------------------------------------------------*/
6579 /* AccRsh - right shift accumulator by known count                 */
6580 /*-----------------------------------------------------------------*/
6581 static void AccRsh (int shCount, int andmask)
6582 {
6583         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6584         assert ((shCount >= 0) && (shCount <= 8));
6585         switch (shCount) {
6586                 case 0 :
6587                         return; break;
6588                 case 1 :
6589                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590                         break;
6591                 case 2 :
6592                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6593                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6594                         break;
6595                 case 3 :
6596                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6598                         break;
6599                 case 4 :
6600                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6601                         break;
6602                 case 5 :
6603                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6604                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605                         break;
6606                 case 6 :
6607                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6609                         break;
6610                 case 7 :
6611                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6612                         break;
6613                 default:
6614                         // Rotating by 8 is a NOP.
6615                         break;
6616         }
6617
6618         if (andmask)
6619                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6620         else
6621                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6622 }
6623
6624 /*-----------------------------------------------------------------*/
6625 /* shiftR1Left2Result - shift right one byte from left to result   */
6626 /*-----------------------------------------------------------------*/
6627 static void shiftR1Left2ResultSigned (operand *left, int offl,
6628                                 operand *result, int offr,
6629                                 int shCount)
6630 {
6631   int same;
6632
6633   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6634   assert ((shCount >= 0) && (shCount <= 8));
6635
6636   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6637
6638   /* Do NOT use result for intermediate results, it might be an SFR!. */
6639   switch (shCount) {
6640   case 0:
6641     if (!same) {
6642       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6643       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6644     }
6645     break;
6646
6647   case 1:
6648     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6649     if (same)
6650       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6651     else {
6652       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6653       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6654     }
6655     break;
6656
6657   case 2:
6658     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6659     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6660     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6661     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6662     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6663     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6664     break;
6665
6666   case 3:
6667     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6668     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6669     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6670     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6671     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6672     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6673     break;
6674
6675   case 4:
6676     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6677     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6678     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6679     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6680     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6681     break;
6682
6683   case 5:
6684     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6685     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6686     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6687     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6688     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6689     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6690     break;
6691
6692   case 6:
6693     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6694     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6695     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6696     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6697     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6698     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6699     break;
6700
6701   case 7:
6702     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6703     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6704     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6705     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6706     break;
6707
6708   default:
6709     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6710     break;
6711   }
6712 }
6713
6714 /*-----------------------------------------------------------------*/
6715 /* shiftR1Left2Result - shift right one byte from left to result   */
6716 /*-----------------------------------------------------------------*/
6717 static void shiftR1Left2Result (operand *left, int offl,
6718                                 operand *result, int offr,
6719                                 int shCount, int sign)
6720 {
6721   int same;
6722
6723   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6724   assert ((shCount >= 0) && (shCount <= 8));
6725
6726   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6727
6728   /* Copy the msb into the carry if signed. */
6729   if (sign) {
6730     shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6731     return;
6732   }
6733
6734   /* Do NOT use result for intermediate results, it might be an SFR!. */
6735   switch (shCount) {
6736   case 0:
6737     if (!same) {
6738       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6739       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6740     }
6741     break;
6742
6743   case 1:
6744     if (same) {
6745       emitCLRC;
6746       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6747     } else {
6748       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6749       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6750       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6751     }
6752     break;
6753
6754   case 2:
6755     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6756     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6757     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6758     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6759     break;
6760
6761   case 3:
6762     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6763     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6764     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6765     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6766     break;
6767
6768   case 4:
6769     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6770     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6771     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6772     break;
6773
6774   case 5:
6775     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6776     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6777     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6778     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6779     break;
6780
6781   case 6:
6782     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6783     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6784     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6785     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6786     break;
6787
6788   case 7:
6789     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6790     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6791     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6792     break;
6793
6794   default:
6795     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6796     break;
6797   }
6798 }
6799
6800 /*-----------------------------------------------------------------*/
6801 /* shiftL1Left2Result - shift left one byte from left to result    */
6802 /*-----------------------------------------------------------------*/
6803 static void shiftL1Left2Result (operand *left, int offl,
6804                                 operand *result, int offr, int shCount)
6805 {
6806   int same;
6807
6808   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6809   assert ((shCount >= 0) && (shCount <= 8));
6810
6811   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6812
6813   /* Do NOT use result for intermediate results, it might be an SFR!. */
6814   switch (shCount) {
6815   case 0:
6816     if (!same) {
6817       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6818       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6819     }
6820     break;
6821
6822   case 1:
6823     if (same) {
6824       emitCLRC;
6825       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6826     } else {
6827       pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6828       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6829       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6830     }
6831     break;
6832
6833   case 2:
6834     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6835     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6836     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6837     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6838     break;
6839
6840   case 3:
6841     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6842     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6843     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6844     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6845     break;
6846
6847   case 4:
6848     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6849     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6850     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6851     break;
6852
6853   case 5:
6854     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6855     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6856     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6857     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6858     break;
6859
6860   case 6:
6861     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6862     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6863     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6864     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6865     break;
6866
6867   case 7:
6868     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6869     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6870     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6871     break;
6872
6873   default:
6874     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6875     break;
6876   }
6877 }
6878
6879 /*-----------------------------------------------------------------*/
6880 /* movLeft2Result - move byte from left to result                  */
6881 /*-----------------------------------------------------------------*/
6882 static void movLeft2Result (operand *left, int offl,
6883                             operand *result, int offr)
6884 {
6885   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6886   if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6887     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6888     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6889   }
6890 }
6891
6892 /*-----------------------------------------------------------------*/
6893 /* shiftL2Left2Result - shift left two bytes from left to result   */
6894 /*-----------------------------------------------------------------*/
6895 static void shiftL2Left2Result (operand *left, int offl,
6896                                 operand *result, int offr, int shCount)
6897 {
6898   int same = pic16_sameRegs(AOP(result), AOP(left));
6899   int i;
6900
6901   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6902
6903   if (same && (offl != offr)) { // shift bytes
6904     if (offr > offl) {
6905        for(i=1;i>-1;i--) {
6906          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6907          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6908        }
6909     } else { // just treat as different later on
6910                 same = 0;
6911     }
6912   }
6913
6914   if(same) {
6915     switch(shCount) {
6916     case 0:
6917       break;
6918     case 1:
6919     case 2:
6920     case 3:
6921
6922       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6923       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6924       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6925
6926       while(--shCount) {
6927                 emitCLRC;
6928                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6929                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6930       }
6931
6932       break;
6933     case 4:
6934     case 5:
6935       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6936       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6937       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6938       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6939       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6940       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6941       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6942       if(shCount >=5) {
6943                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6944                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6945       }
6946       break;
6947     case 6:
6948       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6949       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6950       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6951       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6952       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6953       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6954       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6955       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6956       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6957       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6958       break;
6959     case 7:
6960       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6961       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6962       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6963       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6964       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6965     }
6966
6967   } else {
6968     switch(shCount) {
6969     case 0:
6970       break;
6971     case 1:
6972     case 2:
6973     case 3:
6974       /* note, use a mov/add for the shift since the mov has a
6975          chance of getting optimized out */
6976       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6977       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6978       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6979       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6980       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6981
6982       while(--shCount) {
6983                 emitCLRC;
6984                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6985                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6986       }
6987       break;
6988
6989     case 4:
6990     case 5:
6991       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6992       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6993       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6994       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6995       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6996       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
6997       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6998       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6999
7000
7001       if(shCount == 5) {
7002                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7003                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7004       }
7005       break;
7006     case 6:
7007       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7008       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7009       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7010       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7011
7012       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7013       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7014       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7015       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7016       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7017       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7018       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7019       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7020       break;
7021     case 7:
7022       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7023       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7024       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7025       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7026       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7027     }
7028   }
7029
7030 }
7031 /*-----------------------------------------------------------------*/
7032 /* shiftR2Left2Result - shift right two bytes from left to result  */
7033 /*-----------------------------------------------------------------*/
7034 static void shiftR2Left2Result (operand *left, int offl,
7035                                 operand *result, int offr,
7036                                 int shCount, int sign)
7037 {
7038   int same = pic16_sameRegs(AOP(result), AOP(left));
7039   int i;
7040   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7041
7042   if (same && (offl != offr)) { // shift right bytes
7043     if (offr < offl) {
7044        for(i=0;i<2;i++) {
7045          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7046          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7047        }
7048     } else { // just treat as different later on
7049                 same = 0;
7050     }
7051   }
7052
7053   switch(shCount) {
7054   case 0:
7055     break;
7056   case 1:
7057   case 2:
7058   case 3:
7059     /* obtain sign from left operand */
7060     if(sign)
7061       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7062     else
7063       emitCLRC;
7064
7065     if(same) {
7066       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7067       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7068     } else {
7069       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7070       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7071       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7072       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7073     }
7074
7075     while(--shCount) {
7076       if(sign)
7077         /* now get sign from already assigned result (avoid BANKSEL) */
7078         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7079       else
7080         emitCLRC;
7081       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7082       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7083     }
7084     break;
7085   case 4:
7086   case 5:
7087     if(same) {
7088
7089       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7090       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7091       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7092
7093       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7094       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7095       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7096       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7097     } else {
7098       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7099       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7100       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7101
7102       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7103       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7104       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7105       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7106       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7107     }
7108
7109     if(shCount >=5) {
7110       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7111       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7112     }
7113
7114     if(sign) {
7115       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7116       pic16_emitpcode(POC_BTFSC,
7117                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7118       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7119     }
7120
7121     break;
7122
7123   case 6:
7124     if(same) {
7125
7126       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7127       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7128
7129       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7130       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7131       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7132       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7133       if(sign) {
7134         pic16_emitpcode(POC_BTFSC,
7135                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7136         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7137       }
7138       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7139       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7140       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7141       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7142     } else {
7143       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7144       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7145       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7146       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7147       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7148       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7149       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7150       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7151       if(sign) {
7152         pic16_emitpcode(POC_BTFSC,
7153                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7154         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7155       }
7156       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7157       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7158
7159
7160     }
7161
7162     break;
7163   case 7:
7164     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7165     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7166     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7167     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7168     if(sign) {
7169       emitSKPNC;
7170       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7171     } else
7172       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7173   }
7174 }
7175
7176
7177 /*-----------------------------------------------------------------*/
7178 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7179 /*-----------------------------------------------------------------*/
7180 static void shiftLLeftOrResult (operand *left, int offl,
7181                                 operand *result, int offr, int shCount)
7182 {
7183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7184
7185     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7186     /* shift left accumulator */
7187     AccLsh(shCount, 1);
7188     /* or with result */
7189     /* back to result */
7190     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7191 }
7192
7193 /*-----------------------------------------------------------------*/
7194 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7195 /*-----------------------------------------------------------------*/
7196 static void shiftRLeftOrResult (operand *left, int offl,
7197                                 operand *result, int offr, int shCount)
7198 {
7199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7200
7201     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7202     /* shift right accumulator */
7203     AccRsh(shCount, 1);
7204     /* or with result */
7205     /* back to result */
7206     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7207 }
7208
7209 /*-----------------------------------------------------------------*/
7210 /* genlshOne - left shift a one byte quantity by known count       */
7211 /*-----------------------------------------------------------------*/
7212 static void genlshOne (operand *result, operand *left, int shCount)
7213 {
7214     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7215     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7216 }
7217
7218 /*-----------------------------------------------------------------*/
7219 /* genlshTwo - left shift two bytes by known amount != 0           */
7220 /*-----------------------------------------------------------------*/
7221 static void genlshTwo (operand *result,operand *left, int shCount)
7222 {
7223     int size;
7224
7225     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7226     size = pic16_getDataSize(result);
7227
7228     /* if shCount >= 8 */
7229     if (shCount >= 8) {
7230         shCount -= 8 ;
7231
7232         if (size > 1){
7233             if (shCount)
7234                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7235             else
7236                 movLeft2Result(left, LSB, result, MSB16);
7237         }
7238         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7239     }
7240
7241     /*  1 <= shCount <= 7 */
7242     else {
7243         if(size == 1)
7244             shiftL1Left2Result(left, LSB, result, LSB, shCount);
7245         else
7246             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7247     }
7248 }
7249
7250 /*-----------------------------------------------------------------*/
7251 /* shiftLLong - shift left one long from left to result            */
7252 /* offr = LSB or MSB16                                             */
7253 /*-----------------------------------------------------------------*/
7254 static void shiftLLong (operand *left, operand *result, int offr )
7255 {
7256     int size = AOP_SIZE(result);
7257     int same = pic16_sameRegs(AOP(left),AOP(result));
7258         int i;
7259
7260     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7261
7262         if (same && (offr == MSB16)) { //shift one byte
7263                 for(i=size-1;i>=MSB16;i--) {
7264                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7265                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7266                 }
7267         } else {
7268                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7269         }
7270
7271     if (size > LSB+offr ){
7272                 if (same) {
7273                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7274                 } else {
7275                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7276                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7277                 }
7278          }
7279
7280     if(size > MSB16+offr){
7281                 if (same) {
7282                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7283                 } else {
7284                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7285                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7286                 }
7287     }
7288
7289     if(size > MSB24+offr){
7290                 if (same) {
7291                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7292                 } else {
7293                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7294                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7295                 }
7296     }
7297
7298     if(size > MSB32+offr){
7299                 if (same) {
7300                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7301                 } else {
7302                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7303                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7304                 }
7305     }
7306     if(offr != LSB)
7307                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7308
7309 }
7310
7311 /*-----------------------------------------------------------------*/
7312 /* genlshFour - shift four byte by a known amount != 0             */
7313 /*-----------------------------------------------------------------*/
7314 static void genlshFour (operand *result, operand *left, int shCount)
7315 {
7316     int size;
7317
7318     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7319     size = AOP_SIZE(result);
7320
7321     /* if shifting more that 3 bytes */
7322     if (shCount >= 24 ) {
7323         shCount -= 24;
7324         if (shCount)
7325             /* lowest order of left goes to the highest
7326             order of the destination */
7327             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7328         else
7329             movLeft2Result(left, LSB, result, MSB32);
7330
7331                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7332                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7333                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7334
7335         return;
7336     }
7337
7338     /* more than two bytes */
7339     else if ( shCount >= 16 ) {
7340         /* lower order two bytes goes to higher order two bytes */
7341         shCount -= 16;
7342         /* if some more remaining */
7343         if (shCount)
7344             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7345         else {
7346             movLeft2Result(left, MSB16, result, MSB32);
7347             movLeft2Result(left, LSB, result, MSB24);
7348         }
7349                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7350                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7351         return;
7352     }
7353
7354     /* if more than 1 byte */
7355     else if ( shCount >= 8 ) {
7356         /* lower order three bytes goes to higher order  three bytes */
7357         shCount -= 8;
7358         if(size == 2){
7359             if(shCount)
7360                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7361             else
7362                 movLeft2Result(left, LSB, result, MSB16);
7363         }
7364         else{   /* size = 4 */
7365             if(shCount == 0){
7366                 movLeft2Result(left, MSB24, result, MSB32);
7367                 movLeft2Result(left, MSB16, result, MSB24);
7368                 movLeft2Result(left, LSB, result, MSB16);
7369                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7370             }
7371             else if(shCount == 1)
7372                 shiftLLong(left, result, MSB16);
7373             else{
7374                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7375                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7376                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7377                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7378             }
7379         }
7380     }
7381
7382     /* 1 <= shCount <= 7 */
7383     else if(shCount <= 3)
7384     {
7385         shiftLLong(left, result, LSB);
7386         while(--shCount >= 1)
7387             shiftLLong(result, result, LSB);
7388     }
7389     /* 3 <= shCount <= 7, optimize */
7390     else{
7391         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7392         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7393         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7394     }
7395 }
7396
7397 /*-----------------------------------------------------------------*/
7398 /* genLeftShiftLiteral - left shifting by known count              */
7399 /*-----------------------------------------------------------------*/
7400 void pic16_genLeftShiftLiteral (operand *left,
7401                                  operand *right,
7402                                  operand *result,
7403                                  iCode *ic)
7404 {
7405     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7406     int size;
7407
7408     FENTRY;
7409     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7410     pic16_freeAsmop(right,NULL,ic,TRUE);
7411
7412     pic16_aopOp(left,ic,FALSE);
7413     pic16_aopOp(result,ic,TRUE);
7414
7415     size = getSize(operandType(result));
7416
7417 #if VIEW_SIZE
7418     pic16_emitcode("; shift left ","result %d, left %d",size,
7419              AOP_SIZE(left));
7420 #endif
7421
7422     /* I suppose that the left size >= result size */
7423     if(shCount == 0){
7424         while(size--){
7425             movLeft2Result(left, size, result, size);
7426         }
7427     }
7428
7429     else if(shCount >= (size * 8))
7430         while(size--)
7431             pic16_aopPut(AOP(result),zero,size);
7432     else{
7433         switch (size) {
7434             case 1:
7435                 genlshOne (result,left,shCount);
7436                 break;
7437
7438             case 2:
7439             case 3:
7440                 genlshTwo (result,left,shCount);
7441                 break;
7442
7443             case 4:
7444                 genlshFour (result,left,shCount);
7445                 break;
7446         }
7447     }
7448     pic16_freeAsmop(left,NULL,ic,TRUE);
7449     pic16_freeAsmop(result,NULL,ic,TRUE);
7450 }
7451
7452 /*-----------------------------------------------------------------*
7453  * genMultiAsm - repeat assembly instruction for size of register.
7454  * if endian == 1, then the high byte (i.e base address + size of
7455  * register) is used first else the low byte is used first;
7456  *-----------------------------------------------------------------*/
7457 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7458 {
7459
7460   int offset = 0;
7461
7462   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7463
7464   if(!reg)
7465     return;
7466
7467   if(!endian) {
7468     endian = 1;
7469   } else {
7470     endian = -1;
7471     offset = size-1;
7472   }
7473
7474   while(size--) {
7475     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7476     offset += endian;
7477   }
7478
7479 }
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genrshOne - right shift a one byte quantity by known count      */
7483 /*-----------------------------------------------------------------*/
7484 static void genrshOne (operand *result, operand *left,
7485                        int shCount, int sign)
7486 {
7487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7488     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7489 }
7490
7491 /*-----------------------------------------------------------------*/
7492 /* genrshTwo - right shift two bytes by known amount != 0          */
7493 /*-----------------------------------------------------------------*/
7494 static void genrshTwo (operand *result,operand *left,
7495                        int shCount, int sign)
7496 {
7497   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7498   /* if shCount >= 8 */
7499   if (shCount >= 8) {
7500     shCount -= 8 ;
7501     if (shCount)
7502       shiftR1Left2Result(left, MSB16, result, LSB,
7503                          shCount, sign);
7504     else
7505       movLeft2Result(left, MSB16, result, LSB);
7506
7507     pic16_addSign (result, 1, sign);
7508   }
7509
7510   /*  1 <= shCount <= 7 */
7511   else
7512     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7513 }
7514
7515 /*-----------------------------------------------------------------*/
7516 /* shiftRLong - shift right one long from left to result           */
7517 /* offl = LSB or MSB16                                             */
7518 /*-----------------------------------------------------------------*/
7519 static void shiftRLong (operand *left, int offl,
7520                         operand *result, int sign)
7521 {
7522     int size = AOP_SIZE(result);
7523     int same = pic16_sameRegs(AOP(left),AOP(result));
7524     int i;
7525     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7526
7527         if (same && (offl == MSB16)) { //shift one byte right
7528                 for(i=MSB16;i<size;i++) {
7529                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7530                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7531                 }
7532         }
7533
7534     if(sign)
7535                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7536         else
7537                 emitCLRC;
7538
7539         if (same) {
7540                 if (offl == LSB)
7541                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7542         } else {
7543         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7544         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7545         }
7546
7547     if(offl == MSB16) {
7548         /* add sign of "a" */
7549         pic16_addSign(result, MSB32, sign);
7550         }
7551
7552         if (same) {
7553         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7554         } else {
7555         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7556         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7557         }
7558
7559         if (same) {
7560         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7561         } else {
7562         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7563         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7564         }
7565
7566         if (same) {
7567         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7568         } else {
7569         if(offl == LSB){
7570                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7571                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7572         }
7573         }
7574 }
7575
7576 /*-----------------------------------------------------------------*/
7577 /* genrshFour - shift four byte by a known amount != 0             */
7578 /*-----------------------------------------------------------------*/
7579 static void genrshFour (operand *result, operand *left,
7580                         int shCount, int sign)
7581 {
7582   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7583   /* if shifting more that 3 bytes */
7584   if(shCount >= 24 ) {
7585     shCount -= 24;
7586     if(shCount)
7587       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7588     else
7589       movLeft2Result(left, MSB32, result, LSB);
7590
7591     pic16_addSign(result, MSB16, sign);
7592   }
7593   else if(shCount >= 16){
7594     shCount -= 16;
7595     if(shCount)
7596       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7597     else{
7598       movLeft2Result(left, MSB24, result, LSB);
7599       movLeft2Result(left, MSB32, result, MSB16);
7600     }
7601     pic16_addSign(result, MSB24, sign);
7602   }
7603   else if(shCount >= 8){
7604     shCount -= 8;
7605     if(shCount == 1)
7606       shiftRLong(left, MSB16, result, sign);
7607     else if(shCount == 0){
7608       movLeft2Result(left, MSB16, result, LSB);
7609       movLeft2Result(left, MSB24, result, MSB16);
7610       movLeft2Result(left, MSB32, result, MSB24);
7611       pic16_addSign(result, MSB32, sign);
7612     }
7613     else{ //shcount >= 2
7614       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7615       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7616       /* the last shift is signed */
7617       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7618       pic16_addSign(result, MSB32, sign);
7619     }
7620   }
7621   else{   /* 1 <= shCount <= 7 */
7622     if(shCount <= 2){
7623       shiftRLong(left, LSB, result, sign);
7624       if(shCount == 2)
7625         shiftRLong(result, LSB, result, sign);
7626     }
7627     else{
7628       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7629       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7630       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7631     }
7632   }
7633 }
7634
7635 /*-----------------------------------------------------------------*/
7636 /* genRightShiftLiteral - right shifting by known count            */
7637 /*-----------------------------------------------------------------*/
7638 static void genRightShiftLiteral (operand *left,
7639                                   operand *right,
7640                                   operand *result,
7641                                   iCode *ic,
7642                                   int sign)
7643 {
7644   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7645   int lsize,res_size;
7646
7647   pic16_freeAsmop(right,NULL,ic,TRUE);
7648
7649   pic16_aopOp(left,ic,FALSE);
7650   pic16_aopOp(result,ic,TRUE);
7651
7652   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7653
7654 #if VIEW_SIZE
7655   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7656                  AOP_SIZE(left));
7657 #endif
7658
7659   lsize = pic16_getDataSize(left);
7660   res_size = pic16_getDataSize(result);
7661   /* test the LEFT size !!! */
7662
7663   /* I suppose that the left size >= result size */
7664   if (shCount == 0) {
7665     assert (res_size <= lsize);
7666     while (res_size--) {
7667       pic16_mov2f (AOP(result), AOP(left), res_size);
7668     } // for
7669   } else if (shCount >= (lsize * 8)) {
7670     if (sign) {
7671       /* 
7672        * Do NOT use
7673        *    CLRF    result
7674        *    BTFSC   left, 7
7675        *    SETF    result
7676        * even for 8-bit operands; result might be an SFR.
7677        */
7678       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7679       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7680       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7681       while (res_size--) {
7682         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7683       }
7684     } else { // unsigned
7685       while (res_size--) {
7686         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7687       }
7688     }
7689   } else { // 0 < shCount < 8*lsize
7690     switch (res_size) {
7691     case 1:
7692       genrshOne (result,left,shCount,sign);
7693       break;
7694
7695     case 2:
7696       genrshTwo (result,left,shCount,sign);
7697       break;
7698
7699     case 4:
7700       genrshFour (result,left,shCount,sign);
7701       break;
7702     default :
7703       break;
7704     }
7705   }
7706
7707   pic16_freeAsmop(left,NULL,ic,TRUE);
7708   pic16_freeAsmop(result,NULL,ic,TRUE);
7709 }
7710
7711 /*-----------------------------------------------------------------*/
7712 /* genGenericShift - generates code for left or right shifting     */
7713 /*-----------------------------------------------------------------*/
7714 static void genGenericShift (iCode *ic, int isShiftLeft)
7715 {
7716   operand *left,*right, *result;
7717   int offset;
7718   int sign, signedCount;
7719   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7720   PIC_OPCODE pos_shift, neg_shift;
7721
7722   FENTRY;
7723
7724   right = IC_RIGHT(ic);
7725   left  = IC_LEFT(ic);
7726   result = IC_RESULT(ic);
7727
7728   pic16_aopOp(right,ic,FALSE);
7729   pic16_aopOp(left,ic,FALSE);
7730   pic16_aopOp(result,ic,TRUE);
7731
7732   sign = !SPEC_USIGN(operandType (left));
7733   signedCount = !SPEC_USIGN(operandType (right));
7734
7735   /* if the shift count is known then do it
7736      as efficiently as possible */
7737   if (AOP_TYPE(right) == AOP_LIT) {
7738     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7739     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7740     // we should modify right->aopu.aop_lit here!
7741     // Instead we use abs(shCount) in genXXXShiftLiteral()...
7742     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7743     if (isShiftLeft)
7744       pic16_genLeftShiftLiteral (left,right,result,ic);
7745     else
7746       genRightShiftLiteral (left,right,result,ic, sign);
7747
7748     goto release;
7749   } // if (right is literal)
7750
7751   /* shift count is unknown then we have to form a loop.
7752    * Note: we take only the lower order byte since shifting
7753    * more than 32 bits make no sense anyway, ( the
7754    * largest size of an object can be only 32 bits )
7755    * Note: we perform arithmetic shifts if the left operand is
7756    * signed and we do an (effective) right shift, i. e. we
7757    * shift in the sign bit from the left. */
7758
7759   label_complete = newiTempLabel ( NULL );
7760   label_loop_pos = newiTempLabel ( NULL );
7761   label_loop_neg = NULL;
7762   label_negative = NULL;
7763   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7764   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7765
7766   if (signedCount) {
7767     // additional labels needed
7768     label_loop_neg = newiTempLabel ( NULL );
7769     label_negative = newiTempLabel ( NULL );
7770   } // if
7771
7772   // copy source to result -- this will effectively truncate the left operand to the size of result!
7773   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7774   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7775   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7776     pic16_mov2f (AOP(result),AOP(left), offset);
7777   } // for
7778
7779   // if result is longer than left, fill with zeros (or sign)
7780   if (AOP_SIZE(left) < AOP_SIZE(result)) {
7781     if (sign && AOP_SIZE(left) > 0) {
7782       // shift signed operand -- fill with sign
7783       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7784       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7785       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7786       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7787         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7788       } // for
7789     } else {
7790       // shift unsigned operand -- fill result with zeros
7791       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7792         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7793       } // for
7794     }
7795   } // if (size mismatch)
7796
7797   pic16_mov2w (AOP(right), 0);
7798   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7799   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7800
7801 #if 0
7802   // perform a shift by one (shift count is positive)
7803   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7804   // 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])
7805   pic16_emitpLabel (label_loop_pos->key);
7806   emitCLRC;
7807   if (sign && (pos_shift == POC_RRCF)) {
7808     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7809     emitSETC;
7810   } // if
7811   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7812   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7813   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7814 #else
7815   // perform a shift by one (shift count is positive)
7816   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7817   // 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])
7818   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7819   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7820   emitCLRC;
7821   pic16_emitpLabel (label_loop_pos->key);
7822   if (sign && (pos_shift == POC_RRCF)) {
7823     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7824     emitSETC;
7825   } // if
7826   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7827   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7828   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7829   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7830 #endif
7831
7832   if (signedCount) {
7833     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7834
7835     pic16_emitpLabel (label_negative->key);
7836     // perform a shift by -1 (shift count is negative)
7837     // 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)
7838     emitCLRC;
7839     pic16_emitpLabel (label_loop_neg->key);
7840     if (sign && (neg_shift == POC_RRCF)) {
7841       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7842       emitSETC;
7843     } // if
7844     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7845     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7846     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7847     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7848   } // if (signedCount)
7849
7850   pic16_emitpLabel (label_complete->key);
7851
7852 release:
7853   pic16_freeAsmop (right,NULL,ic,TRUE);
7854   pic16_freeAsmop(left,NULL,ic,TRUE);
7855   pic16_freeAsmop(result,NULL,ic,TRUE);
7856 }
7857
7858 static void genLeftShift (iCode *ic) {
7859   genGenericShift (ic, 1);
7860 }
7861
7862 static void genRightShift (iCode *ic) {
7863   genGenericShift (ic, 0);
7864 }
7865
7866
7867 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7868 void pic16_loadFSR0(operand *op, int lit)
7869 {
7870   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7871     if (AOP_TYPE(op) == AOP_LIT) {
7872       /* handle 12 bit integers correctly */
7873       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7874       if ((val & 0x0fff) != val) {
7875         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7876                 val, (val & 0x0fff) );
7877         val &= 0x0fff;
7878       }
7879       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7880     } else {
7881       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7882     }
7883   } else {
7884     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7885     // set up FSR0 with address of result
7886     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7887     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7888   }
7889 }
7890
7891 /*----------------------------------------------------------------*/
7892 /* pic16_derefPtr - move one byte from the location ptr points to */
7893 /*                  to WREG (doWrite == 0) or one byte from WREG   */
7894 /*                  to the location ptr points to (doWrite != 0)   */
7895 /*----------------------------------------------------------------*/
7896 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7897 {
7898   if (!IS_PTR(operandType(ptr)))
7899   {
7900     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7901     else pic16_mov2w (AOP(ptr), 0);
7902     return;
7903   }
7904
7905   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7906   /* We might determine pointer type right here: */
7907   p_type = DCL_TYPE(operandType(ptr));
7908
7909   switch (p_type) {
7910     case FPOINTER:
7911     case POINTER:
7912       if (!fsr0_setup || !*fsr0_setup)
7913       {
7914         pic16_loadFSR0( ptr, 0 );
7915         if (fsr0_setup) *fsr0_setup = 1;
7916       }
7917       if (doWrite)
7918         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7919       else
7920         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7921       break;
7922
7923     case GPOINTER:
7924       if (AOP(ptr)->aopu.aop_reg[2]) {
7925         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7926         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7927         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7928         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7929         pic16_mov2w(AOP(ptr), 2);
7930         pic16_callGenericPointerRW(doWrite, 1);
7931       } else {
7932         // data pointer (just 2 byte given)
7933         if (!fsr0_setup || !*fsr0_setup)
7934         {
7935           pic16_loadFSR0( ptr, 0 );
7936           if (fsr0_setup) *fsr0_setup = 1;
7937         }
7938         if (doWrite)
7939           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7940         else
7941           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7942       }
7943       break;
7944
7945     default:
7946       assert (0 && "invalid pointer type specified");
7947       break;
7948   }
7949 }
7950
7951 /*-----------------------------------------------------------------*/
7952 /* genUnpackBits - generates code for unpacking bits               */
7953 /*-----------------------------------------------------------------*/
7954 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7955 {
7956   int shCnt ;
7957   sym_link *etype, *letype;
7958   int blen=0, bstr=0;
7959   int lbstr;
7960   int same;
7961   pCodeOp *op;
7962
7963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7964   etype = getSpec(operandType(result));
7965   letype = getSpec(operandType(left));
7966
7967   //    if(IS_BITFIELD(etype)) {
7968   blen = SPEC_BLEN(etype);
7969   bstr = SPEC_BSTR(etype);
7970   //    }
7971
7972   lbstr = SPEC_BSTR( letype );
7973
7974   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7975       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7976
7977 #if 1
7978   if((blen == 1) && (bstr < 8)
7979       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
7980     /* it is a single bit, so use the appropriate bit instructions */
7981     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
7982
7983     same = pic16_sameRegs(AOP(left),AOP(result));
7984     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
7985     pic16_emitpcode(POC_CLRF, op);
7986
7987     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
7988       /* workaround to reduce the extra lfsr instruction */
7989       pic16_emitpcode(POC_BTFSC,
7990           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
7991     } else {
7992       assert (PIC_IS_DATA_PTR (operandType(left)));
7993       pic16_loadFSR0 (left, 0);
7994       pic16_emitpcode(POC_BTFSC,
7995           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
7996     }
7997
7998     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7999       /* unsigned bitfields result in either 0 or 1 */
8000       pic16_emitpcode(POC_INCF, op);
8001     } else {
8002       /* signed bitfields result in either 0 or -1 */
8003       pic16_emitpcode(POC_DECF, op);
8004     }
8005     if (same) {
8006       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8007     }
8008
8009     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8010     return;
8011   }
8012
8013 #endif
8014
8015   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8016     // access symbol directly
8017     pic16_mov2w (AOP(left), 0);
8018   } else {
8019     pic16_derefPtr (left, ptype, 0, NULL);
8020   }
8021
8022   /* if we have bitdisplacement then it fits   */
8023   /* into this byte completely or if length is */
8024   /* less than a byte                          */
8025   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
8026
8027     /* shift right acc */
8028     AccRsh(shCnt, 0);
8029
8030     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8031           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8032
8033     /* VR -- normally I would use the following, but since we use the hack,
8034      * to avoid the masking from AccRsh, why not mask it right now? */
8035
8036     /*
8037        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8038      */
8039
8040     /* extend signed bitfields to 8 bits */
8041     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8042     {
8043       assert (blen + bstr > 0);
8044       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8045       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8046     }
8047
8048     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8049
8050     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8051     return ;
8052   }
8053
8054   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8055   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8056   exit(EXIT_FAILURE);
8057
8058   return ;
8059 }
8060
8061
8062 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8063 {
8064   int size, offset = 0, leoffset=0 ;
8065
8066         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8067         pic16_aopOp(result, ic, TRUE);
8068
8069         FENTRY;
8070
8071         size = AOP_SIZE(result);
8072 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8073
8074
8075 #if 1
8076         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8077                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8078                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8079                 goto release;
8080         }
8081 #endif
8082
8083         if(AOP(left)->aopu.pcop->type == PO_DIR)
8084                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8085
8086         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8087
8088         while (size--) {
8089                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8090
8091 //              pic16_DumpOp("(result)",result);
8092                 if(pic16_isLitAop(AOP(result))) {
8093                         pic16_mov2w(AOP(left), offset); // patch 8
8094                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8095                 } else {
8096                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8097                                 pic16_popGet(AOP(left), offset), //patch 8
8098                                 pic16_popGet(AOP(result), offset)));
8099                 }
8100
8101                 offset++;
8102                 leoffset++;
8103         }
8104
8105 release:
8106     pic16_freeAsmop(result,NULL,ic,TRUE);
8107 }
8108
8109
8110
8111 /*-----------------------------------------------------------------*/
8112 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8113 /*-----------------------------------------------------------------*/
8114 static void genNearPointerGet (operand *left,
8115                                operand *result,
8116                                iCode *ic)
8117 {
8118 //  asmop *aop = NULL;
8119   //regs *preg = NULL ;
8120   sym_link *rtype, *retype;
8121   sym_link *ltype, *letype;
8122
8123     FENTRY;
8124
8125     rtype = operandType(result);
8126     retype= getSpec(rtype);
8127     ltype = operandType(left);
8128     letype= getSpec(ltype);
8129
8130     pic16_aopOp(left,ic,FALSE);
8131
8132 //    pic16_DumpOp("(left)",left);
8133 //    pic16_DumpOp("(result)",result);
8134
8135     /* if left is rematerialisable and
8136      * result is not bit variable type and
8137      * the left is pointer to data space i.e
8138      * lower 128 bytes of space */
8139
8140     if (AOP_TYPE(left) == AOP_PCODE
8141       && !IS_BITFIELD(retype)
8142       && DCL_TYPE(ltype) == POINTER) {
8143
8144         genDataPointerGet (left,result,ic);
8145         pic16_freeAsmop(left, NULL, ic, TRUE);
8146         return ;
8147     }
8148
8149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8150     pic16_aopOp (result,ic,TRUE);
8151
8152     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8153
8154 #if 1
8155     if(IS_BITFIELD( retype )
8156       && (SPEC_BLEN(operandType(result))==1)
8157     ) {
8158       iCode *nextic;
8159       pCodeOp *jop;
8160       int bitstrt, bytestrt;
8161
8162         /* if this is bitfield of size 1, see if we are checking the value
8163          * of a single bit in an if-statement,
8164          * if yes, then don't generate usual code, but execute the
8165          * genIfx directly -- VR */
8166
8167         nextic = ic->next;
8168
8169         /* CHECK: if next iCode is IFX
8170          * and current result operand is nextic's conditional operand
8171          * and current result operand live ranges ends at nextic's key number
8172          */
8173         if((nextic->op == IFX)
8174           && (result == IC_COND(nextic))
8175           && (OP_LIVETO(result) == nextic->seq)
8176           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
8177           ) {
8178             /* everything is ok then */
8179             /* find a way to optimize the genIfx iCode */
8180
8181             bytestrt = SPEC_BSTR(operandType(result))/8;
8182             bitstrt = SPEC_BSTR(operandType(result))%8;
8183
8184             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8185
8186             genIfxpCOpJump(nextic, jop);
8187
8188             pic16_freeAsmop(left, NULL, ic, TRUE);
8189             pic16_freeAsmop(result, NULL, ic, TRUE);
8190             return;
8191         }
8192     }
8193 #endif
8194
8195     /* if bitfield then unpack the bits */
8196     if (IS_BITFIELD(letype))
8197       genUnpackBits (result, left, NULL, POINTER);
8198     else {
8199       /* we have can just get the values */
8200       int size = AOP_SIZE(result);
8201       int offset = 0;
8202
8203       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8204
8205       pic16_loadFSR0( left, 0 );
8206
8207       while(size--) {
8208         if(size) {
8209           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8210                 pic16_popGet(AOP(result), offset++)));
8211         } else {
8212           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8213                 pic16_popGet(AOP(result), offset++)));
8214         }
8215       }
8216     }
8217
8218 #if 0
8219     /* now some housekeeping stuff */
8220     if (aop) {
8221       /* we had to allocate for this iCode */
8222       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8223       pic16_freeAsmop(NULL,aop,ic,TRUE);
8224     } else {
8225       /* we did not allocate which means left
8226        * already in a pointer register, then
8227        * if size > 0 && this could be used again
8228        * we have to point it back to where it
8229        * belongs */
8230       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8231       if (AOP_SIZE(result) > 1
8232         && !OP_SYMBOL(left)->remat
8233         && ( OP_SYMBOL(left)->liveTo > ic->seq
8234             || ic->depth )) {
8235 //        int size = AOP_SIZE(result) - 1;
8236 //        while (size--)
8237 //          pic16_emitcode("dec","%s",rname);
8238         }
8239     }
8240 #endif
8241
8242     /* done */
8243     pic16_freeAsmop(left,NULL,ic,TRUE);
8244     pic16_freeAsmop(result,NULL,ic,TRUE);
8245 }
8246
8247 /*-----------------------------------------------------------------*/
8248 /* genGenPointerGet - gget value from generic pointer space        */
8249 /*-----------------------------------------------------------------*/
8250 static void genGenPointerGet (operand *left,
8251                               operand *result, iCode *ic)
8252 {
8253   int size;
8254   sym_link *letype = getSpec(operandType(left));
8255
8256   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8257   pic16_aopOp(left,ic,FALSE);
8258   pic16_aopOp(result,ic,TRUE);
8259   size = AOP_SIZE(result);
8260
8261   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8262
8263   /* if bit then unpack */
8264   if (IS_BITFIELD(letype)) {
8265     genUnpackBits(result,left,"BAD",GPOINTER);
8266     goto release;
8267   }
8268
8269   /* set up WREG:PRODL:FSR0L with address from left */
8270   mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8271   mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8272   pic16_mov2w(AOP(left), 2);
8273   pic16_callGenericPointerRW(0, size);
8274
8275   assignResultValue(result, size, 1);
8276
8277 release:
8278   pic16_freeAsmop(left,NULL,ic,TRUE);
8279   pic16_freeAsmop(result,NULL,ic,TRUE);
8280 }
8281
8282 /*-----------------------------------------------------------------*/
8283 /* genConstPointerGet - get value from const generic pointer space */
8284 /*-----------------------------------------------------------------*/
8285 static void genConstPointerGet (operand *left,
8286                                 operand *result, iCode *ic)
8287 {
8288   //sym_link *retype = getSpec(operandType(result));
8289   // symbol *albl = newiTempLabel(NULL);        // patch 15
8290   // symbol *blbl = newiTempLabel(NULL);        //
8291   // PIC_OPCODE poc;                            // patch 15
8292   int size;
8293   int offset = 0;
8294
8295   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8296   pic16_aopOp(left,ic,FALSE);
8297   pic16_aopOp(result,ic,TRUE);
8298   size = AOP_SIZE(result);
8299
8300   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8301
8302   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8303
8304   // set up table pointer
8305   if( (AOP_TYPE(left) == AOP_PCODE)
8306       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8307           || (AOP(left)->aopu.pcop->type == PO_DIR)))
8308     {
8309       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8310       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8311       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8312       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8313       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8314       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8315   } else {
8316     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8317     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8318     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8319   }
8320
8321   while(size--) {
8322     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8323     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8324     offset++;
8325   }
8326
8327   pic16_freeAsmop(left,NULL,ic,TRUE);
8328   pic16_freeAsmop(result,NULL,ic,TRUE);
8329 }
8330
8331
8332 /*-----------------------------------------------------------------*/
8333 /* genPointerGet - generate code for pointer get                   */
8334 /*-----------------------------------------------------------------*/
8335 static void genPointerGet (iCode *ic)
8336 {
8337   operand *left, *result ;
8338   sym_link *type, *etype;
8339   int p_type;
8340
8341     FENTRY;
8342
8343     left = IC_LEFT(ic);
8344     result = IC_RESULT(ic) ;
8345
8346     /* depending on the type of pointer we need to
8347     move it to the correct pointer register */
8348     type = operandType(left);
8349     etype = getSpec(type);
8350
8351 #if 0
8352     if (IS_PTR_CONST(type))
8353 #else
8354     if (IS_CODEPTR(type))
8355 #endif
8356       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8357
8358     /* if left is of type of pointer then it is simple */
8359     if (IS_PTR(type) && !IS_FUNC(type->next))
8360       p_type = DCL_TYPE(type);
8361     else {
8362       /* we have to go by the storage class */
8363       p_type = PTR_TYPE(SPEC_OCLS(etype));
8364
8365       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8366
8367       if (SPEC_OCLS(etype)->codesp ) {
8368         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8369         //p_type = CPOINTER ;
8370       } else
8371       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8372         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8373         /*p_type = FPOINTER ;*/
8374       } else
8375       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8376         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8377         /* p_type = PPOINTER; */
8378       } else
8379       if (SPEC_OCLS(etype) == idata ) {
8380         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8381         /* p_type = IPOINTER; */
8382       } else {
8383         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8384         /* p_type = POINTER ; */
8385       }
8386     }
8387
8388     /* now that we have the pointer type we assign
8389     the pointer values */
8390     switch (p_type) {
8391       case POINTER:
8392       case FPOINTER:
8393       case IPOINTER:
8394         genNearPointerGet (left,result,ic);
8395         break;
8396
8397 #if 0
8398       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8399       case PPOINTER:
8400         genPagedPointerGet(left,result,ic);
8401         break;
8402
8403       case FPOINTER:
8404         genFarPointerGet (left,result,ic);
8405         break;
8406 #endif
8407
8408       case CPOINTER:
8409         genConstPointerGet (left,result,ic);
8410         //pic16_emitcodePointerGet (left,result,ic);
8411         break;
8412
8413       case GPOINTER:
8414 #if 0
8415       if (IS_PTR_CONST(type))
8416         genConstPointerGet (left,result,ic);
8417       else
8418 #endif
8419         genGenPointerGet (left,result,ic);
8420       break;
8421
8422     default:
8423       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8424               "genPointerGet: illegal pointer type");
8425
8426     }
8427 }
8428
8429 /*-----------------------------------------------------------------*/
8430 /* genPackBits - generates code for packed bit storage             */
8431 /*-----------------------------------------------------------------*/
8432 static void genPackBits (sym_link    *etype , operand *result,
8433                          operand *right ,
8434                          char *rname, int p_type)
8435 {
8436   int shCnt = 0 ;
8437   int offset = 0  ;
8438   int rLen = 0 ;
8439   int blen, bstr ;
8440   int shifted_and_masked = 0;
8441   unsigned long lit = (unsigned long)-1;
8442   sym_link *retype;
8443
8444   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8445   blen = SPEC_BLEN(etype);
8446   bstr = SPEC_BSTR(etype);
8447
8448   retype = getSpec(operandType(right));
8449
8450   if(AOP_TYPE(right) == AOP_LIT) {
8451     lit = ulFromVal (AOP(right)->aopu.aop_lit);
8452
8453     if((blen == 1) && (bstr < 8)) {
8454       /* it is a single bit, so use the appropriate bit instructions */
8455
8456       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8457
8458       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8459         /* workaround to reduce the extra lfsr instruction */
8460         if(lit) {
8461           pic16_emitpcode(POC_BSF,
8462               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8463         } else {
8464           pic16_emitpcode(POC_BCF,
8465               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8466         }
8467       } else {
8468         if (PIC_IS_DATA_PTR(operandType(result))) {
8469           pic16_loadFSR0(result, 0);
8470           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8471               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8472         } else {
8473           /* get old value */
8474           pic16_derefPtr (result, p_type, 0, NULL);
8475           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8476               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8477           /* write back new value */
8478           pic16_derefPtr (result, p_type, 1, NULL);
8479         }
8480       }
8481
8482       return;
8483     }
8484     /* IORLW below is more efficient */
8485     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8486     lit = (lit & ((1UL << blen) - 1)) << bstr;
8487     shifted_and_masked = 1;
8488     offset++;
8489   } else
8490     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8491         && IS_BITFIELD(retype)
8492         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8493         && (blen == 1)) {
8494       int rblen, rbstr;
8495
8496       rblen = SPEC_BLEN( retype );
8497       rbstr = SPEC_BSTR( retype );
8498
8499       if(IS_BITFIELD(etype)) {
8500         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8501         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8502       } else {
8503         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8504       }
8505
8506       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8507
8508       if(IS_BITFIELD(etype)) {
8509         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8510       } else {
8511         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8512       }
8513
8514       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8515
8516       return;
8517     } else {
8518       /* move right to W */
8519       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8520     }
8521
8522   /* if the bit length is less than or   */
8523   /* it exactly fits a byte then         */
8524   if((shCnt=SPEC_BSTR(etype))
8525       || SPEC_BLEN(etype) <= 8 )  {
8526     int fsr0_setup = 0;
8527
8528     if (blen != 8 || (bstr % 8) != 0) {
8529       // we need to combine the value with the old value
8530       if(!shifted_and_masked)
8531       {
8532         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8533
8534         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8535             SPEC_BSTR(etype), SPEC_BLEN(etype));
8536
8537         /* shift left acc, do NOT mask the result again */
8538         AccLsh(shCnt, 0);
8539
8540         /* using PRODH as a temporary register here */
8541         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8542       }
8543
8544       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8545         || IS_DIRECT(result)) {
8546         /* access symbol directly */
8547         pic16_mov2w (AOP(result), 0);
8548       } else {
8549         /* get old value */
8550         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8551       }
8552 #if 1
8553       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8554             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8555                             (unsigned char)(0xff >> (8-bstr))) ));
8556       if (!shifted_and_masked) {
8557         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8558       } else {
8559         /* We have the shifted and masked (literal) right value in `lit' */
8560         if (lit != 0)
8561           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8562       }
8563     } else { // if (blen == 8 && (bstr % 8) == 0)
8564         if (shifted_and_masked) {
8565             // move right (literal) to WREG (only case where right is not yet in WREG)
8566             pic16_mov2w(AOP(right), (bstr / 8));
8567         }
8568     }
8569
8570     /* write new value back */
8571     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8572         || IS_DIRECT(result)) {
8573       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8574     } else {
8575       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8576     }
8577 #endif
8578
8579     return;
8580   }
8581
8582
8583 #if 0
8584   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8585   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8586   exit(EXIT_FAILURE);
8587 #endif
8588
8589
8590   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
8591   rLen = SPEC_BLEN(etype)-8;
8592
8593   /* now generate for lengths greater than one byte */
8594   while (1) {
8595     rLen -= 8 ;
8596     if (rLen <= 0 ) {
8597       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8598       break ;
8599     }
8600
8601     switch (p_type) {
8602       case POINTER:
8603         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8604         break;
8605
8606         /*
8607            case FPOINTER:
8608            MOVA(l);
8609            pic16_emitcode("movx","@dptr,a");
8610            break;
8611
8612            case GPOINTER:
8613            MOVA(l);
8614            DEBUGpic16_emitcode(";lcall","__gptrput");
8615            break;
8616          */
8617       default:
8618         assert(0);
8619     }
8620
8621
8622     pic16_mov2w(AOP(right), offset++);
8623   }
8624
8625   /* last last was not complete */
8626   if (rLen)   {
8627     /* save the byte & read byte */
8628     switch (p_type) {
8629       case POINTER:
8630         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8631         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8632         break;
8633
8634         /*
8635            case FPOINTER:
8636            pic16_emitcode ("mov","b,a");
8637            pic16_emitcode("movx","a,@dptr");
8638            break;
8639
8640            case GPOINTER:
8641            pic16_emitcode ("push","b");
8642            pic16_emitcode ("push","acc");
8643            pic16_emitcode ("lcall","__gptrget");
8644            pic16_emitcode ("pop","b");
8645            break;
8646          */
8647       default:
8648         assert(0);
8649     }
8650     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8651     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8652     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8653     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8654     //        pic16_emitcode ("orl","a,b");
8655   }
8656
8657   //    if (p_type == GPOINTER)
8658   //        pic16_emitcode("pop","b");
8659
8660   switch (p_type) {
8661
8662     case POINTER:
8663       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8664       //        pic16_emitcode("mov","@%s,a",rname);
8665       break;
8666       /*
8667          case FPOINTER:
8668          pic16_emitcode("movx","@dptr,a");
8669          break;
8670
8671          case GPOINTER:
8672          DEBUGpic16_emitcode(";lcall","__gptrput");
8673          break;
8674        */
8675     default:
8676       assert(0);
8677   }
8678
8679   //    pic16_freeAsmop(right, NULL, ic, TRUE);
8680 }
8681
8682 /*-----------------------------------------------------------------*/
8683 /* genDataPointerSet - remat pointer to data space                 */
8684 /*-----------------------------------------------------------------*/
8685 static void genDataPointerSet(operand *right,
8686                               operand *result,
8687                               iCode *ic)
8688 {
8689   int size, offset = 0, resoffset=0 ;
8690
8691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8692     pic16_aopOp(right,ic,FALSE);
8693
8694     size = AOP_SIZE(right);
8695
8696 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8697
8698 #if 0
8699     if ( AOP_TYPE(result) == AOP_PCODE) {
8700       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8701               AOP(result)->aopu.pcop->name,
8702                 (AOP(result)->aopu.pcop->type == PO_DIR)?
8703               PCOR(AOP(result)->aopu.pcop)->instance:
8704               PCOI(AOP(result)->aopu.pcop)->offset);
8705     }
8706 #endif
8707
8708     if(AOP(result)->aopu.pcop->type == PO_DIR)
8709       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8710
8711     while (size--) {
8712       if (AOP_TYPE(right) == AOP_LIT) {
8713         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8714         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8715       } else {
8716         pic16_mov2w(AOP(right), offset);
8717         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8718       }
8719       offset++;
8720       resoffset++;
8721     }
8722
8723     pic16_freeAsmop(right,NULL,ic,TRUE);
8724 }
8725
8726
8727
8728 /*-----------------------------------------------------------------*/
8729 /* genNearPointerSet - pic16_emitcode for near pointer put         */
8730 /*-----------------------------------------------------------------*/
8731 static void genNearPointerSet (operand *right,
8732                                operand *result,
8733                                iCode *ic)
8734 {
8735   asmop *aop = NULL;
8736   sym_link *retype;
8737   sym_link *ptype = operandType(result);
8738   sym_link *resetype;
8739
8740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741     retype= getSpec(operandType(right));
8742     resetype = getSpec(operandType(result));
8743
8744     pic16_aopOp(result,ic,FALSE);
8745
8746     /* if the result is rematerializable &
8747      * in data space & not a bit variable */
8748
8749     /* and result is not a bit variable */
8750     if (AOP_TYPE(result) == AOP_PCODE
8751       && DCL_TYPE(ptype) == POINTER
8752       && !IS_BITFIELD(retype)
8753       && !IS_BITFIELD(resetype)) {
8754
8755         genDataPointerSet (right,result,ic);
8756         pic16_freeAsmop(result,NULL,ic,TRUE);
8757       return;
8758     }
8759
8760     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8761     pic16_aopOp(right,ic,FALSE);
8762     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8763
8764     /* if bitfield then unpack the bits */
8765     if (IS_BITFIELD(resetype)) {
8766       genPackBits (resetype, result, right, NULL, POINTER);
8767     } else {
8768       /* we have can just get the values */
8769       int size = AOP_SIZE(right);
8770       int offset = 0 ;
8771
8772         pic16_loadFSR0(result, 0);
8773
8774         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8775         while (size--) {
8776           if (pic16_isLitOp(right)) {
8777             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8778             if (size) {
8779               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8780             } else {
8781               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8782             }
8783           } else { // no literal
8784             if(size) {
8785               pic16_emitpcode(POC_MOVFF,
8786                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8787                   pic16_popCopyReg(&pic16_pc_postinc0)));
8788             } else {
8789               pic16_emitpcode(POC_MOVFF,
8790                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8791                   pic16_popCopyReg(&pic16_pc_indf0)));
8792             }
8793           }
8794
8795           offset++;
8796         }
8797     }
8798
8799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8800     /* now some housekeeping stuff */
8801     if (aop) {
8802       /* we had to allocate for this iCode */
8803       pic16_freeAsmop(NULL,aop,ic,TRUE);
8804     } else {
8805       /* we did not allocate which means left
8806        * already in a pointer register, then
8807        * if size > 0 && this could be used again
8808        * we have to point it back to where it
8809        * belongs */
8810       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8811       if (AOP_SIZE(right) > 1
8812         && !OP_SYMBOL(result)->remat
8813         && ( OP_SYMBOL(result)->liveTo > ic->seq
8814         || ic->depth )) {
8815
8816           int size = AOP_SIZE(right) - 1;
8817
8818             while (size--)
8819               pic16_emitcode("decf","fsr0,f");
8820               //pic16_emitcode("dec","%s",rname);
8821       }
8822     }
8823
8824     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825     /* done */
8826 //release:
8827     pic16_freeAsmop(right,NULL,ic,TRUE);
8828     pic16_freeAsmop(result,NULL,ic,TRUE);
8829 }
8830
8831 /*-----------------------------------------------------------------*/
8832 /* genGenPointerSet - set value from generic pointer space         */
8833 /*-----------------------------------------------------------------*/
8834 static void genGenPointerSet (operand *right,
8835                               operand *result, iCode *ic)
8836 {
8837   int size;
8838   sym_link *retype = getSpec(operandType(result));
8839
8840     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8841
8842     pic16_aopOp(result,ic,FALSE);
8843     pic16_aopOp(right,ic,FALSE);
8844     size = AOP_SIZE(right);
8845
8846     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8847
8848
8849     /* if bit then unpack */
8850     if (IS_BITFIELD(retype)) {
8851 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8852       genPackBits(retype,result,right,"dptr",GPOINTER);
8853       goto release;
8854     }
8855
8856     size = AOP_SIZE(right);
8857
8858     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8859
8860
8861     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8862
8863     /* value of right+0 is placed on stack, which will be retrieved
8864      * by the support function thus restoring the stack. The important
8865      * thing is that there is no need to manually restore stack pointer
8866      * here */
8867     pushaop(AOP(right), 0);
8868 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8869     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8870     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8871     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8872
8873     /* load address to write to in WREG:FSR0H:FSR0L */
8874     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8875                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
8876     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8877                                 pic16_popCopyReg(&pic16_pc_prodl)));
8878     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8879
8880     pic16_callGenericPointerRW(1, size);
8881
8882 release:
8883     pic16_freeAsmop(right,NULL,ic,TRUE);
8884     pic16_freeAsmop(result,NULL,ic,TRUE);
8885 }
8886
8887 /*-----------------------------------------------------------------*/
8888 /* genPointerSet - stores the value into a pointer location        */
8889 /*-----------------------------------------------------------------*/
8890 static void genPointerSet (iCode *ic)
8891 {
8892   operand *right, *result ;
8893   sym_link *type, *etype;
8894   int p_type;
8895
8896     FENTRY;
8897
8898     right = IC_RIGHT(ic);
8899     result = IC_RESULT(ic) ;
8900
8901     /* depending on the type of pointer we need to
8902     move it to the correct pointer register */
8903     type = operandType(result);
8904     etype = getSpec(type);
8905
8906     /* if left is of type of pointer then it is simple */
8907     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8908         p_type = DCL_TYPE(type);
8909     }
8910     else {
8911         /* we have to go by the storage class */
8912         p_type = PTR_TYPE(SPEC_OCLS(etype));
8913
8914 /*      if (SPEC_OCLS(etype)->codesp ) { */
8915 /*          p_type = CPOINTER ;  */
8916 /*      } */
8917 /*      else */
8918 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8919 /*              p_type = FPOINTER ; */
8920 /*          else */
8921 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8922 /*                  p_type = PPOINTER ; */
8923 /*              else */
8924 /*                  if (SPEC_OCLS(etype) == idata ) */
8925 /*                      p_type = IPOINTER ; */
8926 /*                  else */
8927 /*                      p_type = POINTER ; */
8928     }
8929
8930     /* now that we have the pointer type we assign
8931     the pointer values */
8932     switch (p_type) {
8933       case POINTER:
8934       case FPOINTER:
8935       case IPOINTER:
8936         genNearPointerSet (right,result,ic);
8937         break;
8938
8939 #if 0
8940       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8941       case PPOINTER:
8942         genPagedPointerSet (right,result,ic);
8943         break;
8944
8945       case FPOINTER:
8946         genFarPointerSet (right,result,ic);
8947         break;
8948 #endif
8949
8950       case GPOINTER:
8951         genGenPointerSet (right,result,ic);
8952         break;
8953
8954       default:
8955         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8956           "genPointerSet: illegal pointer type");
8957     }
8958 }
8959
8960 /*-----------------------------------------------------------------*/
8961 /* genIfx - generate code for Ifx statement                        */
8962 /*-----------------------------------------------------------------*/
8963 static void genIfx (iCode *ic, iCode *popIc)
8964 {
8965   operand *cond = IC_COND(ic);
8966   int isbit =0;
8967
8968     FENTRY;
8969
8970     pic16_aopOp(cond,ic,FALSE);
8971
8972     /* get the value into acc */
8973     if (AOP_TYPE(cond) != AOP_CRY)
8974       pic16_toBoolean(cond);
8975     else
8976       isbit = 1;
8977     /* the result is now in the accumulator */
8978     pic16_freeAsmop(cond,NULL,ic,TRUE);
8979
8980     /* if there was something to be popped then do it */
8981     if (popIc)
8982       genIpop(popIc);
8983
8984     /* if the condition is  a bit variable */
8985     if (isbit && IS_ITEMP(cond) &&
8986         SPIL_LOC(cond)) {
8987       genIfxJump(ic,"c");
8988       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8989     } else {
8990       if (isbit && !IS_ITEMP(cond))
8991         genIfxJump(ic,OP_SYMBOL(cond)->rname);
8992         else
8993         genIfxJump(ic,"a");
8994     }
8995     ic->generated = 1;
8996 }
8997
8998 /*-----------------------------------------------------------------*/
8999 /* genAddrOf - generates code for address of                       */
9000 /*-----------------------------------------------------------------*/
9001 static void genAddrOf (iCode *ic)
9002 {
9003   operand *result, *left;
9004   int size;
9005   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9006   pCodeOp *pcop0, *pcop1, *pcop2;
9007
9008     FENTRY;
9009
9010     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9011
9012     sym = OP_SYMBOL( IC_LEFT(ic) );
9013
9014     if(sym->onStack) {
9015       /* get address of symbol on stack */
9016       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9017 #if 0
9018       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9019                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9020 #endif
9021
9022       // operands on stack are accessible via "FSR2 + index" with index
9023       // starting at 2 for arguments and growing from 0 downwards for
9024       // local variables (index == 0 is not assigned so we add one here)
9025       {
9026         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9027
9028           if (soffs <= 0) {
9029             assert (soffs < 0);
9030             soffs++;
9031           } // if
9032
9033           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9034           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9035           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9036           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9037           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9038           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9039           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9040       }
9041
9042       goto release;
9043     }
9044
9045 //      if(pic16_debug_verbose) {
9046 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9047 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9048 //      }
9049
9050     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9051     size = AOP_SIZE(IC_RESULT(ic));
9052
9053     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9054     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9055     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9056
9057     if (size == 3) {
9058       pic16_emitpcode(POC_MOVLW, pcop0);
9059       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9060       pic16_emitpcode(POC_MOVLW, pcop1);
9061       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9062       pic16_emitpcode(POC_MOVLW, pcop2);
9063       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9064     } else
9065     if (size == 2) {
9066       pic16_emitpcode(POC_MOVLW, pcop0);
9067       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9068       pic16_emitpcode(POC_MOVLW, pcop1);
9069     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9070     } else {
9071       pic16_emitpcode(POC_MOVLW, pcop0);
9072       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9073     }
9074
9075     pic16_freeAsmop(left, NULL, ic, FALSE);
9076 release:
9077     pic16_freeAsmop(result,NULL,ic,TRUE);
9078 }
9079
9080
9081 /*-----------------------------------------------------------------*/
9082 /* genAssign - generate code for assignment                        */
9083 /*-----------------------------------------------------------------*/
9084 static void genAssign (iCode *ic)
9085 {
9086   operand *result, *right;
9087   sym_link *restype, *rtype;
9088   int size, offset,know_W;
9089   unsigned long lit = 0L;
9090
9091     result = IC_RESULT(ic);
9092     right  = IC_RIGHT(ic) ;
9093
9094     FENTRY;
9095
9096     /* if they are the same */
9097     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9098       return ;
9099
9100     /* reversed order operands are aopOp'ed so that result operand
9101      * is effective in case right is a stack symbol. This maneauver
9102      * allows to use the _G.resDirect flag later */
9103      pic16_aopOp(result,ic,TRUE);
9104     pic16_aopOp(right,ic,FALSE);
9105
9106     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9107
9108     /* if they are the same registers */
9109     if (pic16_sameRegs(AOP(right),AOP(result)))
9110       goto release;
9111
9112     /* if the result is a bit */
9113     if (AOP_TYPE(result) == AOP_CRY) {
9114       /* if the right size is a literal then
9115          we know what the value is */
9116       if (AOP_TYPE(right) == AOP_LIT) {
9117
9118         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9119             pic16_popGet(AOP(result),0));
9120
9121         if (((int) operandLitValue(right)))
9122           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9123               AOP(result)->aopu.aop_dir,
9124               AOP(result)->aopu.aop_dir);
9125         else
9126           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9127               AOP(result)->aopu.aop_dir,
9128               AOP(result)->aopu.aop_dir);
9129
9130         goto release;
9131       }
9132
9133       /* the right is also a bit variable */
9134       if (AOP_TYPE(right) == AOP_CRY) {
9135         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9136         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9137         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9138
9139         goto release ;
9140       }
9141
9142       /* we need to or */
9143       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9144       pic16_toBoolean(right);
9145       emitSKPZ;
9146       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9147       //pic16_aopPut(AOP(result),"a",0);
9148       goto release ;
9149     }
9150
9151     /* bit variables done */
9152     /* general case */
9153     size = AOP_SIZE(result);
9154     offset = 0 ;
9155
9156   /* bit variables done */
9157   /* general case */
9158   size = AOP_SIZE(result);
9159   restype = operandType(result);
9160   rtype = operandType(right);
9161   offset = 0 ;
9162
9163   if(AOP_TYPE(right) == AOP_LIT) {
9164     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9165     {
9166       lit = ulFromVal (AOP(right)->aopu.aop_lit);
9167
9168       /* patch tag for literals that are cast to pointers */
9169       if (IS_CODEPTR(restype)) {
9170         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9171         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9172       } else {
9173         if (IS_GENPTR(restype))
9174         {
9175           if (IS_CODEPTR(rtype)) {
9176             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9177             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9178           } else if (PIC_IS_DATA_PTR(rtype)) {
9179             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9180             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9181           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9182             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9183           } else if (IS_PTR(rtype)) {
9184             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9185             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9186           }
9187         }
9188       }
9189     } else {
9190       union {
9191         unsigned long lit_int;
9192         float lit_float;
9193       } info;
9194
9195
9196       if(IS_FIXED16X16(operandType(right))) {
9197         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9198       } else {
9199         /* take care if literal is a float */
9200         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9201         lit = info.lit_int;
9202       }
9203     }
9204   }
9205
9206 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9207 //                      sizeof(unsigned long int), sizeof(float));
9208
9209
9210     if (AOP_TYPE(right) == AOP_REG) {
9211       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9212       while (size--) {
9213         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9214       } // while
9215       goto release;
9216     }
9217
9218     /* when do we have to read the program memory?
9219      * - if right itself is a symbol in code space
9220      *   (we don't care what it points to if it's a pointer)
9221      * - AND right is not a function (we would want its address)
9222      */
9223     if(AOP_TYPE(right) != AOP_LIT
9224       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9225       && !IS_FUNC(OP_SYM_TYPE(right))
9226       && !IS_ITEMP(right)) {
9227
9228       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9229       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9230
9231       // set up table pointer
9232       if(pic16_isLitOp(right)) {
9233 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9234         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9235         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9236         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9237         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9238         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9239         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9240       } else {
9241 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9242         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9243             pic16_popCopyReg(&pic16_pc_tblptrl)));
9244         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9245             pic16_popCopyReg(&pic16_pc_tblptrh)));
9246         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9247             pic16_popCopyReg(&pic16_pc_tblptru)));
9248       }
9249
9250       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9251       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9252       while(size--) {
9253         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9254         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9255             pic16_popGet(AOP(result),offset)));
9256         offset++;
9257       }
9258
9259       /* FIXME: for pointers we need to extend differently (according
9260        * to pointer type DATA/CODE/EEPROM/... :*/
9261       size = getSize(OP_SYM_TYPE(right));
9262       if(AOP_SIZE(result) > size) {
9263         size = AOP_SIZE(result) - size;
9264         while(size--) {
9265           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9266           offset++;
9267         }
9268       }
9269       goto release;
9270     }
9271
9272 #if 0
9273     /* VR - What is this?! */
9274     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9275       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9276
9277       if(aopIdx(AOP(result),0) == 4) {
9278         /* this is a workaround to save value of right into wreg too,
9279          * value of wreg is going to be used later */
9280         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9281         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9282         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9283         goto release;
9284       } else
9285 //      assert(0);
9286       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9287     }
9288 #endif
9289
9290     size = AOP_SIZE(right);
9291     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9292     know_W=-1;
9293     while (size--) {
9294       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
9295       if(AOP_TYPE(right) == AOP_LIT) {
9296         if(lit&0xff) {
9297           if(know_W != (lit&0xff))
9298             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9299           know_W = lit&0xff;
9300           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9301         } else
9302           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9303
9304         lit >>= 8;
9305
9306       } else if (AOP_TYPE(right) == AOP_CRY) {
9307         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9308         if(offset == 0) {
9309           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9310           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9311           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9312         }
9313       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9314         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9315         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9316       } else {
9317         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9318
9319         if(!_G.resDirect) {                                             /* use this aopForSym feature */
9320           if(AOP_TYPE(result) == AOP_ACC) {
9321             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9322           } else
9323             if(AOP_TYPE(right) == AOP_ACC) {
9324               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9325             } else {
9326               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9327             }
9328         }
9329       }
9330
9331       offset++;
9332     }
9333     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9334
9335 release:
9336   pic16_freeAsmop (right,NULL,ic,FALSE);
9337   pic16_freeAsmop (result,NULL,ic,TRUE);
9338 }
9339
9340 /*-----------------------------------------------------------------*/
9341 /* genJumpTab - generates code for jump table                       */
9342 /*-----------------------------------------------------------------*/
9343 static void genJumpTab (iCode *ic)
9344 {
9345   symbol *jtab;
9346   char *l;
9347   pCodeOp *jt_offs;
9348   pCodeOp *jt_offs_hi;
9349   pCodeOp *jt_label;
9350
9351     FENTRY;
9352
9353     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9354     /* get the condition into accumulator */
9355     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9356     MOVA(l);
9357     /* multiply by three */
9358     pic16_emitcode("add","a,acc");
9359     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9360
9361     jtab = newiTempLabel(NULL);
9362     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9363     pic16_emitcode("jmp","@a+dptr");
9364     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9365
9366 #if 0
9367     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9368     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9369     emitSKPNC;
9370     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9371     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9372     pic16_emitpLabel(jtab->key);
9373
9374 #else
9375
9376     jt_offs = pic16_popGetTempReg(0);
9377     jt_offs_hi = pic16_popGetTempReg(1);
9378     jt_label = pic16_popGetLabel (jtab->key);
9379     //fprintf (stderr, "Creating jump table...\n");
9380
9381     // calculate offset into jump table (idx * sizeof (GOTO))
9382     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
9383     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9384     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9385     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9386     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9387     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9388     pic16_emitpcode(POC_MOVWF , jt_offs);
9389
9390     // prepare PCLATx (set to first entry in jump table)
9391     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9392     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9393     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9394     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9395     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9396
9397     // set PCLATx to selected entry (new PCL is stored in jt_offs)
9398     pic16_emitpcode(POC_ADDWF , jt_offs);
9399     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9400     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9401     emitSKPNC;
9402     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
9403
9404     // release temporaries and prepare jump into table (new PCL --> WREG)
9405     pic16_emitpcode(POC_MOVFW , jt_offs);
9406     pic16_popReleaseTempReg (jt_offs_hi, 1);
9407     pic16_popReleaseTempReg (jt_offs, 0);
9408
9409     // jump into the table
9410     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9411
9412     pic16_emitpLabelFORCE(jtab->key);
9413 #endif
9414
9415     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9416 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9417
9418     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9419     /* now generate the jump labels */
9420     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9421          jtab = setNextItem(IC_JTLABELS(ic))) {
9422 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9423         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9424
9425     }
9426     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9427
9428 }
9429
9430 /*-----------------------------------------------------------------*/
9431 /* genMixedOperation - gen code for operators between mixed types  */
9432 /*-----------------------------------------------------------------*/
9433 /*
9434   TSD - Written for the PIC port - but this unfortunately is buggy.
9435   This routine is good in that it is able to efficiently promote
9436   types to different (larger) sizes. Unfortunately, the temporary
9437   variables that are optimized out by this routine are sometimes
9438   used in other places. So until I know how to really parse the
9439   iCode tree, I'm going to not be using this routine :(.
9440 */
9441 static int genMixedOperation (iCode *ic)
9442 {
9443 #if 0
9444   operand *result = IC_RESULT(ic);
9445   sym_link *ctype = operandType(IC_LEFT(ic));
9446   operand *right = IC_RIGHT(ic);
9447   int ret = 0;
9448   int big,small;
9449   int offset;
9450
9451   iCode *nextic;
9452   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9453
9454   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9455
9456   nextic = ic->next;
9457   if(!nextic)
9458     return 0;
9459
9460   nextright = IC_RIGHT(nextic);
9461   nextleft  = IC_LEFT(nextic);
9462   nextresult = IC_RESULT(nextic);
9463
9464   pic16_aopOp(right,ic,FALSE);
9465   pic16_aopOp(result,ic,FALSE);
9466   pic16_aopOp(nextright,  nextic, FALSE);
9467   pic16_aopOp(nextleft,   nextic, FALSE);
9468   pic16_aopOp(nextresult, nextic, FALSE);
9469
9470   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9471
9472     operand *t = right;
9473     right = nextright;
9474     nextright = t;
9475
9476     pic16_emitcode(";remove right +","");
9477
9478   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9479 /*
9480     operand *t = right;
9481     right = nextleft;
9482     nextleft = t;
9483 */
9484     pic16_emitcode(";remove left +","");
9485   } else
9486     return 0;
9487
9488   big = AOP_SIZE(nextleft);
9489   small = AOP_SIZE(nextright);
9490
9491   switch(nextic->op) {
9492
9493   case '+':
9494     pic16_emitcode(";optimize a +","");
9495     /* if unsigned or not an integral type */
9496     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9497       pic16_emitcode(";add a bit to something","");
9498     } else {
9499
9500       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9501
9502       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9503         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9504         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9505       } else
9506         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9507
9508       offset = 0;
9509       while(--big) {
9510
9511         offset++;
9512
9513         if(--small) {
9514           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9515             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9516             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9517           }
9518
9519           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9520           emitSKPNC;
9521           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9522                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9523                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9524           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9525           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9526
9527         } else {
9528           pic16_emitcode("rlf","known_zero,w");
9529
9530           /*
9531             if right is signed
9532               btfsc  right,7
9533                addlw ff
9534           */
9535           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9536             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9537             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9538           } else {
9539             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9540           }
9541         }
9542       }
9543       ret = 1;
9544     }
9545   }
9546   ret = 1;
9547
9548 release:
9549   pic16_freeAsmop(right,NULL,ic,TRUE);
9550   pic16_freeAsmop(result,NULL,ic,TRUE);
9551   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9552   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9553   if(ret)
9554     nextic->generated = 1;
9555
9556   return ret;
9557 #else
9558   return 0;
9559 #endif
9560 }
9561 /*-----------------------------------------------------------------*/
9562 /* genCast - gen code for casting                                  */
9563 /*-----------------------------------------------------------------*/
9564 static void genCast (iCode *ic)
9565 {
9566   operand *result = IC_RESULT(ic);
9567   sym_link *ctype = operandType(IC_LEFT(ic));
9568   sym_link *rtype = operandType(IC_RIGHT(ic));
9569   sym_link *restype = operandType(IC_RESULT(ic));
9570   operand *right = IC_RIGHT(ic);
9571   int size, offset ;
9572
9573
9574     FENTRY;
9575
9576         /* if they are equivalent then do nothing */
9577 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9578 //              return ;
9579
9580         pic16_aopOp(result,ic,FALSE);
9581         pic16_aopOp(right,ic,FALSE) ;
9582
9583         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9584
9585
9586         /* if the result is a bit */
9587         if (AOP_TYPE(result) == AOP_CRY) {
9588
9589                 /* if the right size is a literal then
9590                  * we know what the value is */
9591                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9592
9593                 if (AOP_TYPE(right) == AOP_LIT) {
9594                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9595                                 pic16_popGet(AOP(result),0));
9596
9597                         if (((int) operandLitValue(right)))
9598                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9599                                         AOP(result)->aopu.aop_dir,
9600                                         AOP(result)->aopu.aop_dir);
9601                         else
9602                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9603                                         AOP(result)->aopu.aop_dir,
9604                                         AOP(result)->aopu.aop_dir);
9605                         goto release;
9606                 }
9607
9608                 /* the right is also a bit variable */
9609                 if (AOP_TYPE(right) == AOP_CRY) {
9610                         emitCLRC;
9611                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9612
9613                         pic16_emitcode("clrc","");
9614                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9615                                 AOP(right)->aopu.aop_dir,
9616                                 AOP(right)->aopu.aop_dir);
9617                         pic16_aopPut(AOP(result),"c",0);
9618                         goto release ;
9619                 }
9620
9621                 /* we need to or */
9622                 if (AOP_TYPE(right) == AOP_REG) {
9623                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9624                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9625                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9626                 }
9627                 pic16_toBoolean(right);
9628                 pic16_aopPut(AOP(result),"a",0);
9629                 goto release ;
9630         }
9631
9632         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9633           int offset = 1;
9634
9635                 size = AOP_SIZE(result);
9636
9637                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9638
9639                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9640                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9641                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9642
9643                 while (size--)
9644                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9645
9646                 goto release;
9647         }
9648
9649         if(IS_BITFIELD(getSpec(restype))
9650           && IS_BITFIELD(getSpec(rtype))) {
9651           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9652         }
9653
9654         /* port from pic14 to cope with generic pointers */
9655         if (PIC_IS_TAGGED(restype))
9656         {
9657           operand *result = IC_RESULT(ic);
9658           //operand *left = IC_LEFT(ic);
9659           operand *right = IC_RIGHT(ic);
9660           int tag = 0xff;
9661
9662           /* copy common part */
9663           int max, size = AOP_SIZE(result);
9664           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9665           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9666
9667           max = size;
9668           while (size--)
9669           {
9670             pic16_mov2w (AOP(right), size);
9671             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9672           } // while
9673
9674           /* upcast into generic pointer type? */
9675           if (IS_GENPTR(restype)
9676               && !PIC_IS_TAGGED(rtype)
9677               && (AOP_SIZE(result) > max))
9678           {
9679             /* determine appropriate tag for right */
9680             if (PIC_IS_DATA_PTR(rtype))
9681               tag = GPTR_TAG_DATA;
9682             else if (IS_CODEPTR(rtype))
9683               tag = GPTR_TAG_CODE;
9684             else if (PIC_IS_DATA_PTR(ctype)) {
9685               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9686               tag = GPTR_TAG_DATA;
9687             } else if (IS_CODEPTR(ctype)) {
9688               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9689               tag = GPTR_TAG_CODE;
9690             } else if (IS_PTR(rtype)) {
9691               PERFORM_ONCE(weirdcast,
9692               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9693               );
9694               tag = GPTR_TAG_DATA;
9695             } else {
9696               PERFORM_ONCE(weirdcast,
9697               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9698               );
9699               tag = GPTR_TAG_DATA;
9700             }
9701
9702             assert (AOP_SIZE(result) == 3);
9703             /* zero-extend address... */
9704             for (size = max; size < AOP_SIZE(result)-1; size++)
9705               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9706             /* ...and add tag */
9707             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9708           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9709             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9710             for (size = max; size < AOP_SIZE(result)-1; size++)
9711               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9712             /* add __code tag */
9713             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9714           } else if (AOP_SIZE(result) > max) {
9715             /* extend non-pointers */
9716             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9717             pic16_addSign(result, max, 0);
9718           } // if
9719           goto release;
9720         }
9721
9722         /* if they are the same size : or less */
9723         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9724
9725                 /* if they are in the same place */
9726                 if (pic16_sameRegs(AOP(right),AOP(result)))
9727                         goto release;
9728
9729                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9730 #if 0
9731                 if (IS_PTR_CONST(rtype))
9732 #else
9733                 if (IS_CODEPTR(rtype))
9734 #endif
9735                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9736
9737 #if 0
9738                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9739 #else
9740                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9741 #endif
9742                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9743
9744                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9745                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9746                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9747
9748                         if(AOP_SIZE(result) < 2) {
9749                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9750                         } else {
9751                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9752                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9753                         }
9754                 } else {
9755                         /* if they in different places then copy */
9756                         size = AOP_SIZE(result);
9757                         offset = 0 ;
9758                         while (size--) {
9759                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9760                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9761                                 offset++;
9762                         }
9763                 }
9764                 goto release;
9765         }
9766
9767         /* if the result is of type pointer */
9768         if (IS_PTR(ctype)) {
9769           int p_type;
9770           sym_link *type = operandType(right);
9771           sym_link *etype = getSpec(type);
9772
9773                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9774
9775                 /* pointer to generic pointer */
9776                 if (IS_GENPTR(ctype)) {
9777                   char *l = zero;
9778
9779                         if (IS_PTR(type))
9780                                 p_type = DCL_TYPE(type);
9781                         else {
9782                 /* we have to go by the storage class */
9783                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9784
9785 /*              if (SPEC_OCLS(etype)->codesp )  */
9786 /*                  p_type = CPOINTER ;  */
9787 /*              else */
9788 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9789 /*                      p_type = FPOINTER ; */
9790 /*                  else */
9791 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9792 /*                          p_type = PPOINTER; */
9793 /*                      else */
9794 /*                          if (SPEC_OCLS(etype) == idata ) */
9795 /*                              p_type = IPOINTER ; */
9796 /*                          else */
9797 /*                              p_type = POINTER ; */
9798             }
9799
9800             /* the first two bytes are known */
9801       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9802             size = GPTRSIZE - 1;
9803             offset = 0 ;
9804             while (size--) {
9805               if(offset < AOP_SIZE(right)) {
9806                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9807                 pic16_mov2f(AOP(result), AOP(right), offset);
9808 /*
9809                 if ((AOP_TYPE(right) == AOP_PCODE) &&
9810                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9811                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9812                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9813                 } else {
9814
9815                   pic16_aopPut(AOP(result),
9816                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9817                          offset);
9818                 }
9819 */
9820               } else
9821                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9822               offset++;
9823             }
9824             /* the last byte depending on type */
9825             switch (p_type) {
9826             case IPOINTER:
9827             case POINTER:
9828             case FPOINTER:
9829                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9830                 break;
9831
9832             case CPOINTER:
9833                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9834                 break;
9835
9836             case PPOINTER:
9837               pic16_emitcode(";BUG!? ","%d",__LINE__);
9838                 l = "#0x03";
9839                 break;
9840
9841             case GPOINTER:
9842                 if (GPTRSIZE > AOP_SIZE(right)) {
9843                   // assume __data pointer... THIS MIGHT BE WRONG!
9844                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9845                 } else {
9846                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9847                 }
9848               break;
9849
9850             default:
9851                 /* this should never happen */
9852                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9853                        "got unknown pointer type");
9854                 exit(1);
9855             }
9856             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9857             goto release ;
9858         }
9859
9860
9861         assert( 0 );
9862         /* just copy the pointers */
9863         size = AOP_SIZE(result);
9864         offset = 0 ;
9865         while (size--) {
9866             pic16_aopPut(AOP(result),
9867                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9868                    offset);
9869             offset++;
9870         }
9871         goto release ;
9872     }
9873
9874
9875
9876     /* so we now know that the size of destination is greater
9877     than the size of the source.
9878     Now, if the next iCode is an operator then we might be
9879     able to optimize the operation without performing a cast.
9880     */
9881     if(genMixedOperation(ic))
9882       goto release;
9883
9884     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9885
9886     /* we move to result for the size of source */
9887     size = AOP_SIZE(right);
9888     offset = 0 ;
9889
9890     while (size--) {
9891       if(!_G.resDirect)
9892         pic16_mov2f(AOP(result), AOP(right), offset);
9893       offset++;
9894     }
9895
9896     /* now depending on the sign of the destination */
9897     size = AOP_SIZE(result) - AOP_SIZE(right);
9898     /* if unsigned or not an integral type */
9899     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9900       while (size--)
9901         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9902     } else {
9903       /* we need to extend the sign :( */
9904
9905       if(size == 1) {
9906         /* Save one instruction of casting char to int */
9907         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9908         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9909         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
9910       } else {
9911         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9912
9913         if(offset)
9914           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9915         else
9916           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9917
9918         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9919
9920         while (size--)
9921           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9922       }
9923     }
9924
9925 release:
9926     pic16_freeAsmop(right,NULL,ic,TRUE);
9927     pic16_freeAsmop(result,NULL,ic,TRUE);
9928
9929 }
9930
9931 /*-----------------------------------------------------------------*/
9932 /* genDjnz - generate decrement & jump if not zero instrucion      */
9933 /*-----------------------------------------------------------------*/
9934 static int genDjnz (iCode *ic, iCode *ifx)
9935 {
9936     symbol *lbl, *lbl1;
9937     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9938
9939     if (!ifx)
9940         return 0;
9941
9942     /* if the if condition has a false label
9943        then we cannot save */
9944     if (IC_FALSE(ifx))
9945         return 0;
9946
9947     /* if the minus is not of the form
9948        a = a - 1 */
9949     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9950         !IS_OP_LITERAL(IC_RIGHT(ic)))
9951         return 0;
9952
9953     if (operandLitValue(IC_RIGHT(ic)) != 1)
9954         return 0;
9955
9956     /* if the size of this greater than one then no
9957        saving */
9958     if (getSize(operandType(IC_RESULT(ic))) > 1)
9959         return 0;
9960
9961     /* otherwise we can save BIG */
9962     lbl = newiTempLabel(NULL);
9963     lbl1= newiTempLabel(NULL);
9964
9965     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9966
9967     pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9968     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9969
9970     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9971     ifx->generated = 1;
9972     return 1;
9973 }
9974
9975 /*-----------------------------------------------------------------*/
9976 /* genReceive - generate code for a receive iCode                  */
9977 /*-----------------------------------------------------------------*/
9978 static void genReceive (iCode *ic)
9979 {
9980
9981   FENTRY;
9982
9983 #if 0
9984   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
9985         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
9986 #endif
9987 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
9988
9989   if (isOperandInFarSpace(IC_RESULT(ic))
9990       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
9991           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9992
9993     int size = getSize(operandType(IC_RESULT(ic)));
9994     int offset =  pic16_fReturnSizePic - size;
9995
9996       assert( 0 );
9997       while (size--) {
9998         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9999                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10000                       offset++;
10001         }
10002
10003       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10004
10005       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10006       size = AOP_SIZE(IC_RESULT(ic));
10007       offset = 0;
10008       while (size--) {
10009         pic16_emitcode ("pop","acc");
10010         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10011       }
10012   } else {
10013     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10014     _G.accInUse++;
10015     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10016     _G.accInUse--;
10017
10018     /* set pseudo stack pointer to where it should be - dw*/
10019     GpsuedoStkPtr = ic->parmBytes;
10020
10021     /* setting GpsuedoStkPtr has side effects here: */
10022     /* FIXME: What's the correct size of the return(ed) value?
10023      *        For now, assuming '4' as before... */
10024     assignResultValue(IC_RESULT(ic), 4, 0);
10025   }
10026
10027   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10028 }
10029
10030 /*-----------------------------------------------------------------*/
10031 /* genDummyRead - generate code for dummy read of volatiles        */
10032 /*-----------------------------------------------------------------*/
10033 static void
10034 genDummyRead (iCode * ic)
10035 {
10036   operand *op;
10037
10038   op = IC_RIGHT(ic);
10039   if (op && IS_SYMOP(op)) {
10040     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10041       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10042       return;
10043     }
10044     pic16_aopOp (op, ic, FALSE);
10045     pic16_mov2w_volatile(AOP(op));
10046     pic16_freeAsmop (op, NULL, ic, TRUE);
10047   } else if (op) {
10048     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10049   } // if
10050 }
10051
10052 /*-----------------------------------------------------------------*/
10053 /* genpic16Code - generate code for pic16 based controllers        */
10054 /*-----------------------------------------------------------------*/
10055 /*
10056  * At this point, ralloc.c has gone through the iCode and attempted
10057  * to optimize in a way suitable for a PIC. Now we've got to generate
10058  * PIC instructions that correspond to the iCode.
10059  *
10060  * Once the instructions are generated, we'll pass through both the
10061  * peep hole optimizer and the pCode optimizer.
10062  *-----------------------------------------------------------------*/
10063
10064 void genpic16Code (iCode *lic)
10065 {
10066   iCode *ic;
10067   int cln = 0;
10068
10069     lineHead = lineCurr = NULL;
10070
10071     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10072     pic16_addpBlock(pb);
10073
10074 #if 0
10075     /* if debug information required */
10076     if (options.debug && currFunc) {
10077       if (currFunc) {
10078         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10079       }
10080     }
10081 #endif
10082
10083     for (ic = lic ; ic ; ic = ic->next ) {
10084
10085       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10086       if ( cln != ic->lineno ) {
10087         if ( options.debug ) {
10088           debugFile->writeCLine (ic);
10089         }
10090
10091         if(!options.noCcodeInAsm) {
10092           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10093               printCLine(ic->filename, ic->lineno)));
10094         }
10095
10096         cln = ic->lineno ;
10097       }
10098
10099       if(options.iCodeInAsm) {
10100         const char *iLine;
10101
10102         /* insert here code to print iCode as comment */
10103         iLine = printILine(ic);
10104         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10105         dbuf_free(iLine);
10106       }
10107
10108       /* if the result is marked as
10109        * spilt and rematerializable or code for
10110        * this has already been generated then
10111        * do nothing */
10112       if (resultRemat(ic) || ic->generated )
10113         continue ;
10114
10115       /* depending on the operation */
10116       switch (ic->op) {
10117         case '!' :
10118           pic16_genNot(ic);
10119           break;
10120
10121         case '~' :
10122           pic16_genCpl(ic);
10123           break;
10124
10125         case UNARYMINUS:
10126           genUminus (ic);
10127           break;
10128
10129         case IPUSH:
10130           genIpush (ic);
10131           break;
10132
10133         case IPOP:
10134           /* IPOP happens only when trying to restore a
10135            * spilt live range, if there is an ifx statement
10136            * following this pop then the if statement might
10137            * be using some of the registers being popped which
10138            * would destroy the contents of the register so
10139            * we need to check for this condition and handle it */
10140            if (ic->next
10141              && ic->next->op == IFX
10142              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10143                genIfx (ic->next,ic);
10144           else
10145             genIpop (ic);
10146           break;
10147
10148         case CALL:
10149           genCall (ic);
10150           break;
10151
10152         case PCALL:
10153           genPcall (ic);
10154           break;
10155
10156         case FUNCTION:
10157           genFunction (ic);
10158           break;
10159
10160         case ENDFUNCTION:
10161           genEndFunction (ic);
10162           break;
10163
10164         case RETURN:
10165           genRet (ic);
10166           break;
10167
10168         case LABEL:
10169           genLabel (ic);
10170           break;
10171
10172         case GOTO:
10173           genGoto (ic);
10174           break;
10175
10176         case '+' :
10177           pic16_genPlus (ic) ;
10178           break;
10179
10180         case '-' :
10181           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10182             pic16_genMinus (ic);
10183           break;
10184
10185         case '*' :
10186           genMult (ic);
10187           break;
10188
10189         case '/' :
10190           genDiv (ic) ;
10191           break;
10192
10193         case '%' :
10194           genMod (ic);
10195           break;
10196
10197         case '>' :
10198           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10199           break;
10200
10201         case '<' :
10202           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10203           break;
10204
10205         case LE_OP:
10206         case GE_OP:
10207         case NE_OP:
10208           /* note these two are xlated by algebraic equivalence
10209            * during parsing SDCC.y */
10210           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10211             "got '>=' or '<=' shouldn't have come here");
10212           break;
10213
10214         case EQ_OP:
10215           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10216           break;
10217
10218         case AND_OP:
10219           genAndOp (ic);
10220           break;
10221
10222         case OR_OP:
10223           genOrOp (ic);
10224           break;
10225
10226         case '^' :
10227           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10228           break;
10229
10230         case '|' :
10231           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10232           break;
10233
10234         case BITWISEAND:
10235           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10236           break;
10237
10238         case INLINEASM:
10239           genInline (ic);
10240           break;
10241
10242         case RRC:
10243           genRRC (ic);
10244           break;
10245
10246         case RLC:
10247           genRLC (ic);
10248           break;
10249
10250         case GETHBIT:
10251           genGetHbit (ic);
10252           break;
10253
10254         case LEFT_OP:
10255           genLeftShift (ic);
10256           break;
10257
10258         case RIGHT_OP:
10259           genRightShift (ic);
10260           break;
10261
10262         case GET_VALUE_AT_ADDRESS:
10263           genPointerGet(ic);
10264           break;
10265
10266         case '=' :
10267           if (POINTER_SET(ic))
10268             genPointerSet(ic);
10269           else
10270             genAssign(ic);
10271           break;
10272
10273         case IFX:
10274           genIfx (ic,NULL);
10275           break;
10276
10277         case ADDRESS_OF:
10278           genAddrOf (ic);
10279           break;
10280
10281         case JUMPTABLE:
10282           genJumpTab (ic);
10283           break;
10284
10285         case CAST:
10286           genCast (ic);
10287           break;
10288
10289         case RECEIVE:
10290           genReceive(ic);
10291           break;
10292
10293         case SEND:
10294           addSet(&_G.sendSet,ic);
10295           break;
10296
10297         case DUMMY_READ_VOLATILE:
10298           genDummyRead (ic);
10299           break;
10300
10301         default :
10302           ic = ic;
10303       }
10304     }
10305
10306
10307     /* now we are ready to call the
10308        peep hole optimizer */
10309     if (!options.nopeep)
10310       peepHole (&lineHead);
10311
10312     /* now do the actual printing */
10313     printLine (lineHead, codeOutBuf);
10314
10315 #ifdef PCODE_DEBUG
10316     DFPRINTF((stderr,"printing pBlock\n\n"));
10317     pic16_printpBlock(stdout,pb);
10318 #endif
10319
10320     return;
10321 }