* src/pic16/genarith.c,
[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_mov2f(asmop *dst, asmop *src, int offset)
2000 {
2001   if(pic16_isLitAop(src)) {
2002     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2003     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2004   } else {
2005     if(pic16_sameRegsOfs(src, dst, offset))return;
2006     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2007                       pic16_popGet(dst, offset)));
2008   }
2009 }
2010
2011 static void pic16_movLit2f(pCodeOp *pc, int lit)
2012 {
2013   if (0 == (lit & 0x00ff))
2014   {
2015     pic16_emitpcode (POC_CLRF, pc);
2016   } else if (0xff == (lit & 0x00ff))
2017   {
2018     pic16_emitpcode (POC_SETF, pc);
2019   } else {
2020     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2021     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2022   }
2023 }
2024
2025 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2026 {
2027   if(pic16_isLitAop(src)) {
2028     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2029     pic16_emitpcode(POC_MOVWF, dst);
2030   } else {
2031     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2032   }
2033 }
2034
2035 void pic16_testStackOverflow(void)
2036 {
2037 #define GSTACK_TEST_NAME        "_gstack_test"
2038
2039   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2040
2041   {
2042     symbol *sym;
2043
2044       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2045       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2046 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2047       checkAddSym(&externs, sym);
2048   }
2049
2050 }
2051
2052 /* push pcop into stack */
2053 void pic16_pushpCodeOp(pCodeOp *pcop)
2054 {
2055 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2056   if (pcop->type == PO_LITERAL) {
2057     pic16_emitpcode(POC_MOVLW, pcop);
2058     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2059   } else {
2060     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2061   }
2062   if(pic16_options.gstack)
2063     pic16_testStackOverflow();
2064
2065 }
2066
2067 /* pop pcop from stack */
2068 void pic16_poppCodeOp(pCodeOp *pcop)
2069 {
2070   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2071   if(pic16_options.gstack)
2072     pic16_testStackOverflow();
2073 }
2074
2075
2076 /*-----------------------------------------------------------------*/
2077 /* pushw - pushes wreg to stack                                    */
2078 /*-----------------------------------------------------------------*/
2079 void pushw(void)
2080 {
2081   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2082   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2083   if(pic16_options.gstack)
2084     pic16_testStackOverflow();
2085 }
2086
2087
2088 /*-----------------------------------------------------------------*/
2089 /* pushaop - pushes aop to stack                                   */
2090 /*-----------------------------------------------------------------*/
2091 void pushaop(asmop *aop, int offset)
2092 {
2093   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2094
2095   if(_G.resDirect)return;
2096
2097   if(pic16_isLitAop(aop)) {
2098     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2099     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2100   } else {
2101     pic16_emitpcode(POC_MOVFF,
2102       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2103   }
2104
2105   if(pic16_options.gstack)
2106     pic16_testStackOverflow();
2107 }
2108
2109 /*-----------------------------------------------------------------*/
2110 /* popaop - pops aop from stack                                    */
2111 /*-----------------------------------------------------------------*/
2112 void popaop(asmop *aop, int offset)
2113 {
2114   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2115   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2116   if(pic16_options.gstack)
2117     pic16_testStackOverflow();
2118 }
2119
2120 void popaopidx(asmop *aop, int offset, int index)
2121 {
2122   int ofs=1;
2123
2124     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2125
2126     if(STACK_MODEL_LARGE)ofs++;
2127
2128     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2129     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2130     if(pic16_options.gstack)
2131       pic16_testStackOverflow();
2132 }
2133
2134 /*-----------------------------------------------------------------*/
2135 /* pic16_getDataSize - get the operand data size                         */
2136 /*-----------------------------------------------------------------*/
2137 int pic16_getDataSize(operand *op)
2138 {
2139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2140
2141
2142     return AOP_SIZE(op);
2143
2144     // tsd- in the pic port, the genptr size is 1, so this code here
2145     // fails. ( in the 8051 port, the size was 4).
2146 #if 0
2147     int size;
2148     size = AOP_SIZE(op);
2149     if (size == GPTRSIZE)
2150     {
2151         sym_link *type = operandType(op);
2152         if (IS_GENPTR(type))
2153         {
2154             /* generic pointer; arithmetic operations
2155              * should ignore the high byte (pointer type).
2156              */
2157             size--;
2158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2159         }
2160     }
2161     return size;
2162 #endif
2163 }
2164
2165 /*-----------------------------------------------------------------*/
2166 /* pic16_outAcc - output Acc                                             */
2167 /*-----------------------------------------------------------------*/
2168 void pic16_outAcc(operand *result)
2169 {
2170   int size,offset;
2171   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2172   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2173
2174
2175   size = pic16_getDataSize(result);
2176   if(size){
2177     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2178     size--;
2179     offset = 1;
2180     /* unsigned or positive */
2181     while(size--)
2182       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2183   }
2184
2185 }
2186
2187 /*-----------------------------------------------------------------*/
2188 /* pic16_outBitC - output a bit C                                  */
2189 /*                 Move to result the value of Carry flag -- VR    */
2190 /*-----------------------------------------------------------------*/
2191 void pic16_outBitC(operand *result)
2192 {
2193   int i;
2194
2195     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2196
2197     /* if the result is bit */
2198     if (AOP_TYPE(result) == AOP_CRY) {
2199         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2200         pic16_aopPut(AOP(result),"c",0);
2201     } else {
2202
2203         i = AOP_SIZE(result);
2204         while(i--) {
2205                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2206         }
2207         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2208     }
2209 }
2210
2211 /*-----------------------------------------------------------------*/
2212 /* pic16_outBitOp - output a bit from Op                           */
2213 /*                 Move to result the value of set/clr op -- VR    */
2214 /*-----------------------------------------------------------------*/
2215 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2216 {
2217   int i;
2218
2219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2220
2221     /* if the result is bit */
2222     if (AOP_TYPE(result) == AOP_CRY) {
2223         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2224         pic16_aopPut(AOP(result),"c",0);
2225     } else {
2226
2227         i = AOP_SIZE(result);
2228         while(i--) {
2229                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2230         }
2231         pic16_emitpcode(POC_RRCF, pcop);
2232         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2233     }
2234 }
2235
2236 /*-----------------------------------------------------------------*/
2237 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2238 /*-----------------------------------------------------------------*/
2239 void pic16_toBoolean(operand *oper)
2240 {
2241     int size = AOP_SIZE(oper) - 1;
2242     int offset = 1;
2243
2244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2245
2246     if ( AOP_TYPE(oper) != AOP_ACC) {
2247       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2248     }
2249     while (size--) {
2250       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2251     }
2252 }
2253
2254 /*-----------------------------------------------------------------*/
2255 /* genUminusFloat - unary minus for floating points                */
2256 /*-----------------------------------------------------------------*/
2257 static void genUminusFloat(operand *op,operand *result)
2258 {
2259   int size ,offset =0 ;
2260
2261     FENTRY;
2262     /* for this we just need to flip the
2263     first it then copy the rest in place */
2264     size = AOP_SIZE(op);
2265     assert( size == AOP_SIZE(result) );
2266
2267     while(size--) {
2268       pic16_mov2f(AOP(result), AOP(op), offset);
2269       offset++;
2270     }
2271
2272     /* toggle the MSB's highest bit */
2273     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2274 }
2275
2276 /*-----------------------------------------------------------------*/
2277 /* genUminus - unary minus code generation                         */
2278 /*-----------------------------------------------------------------*/
2279 static void genUminus (iCode *ic)
2280 {
2281   int size, i;
2282   sym_link *optype, *rtype;
2283   symbol *label;
2284   int needLabel=0;
2285
2286     FENTRY;
2287
2288     /* assign asmops */
2289     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2290     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2291
2292     /* if both in bit space then special case */
2293     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2294       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2295
2296         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2297         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2298         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2299         goto release;
2300     }
2301
2302     optype = operandType(IC_LEFT(ic));
2303     rtype = operandType(IC_RESULT(ic));
2304
2305
2306     /* if float then do float stuff */
2307     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2308       if(IS_FIXED(optype))
2309         debugf("implement fixed16x16 type\n", 0);
2310
2311         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2312         goto release;
2313     }
2314
2315     /* otherwise subtract from zero by taking the 2's complement */
2316     size = AOP_SIZE(IC_LEFT(ic));
2317     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2318     label = newiTempLabel ( NULL );
2319
2320     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2321       for (i=size-1; i > 0; i--) {
2322         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2323       } // for
2324       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2325       for (i=1; i < size; i++) {
2326         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2327         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2328       } // for
2329     } else {
2330       for (i=size-1; i >= 0; i--) {
2331         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2332         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2333       } // for
2334       if (size > 1) {
2335         for (i=0; i < size-2; i++) {
2336           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2337           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2338         } // for
2339         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2340       } // if
2341       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2342     }
2343     if (needLabel)
2344       pic16_emitpLabel (label->key);
2345
2346 release:
2347     /* release the aops */
2348     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2349     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2350 }
2351
2352 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2353 {
2354   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2355     pic16_emitpcode(POC_MOVFW, src);
2356     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2357   } else {
2358     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2359         src, pic16_popGet(AOP(op), offset)));
2360   }
2361 }
2362
2363
2364 /*-----------------------------------------------------------------*/
2365 /* assignResultValue - assign results to oper, rescall==1 is       */
2366 /*                     called from genCall() or genPcall()         */
2367 /*-----------------------------------------------------------------*/
2368 static void assignResultValue(operand * oper, int res_size, int rescall)
2369 {
2370   int size = AOP_SIZE(oper);
2371   int offset=0;
2372
2373     FENTRY2;
2374 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2375     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2376
2377     if(rescall) {
2378       /* assign result from a call/pcall function() */
2379
2380       /* function results are stored in a special order,
2381        * see top of file with Function return policy, or manual */
2382
2383       if(size <= 4) {
2384         /* 8-bits, result in WREG */
2385         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2386
2387         if(size > 1 && res_size > 1) {
2388           /* 16-bits, result in PRODL:WREG */
2389           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2390         }
2391
2392         if(size > 2 && res_size > 2) {
2393           /* 24-bits, result in PRODH:PRODL:WREG */
2394           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2395         }
2396
2397         if(size > 3 && res_size > 3) {
2398           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2399           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2400         }
2401
2402         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2403
2404       } else {
2405         /* >32-bits, result on stack, and FSR0 points to beginning.
2406          * Fix stack when done */
2407         /* FIXME FIXME */
2408 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2409         while (size--) {
2410 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2411 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2412
2413           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2414           GpsuedoStkPtr++;
2415         }
2416
2417         /* fix stack */
2418         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2419         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2420         if(STACK_MODEL_LARGE) {
2421           emitSKPNC;
2422           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2423         }
2424       }
2425     } else {
2426       int areg = 0;             /* matching argument register */
2427
2428 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2429       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2430
2431
2432       /* its called from genReceive (probably) -- VR */
2433       /* I hope this code will not be called from somewhere else in the future!
2434        * We manually set the pseudo stack pointer in genReceive. - dw
2435        */
2436       if(!GpsuedoStkPtr && _G.useWreg) {
2437 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2438
2439         /* The last byte in the assignment is in W */
2440         if(areg <= GpsuedoStkPtr) {
2441           size--;
2442           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2443           offset++;
2444 //          debugf("receive from WREG\n", 0);
2445         }
2446         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2447       }
2448 //      GpsuedoStkPtr++;
2449       _G.stack_lat = AOP_SIZE(oper)-1;
2450
2451       while (size) {
2452         size--;
2453         GpsuedoStkPtr++;
2454         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2455 //        debugf("receive from STACK\n", 0);
2456         offset++;
2457       }
2458     }
2459 }
2460
2461
2462 /*-----------------------------------------------------------------*/
2463 /* genIpush - generate code for pushing this gets a little complex */
2464 /*-----------------------------------------------------------------*/
2465 static void genIpush (iCode *ic)
2466 {
2467 //  int size, offset=0;
2468
2469   FENTRY;
2470   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2471
2472   if(ic->parmPush) {
2473     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2474
2475     /* send to stack as normal */
2476     addSet(&_G.sendSet,ic);
2477 //    addSetHead(&_G.sendSet,ic);
2478     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2479   }
2480
2481
2482 #if 0
2483     int size, offset = 0 ;
2484     char *l;
2485
2486
2487     /* if this is not a parm push : ie. it is spill push
2488     and spill push is always done on the local stack */
2489     if (!ic->parmPush) {
2490
2491         /* and the item is spilt then do nothing */
2492         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2493             return ;
2494
2495         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2496         size = AOP_SIZE(IC_LEFT(ic));
2497         /* push it on the stack */
2498         while(size--) {
2499             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2500             if (*l == '#') {
2501                 MOVA(l);
2502                 l = "acc";
2503             }
2504             pic16_emitcode("push","%s",l);
2505         }
2506         return ;
2507     }
2508
2509     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2510 #endif
2511 }
2512
2513 /*-----------------------------------------------------------------*/
2514 /* genIpop - recover the registers: can happen only for spilling   */
2515 /*-----------------------------------------------------------------*/
2516 static void genIpop (iCode *ic)
2517 {
2518   FENTRY;
2519   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2520 #if 0
2521     int size,offset ;
2522
2523
2524     /* if the temp was not pushed then */
2525     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2526         return ;
2527
2528     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2529     size = AOP_SIZE(IC_LEFT(ic));
2530     offset = (size-1);
2531     while (size--)
2532         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2533                                    FALSE,TRUE));
2534
2535     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2536 #endif
2537 }
2538
2539 static int wparamCmp(void *p1, void *p2)
2540 {
2541   return (!strcmp((char *)p1, (char *)p2));
2542 }
2543
2544 int inWparamList(char *s)
2545 {
2546   return isinSetWith(wparamList, s, wparamCmp);
2547 }
2548
2549
2550 /*-----------------------------------------------------------------*/
2551 /* genCall - generates a call statement                            */
2552 /*-----------------------------------------------------------------*/
2553 static void genCall (iCode *ic)
2554 {
2555   sym_link *ftype;
2556   int stackParms=0;
2557   int use_wreg=0;
2558   int inwparam=0;
2559   char *fname;
2560
2561     FENTRY;
2562
2563     ftype = OP_SYM_TYPE(IC_LEFT(ic));
2564     /* if caller saves & we have not saved then */
2565 //    if (!ic->regsSaved)
2566 //      saveRegisters(ic);
2567
2568         /* initialise stackParms for IPUSH pushes */
2569 //      stackParms = psuedoStkPtr;
2570 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2571     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2572     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2573
2574 #if 0
2575     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2576 #endif
2577
2578     /* if send set is not empty the assign */
2579     if (_G.sendSet) {
2580       iCode *sic;
2581       int psuedoStkPtr=-1;
2582       int firstTimeThruLoop = 1;
2583
2584
2585         /* reverse sendSet if function is not reentrant */
2586         if(!IFFUNC_ISREENT(ftype))
2587           _G.sendSet = reverseSet(_G.sendSet);
2588
2589         /* First figure how many parameters are getting passed */
2590         stackParms = 0;
2591         use_wreg = 0;
2592
2593         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2594           int size;
2595 //          int offset = 0;
2596
2597             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2598             size = AOP_SIZE(IC_LEFT(sic));
2599
2600             stackParms += size;
2601
2602             /* pass the last byte through WREG */
2603             if(inwparam) {
2604
2605               while (size--) {
2606                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2607                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2608                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2609
2610                 if(!firstTimeThruLoop) {
2611                   /* If this is not the first time we've been through the loop
2612                    * then we need to save the parameter in a temporary
2613                    * register. The last byte of the last parameter is
2614                    * passed in W. */
2615
2616                   pushw();
2617 //                  --psuedoStkPtr;             // sanity check
2618                   use_wreg = 1;
2619                 }
2620
2621                 firstTimeThruLoop=0;
2622
2623                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2624
2625 //                offset++;
2626               }
2627             } else {
2628               /* all arguments are passed via stack */
2629               use_wreg = 0;
2630
2631               while (size--) {
2632                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2633                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2634                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2635
2636 //                pushaop(AOP(IC_LEFT(sic)), size);
2637                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2638
2639                 if(!_G.resDirect)
2640                   pushw();
2641               }
2642             }
2643
2644             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2645           }
2646
2647           if(inwparam) {
2648             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2649               pushw();  /* save last parameter to stack if functions has varargs */
2650               use_wreg = 0;
2651             } else
2652               use_wreg = 1;
2653           } else use_wreg = 0;
2654
2655           _G.stackRegSet = _G.sendSet;
2656           _G.sendSet = NULL;
2657     }
2658
2659     /* make the call */
2660     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2661
2662     GpsuedoStkPtr=0;
2663
2664     /* if we need to assign a result value */
2665     if ((IS_ITEMP(IC_RESULT(ic))
2666           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2667               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2668         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2669
2670       _G.accInUse++;
2671       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2672       _G.accInUse--;
2673
2674       /* Must not assign an 8-bit result to a 16-bit variable;
2675        * this would use (used...) the uninitialized PRODL! */
2676       /* FIXME: Need a proper way to obtain size of function result type,
2677        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2678       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2679
2680       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2681                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2682
2683       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2684     }
2685
2686     if(!stackParms && ic->parmBytes) {
2687       stackParms = ic->parmBytes;
2688     }
2689
2690     stackParms -= use_wreg;
2691
2692     if(stackParms>0) {
2693       if(stackParms == 1) {
2694         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
2695       } else {
2696         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2697         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2698       }
2699       if(STACK_MODEL_LARGE) {
2700         emitSKPNC;
2701         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
2702       }
2703     }
2704
2705 #if 0
2706     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2707 #endif
2708
2709     /* adjust the stack for parameters if required */
2710 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2711
2712 #if 0
2713       /* if register bank was saved then pop them */
2714       if (ic->bankSaved)
2715         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2716
2717       /* if we hade saved some registers then unsave them */
2718       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2719         unsaveRegisters (ic);
2720 #endif
2721 }
2722
2723
2724
2725 /*-----------------------------------------------------------------*/
2726 /* genPcall - generates a call by pointer statement                */
2727 /*            new version, created from genCall - HJD              */
2728 /*-----------------------------------------------------------------*/
2729 static void genPcall (iCode *ic)
2730 {
2731   sym_link *fntype;
2732   int stackParms=0;
2733   symbol *retlbl = newiTempLabel(NULL);
2734   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2735
2736     FENTRY;
2737
2738     fntype = operandType( IC_LEFT(ic) )->next;
2739
2740     /* if send set is not empty the assign */
2741     if (_G.sendSet) {
2742       iCode *sic;
2743       int psuedoStkPtr=-1;
2744
2745       /* reverse sendSet if function is not reentrant */
2746       if(!IFFUNC_ISREENT(fntype))
2747         _G.sendSet = reverseSet(_G.sendSet);
2748
2749       stackParms = 0;
2750
2751       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2752         int size;
2753
2754           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2755           size = AOP_SIZE(IC_LEFT(sic));
2756           stackParms += size;
2757
2758           /* all parameters are passed via stack, since WREG is clobbered
2759            * by the calling sequence */
2760           while (size--) {
2761             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2762             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2763             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2764
2765             pic16_mov2w (AOP(IC_LEFT(sic)), size);
2766             pushw();
2767           }
2768
2769           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2770       }
2771
2772       _G.stackRegSet = _G.sendSet;
2773       _G.sendSet = NULL;
2774     }
2775
2776     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2777
2778     // push return address
2779     // push $ on return stack, then replace with retlbl
2780
2781     /* Thanks to Thorsten Klose for pointing out that the following
2782      * snippet should be interrupt safe */
2783     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2784     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2785
2786     pic16_emitpcodeNULLop(POC_PUSH);
2787
2788     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2789     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2790     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2791     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2792     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2793     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2794
2795
2796     /* restore interrupt control register */
2797     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2798     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2799
2800     /* make the call by writing the pointer into pc */
2801     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2802     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2803
2804     // note: MOVFF to PCL not allowed
2805     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2806     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2807
2808
2809     /* return address is here: (X) */
2810     pic16_emitpLabelFORCE(retlbl->key);
2811
2812     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2813
2814     GpsuedoStkPtr=0;
2815     /* if we need assign a result value */
2816     if ((IS_ITEMP(IC_RESULT(ic))
2817           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2818               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2819         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2820
2821       _G.accInUse++;
2822       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2823       _G.accInUse--;
2824
2825       /* FIXME: Need proper way to obtain the function result's type.
2826        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2827       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2828
2829       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2830               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2831
2832       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2833     }
2834
2835 //    stackParms -= use_wreg;
2836
2837     if(stackParms>0) {
2838       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2839       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2840       if(STACK_MODEL_LARGE) {
2841         emitSKPNC;
2842         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2843       }
2844     }
2845 }
2846
2847 /*-----------------------------------------------------------------*/
2848 /* resultRemat - result  is rematerializable                       */
2849 /*-----------------------------------------------------------------*/
2850 static int resultRemat (iCode *ic)
2851 {
2852   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2853   if (SKIP_IC(ic) || ic->op == IFX)
2854     return 0;
2855
2856   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2857     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2858     if (sym->remat && !POINTER_SET(ic))
2859       return 1;
2860   }
2861
2862   return 0;
2863 }
2864
2865 #if 0
2866 /*-----------------------------------------------------------------*/
2867 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2868 /*-----------------------------------------------------------------*/
2869 static bool inExcludeList(char *s)
2870 {
2871   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2872     int i =0;
2873
2874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2875     if (options.excludeRegs[i] &&
2876     STRCASECMP(options.excludeRegs[i],"none") == 0)
2877         return FALSE ;
2878
2879     for ( i = 0 ; options.excludeRegs[i]; i++) {
2880         if (options.excludeRegs[i] &&
2881         STRCASECMP(s,options.excludeRegs[i]) == 0)
2882             return TRUE;
2883     }
2884     return FALSE ;
2885 }
2886 #endif
2887
2888 /*-----------------------------------------------------------------*/
2889 /* genFunction - generated code for function entry                 */
2890 /*-----------------------------------------------------------------*/
2891 static void genFunction (iCode *ic)
2892 {
2893   symbol *sym;
2894   sym_link *ftype;
2895
2896     FENTRY;
2897     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2898
2899     pic16_labelOffset += (max_key+4);
2900     max_key=0;
2901     GpsuedoStkPtr=0;
2902     _G.nRegsSaved = 0;
2903
2904     ftype = operandType(IC_LEFT(ic));
2905     sym = OP_SYMBOL(IC_LEFT(ic));
2906
2907     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2908       /* create an absolute section at the interrupt vector:
2909        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2910       symbol *asym;
2911       char asymname[128];
2912       pBlock *apb;
2913
2914 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2915
2916         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2917           sprintf(asymname, "ivec_%s", sym->name);
2918         else
2919           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2920
2921         /* when an interrupt is declared as naked, do not emit the special
2922          * wrapper segment at vector address. The user should take care for
2923          * this instead. -- VR */
2924
2925         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2926           asym = newSymbol(asymname, 0);
2927           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2928           pic16_addpBlock( apb );
2929
2930           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2931           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2932           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2933           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2934           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2935
2936           /* mark the end of this tiny function */
2937           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2938         } else {
2939           sprintf(asymname, "%s", sym->rname);
2940         }
2941
2942         {
2943           absSym *abSym;
2944
2945             abSym = Safe_calloc(1, sizeof(absSym));
2946             strcpy(abSym->name, asymname);
2947
2948             switch( FUNC_INTNO(sym->type) ) {
2949               case 0: abSym->address = 0x000000; break;
2950               case 1: abSym->address = 0x000008; break;
2951               case 2: abSym->address = 0x000018; break;
2952
2953               default:
2954 //                fprintf(stderr, "no interrupt number is given\n");
2955                 abSym->address = -1; break;
2956             }
2957
2958             /* relocate interrupt vectors if needed */
2959             if(abSym->address != -1)
2960               abSym->address += pic16_options.ivt_loc;
2961
2962             addSet(&absSymSet, abSym);
2963         }
2964     }
2965
2966     /* create the function header */
2967     pic16_emitcode(";","-----------------------------------------");
2968     pic16_emitcode(";"," function %s",sym->name);
2969     pic16_emitcode(";","-----------------------------------------");
2970
2971     /* prevent this symbol from being emitted as 'extern' */
2972     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2973
2974     pic16_emitcode("","%s:",sym->rname);
2975     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2976
2977     {
2978       absSym *ab;
2979
2980         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2981           if(!strcmp(ab->name, sym->rname)) {
2982             pic16_pBlockConvert2Absolute(pb);
2983             break;
2984           }
2985         }
2986     }
2987
2988     if(IFFUNC_ISNAKED(ftype)) {
2989       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2990       return;
2991     }
2992
2993     /* if critical function then turn interrupts off */
2994     if (IFFUNC_ISCRITICAL(ftype)) {
2995       //pic16_emitcode("clr","ea");
2996     }
2997
2998     currFunc = sym;             /* update the currFunc symbol */
2999     _G.fregsUsed = sym->regsUsed;
3000     _G.sregsAlloc = newBitVect(128);
3001
3002
3003     /* if this is an interrupt service routine then
3004      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3005     if (IFFUNC_ISISR(sym->type)) {
3006         _G.usefastretfie = 1;   /* use shadow registers by default */
3007
3008         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3009         if(!FUNC_ISSHADOWREGS(sym->type)) {
3010           /* do not save WREG,STATUS,BSR for high priority interrupts
3011            * because they are stored in the hardware shadow registers already */
3012           _G.usefastretfie = 0;
3013           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3014           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3015           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3016         }
3017
3018         /* these should really be optimized somehow, because not all
3019          * interrupt handlers modify them */
3020         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3021         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3022         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3023         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3024         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3025         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3026
3027 //        pic16_pBlockConvert2ISR(pb);
3028     }
3029
3030     /* emit code to setup stack frame if user enabled,
3031      * and function is not main() */
3032
3033 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3034     if(strcmp(sym->name, "main")) {
3035       if(0
3036         || !options.ommitFramePtr
3037 //        || sym->regsUsed
3038         || IFFUNC_ARGS(sym->type)
3039         || FUNC_HASSTACKPARM(sym->etype)
3040         ) {
3041         /* setup the stack frame */
3042         if(STACK_MODEL_LARGE)
3043           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3044         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3045
3046         if(STACK_MODEL_LARGE)
3047           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3048         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3049       }
3050     }
3051
3052     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3053           && sym->stack) {
3054
3055       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3056
3057       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3058       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3059       emitSKPC;
3060       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3061     }
3062
3063     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3064       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3065         _G.useWreg = 0;
3066       else
3067         _G.useWreg = 1;
3068     } else
3069       _G.useWreg = 0;
3070
3071     /* if callee-save to be used for this function
3072      * then save the registers being used in this function */
3073 //    if (IFFUNC_CALLEESAVES(sym->type))
3074     if(strcmp(sym->name, "main")) {
3075       int i;
3076
3077         /* if any registers used */
3078         if (sym->regsUsed) {
3079                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3080
3081           if(!xinst) {
3082             /* save the registers used */
3083             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3084             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3085               if (bitVectBitValue(sym->regsUsed,i)) {
3086 #if 0
3087                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3088 #endif
3089                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3090                 _G.nRegsSaved++;
3091
3092                 if(!pic16_regWithIdx(i)->wasUsed) {
3093                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3094                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3095                   pic16_regWithIdx(i)->wasUsed = 1;
3096                 }
3097               }
3098             }
3099           } else {
3100
3101             /* xinst */
3102             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3103             for(i=0;i<sym->regsUsed->size;i++) {
3104               if(bitVectBitValue(sym->regsUsed, i)) {
3105                 _G.nRegsSaved++;
3106               }
3107             }
3108
3109 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3110           }
3111
3112           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3113
3114         }
3115     }
3116
3117     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3118 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3119 }
3120
3121 /*-----------------------------------------------------------------*/
3122 /* genEndFunction - generates epilogue for functions               */
3123 /*-----------------------------------------------------------------*/
3124 static void genEndFunction (iCode *ic)
3125 {
3126   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3127
3128     FENTRY;
3129
3130     if(IFFUNC_ISNAKED(sym->type)) {
3131       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3132       return;
3133     }
3134
3135     _G.stack_lat = 0;
3136
3137     /* add code for ISCRITICAL */
3138     if(IFFUNC_ISCRITICAL(sym->type)) {
3139       /* if critical function, turn on interrupts */
3140
3141       /* TODO: add code here -- VR */
3142     }
3143
3144 //    sym->regsUsed = _G.fregsUsed;
3145
3146     /* now we need to restore the registers */
3147     /* if any registers used */
3148
3149     /* first restore registers that might be used for stack access */
3150     if(_G.sregsAllocSet) {
3151     regs *sr;
3152
3153       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3154       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3155         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3156       }
3157     }
3158
3159     if (strcmp(sym->name, "main") && sym->regsUsed) {
3160       int i;
3161
3162         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3163         /* restore registers used */
3164         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3165         for ( i = sym->regsUsed->size; i >= 0; i--) {
3166           if (bitVectBitValue(sym->regsUsed,i)) {
3167             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3168             _G.nRegsSaved--;
3169           }
3170         }
3171         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3172     }
3173
3174
3175
3176     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3177           && sym->stack) {
3178       if (sym->stack == 1) {
3179         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3180         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3181       } else {
3182         // we have to add more than one...
3183         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3184         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3185         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3186         emitSKPNC;
3187         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3188         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3189         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3190       }
3191     }
3192
3193     if(strcmp(sym->name, "main")) {
3194       if(0
3195         || !options.ommitFramePtr
3196 //        || sym->regsUsed
3197         || IFFUNC_ARGS(sym->type)
3198         || FUNC_HASSTACKPARM(sym->etype)
3199         ) {
3200         /* restore stack frame */
3201         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3202         if(STACK_MODEL_LARGE)
3203           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3204       }
3205     }
3206
3207     _G.useWreg = 0;
3208
3209     if (IFFUNC_ISISR(sym->type)) {
3210       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3211       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3212       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3213       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3214       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3215       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3216
3217       if(!FUNC_ISSHADOWREGS(sym->type)) {
3218         /* do not restore interrupt vector for WREG,STATUS,BSR
3219          * for high priority interrupt, see genFunction */
3220         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3221         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3222         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3223       }
3224 //      _G.interruptvector = 0;         /* sanity check */
3225
3226
3227       /* if debug then send end of function */
3228 /*      if (options.debug && currFunc)  */
3229       if (currFunc) {
3230         debugFile->writeEndFunction (currFunc, ic, 1);
3231       }
3232
3233       if(_G.usefastretfie)
3234         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3235       else
3236         pic16_emitpcodeNULLop(POC_RETFIE);
3237
3238       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3239
3240       _G.usefastretfie = 0;
3241       return;
3242     }
3243
3244     if (IFFUNC_ISCRITICAL(sym->type)) {
3245       pic16_emitcode("setb","ea");
3246     }
3247
3248     /* if debug then send end of function */
3249     if (currFunc) {
3250       debugFile->writeEndFunction (currFunc, ic, 1);
3251     }
3252
3253     /* insert code to restore stack frame, if user enabled it
3254      * and function is not main() */
3255
3256
3257     pic16_emitpcodeNULLop(POC_RETURN);
3258
3259     /* Mark the end of a function */
3260     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3261 }
3262
3263
3264 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3265 {
3266   unsigned long lit=1;
3267   operand *op;
3268
3269     op = IC_LEFT(ic);
3270
3271     // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3272     if(AOP_TYPE(op) == AOP_LIT) {
3273       if(!IS_FLOAT(operandType( op ))) {
3274         lit = ulFromVal (AOP(op)->aopu.aop_lit);
3275       } else {
3276         union {
3277           unsigned long lit_int;
3278           float lit_float;
3279         } info;
3280
3281         /* take care if literal is a float */
3282         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3283         lit = info.lit_int;
3284       }
3285     }
3286
3287     if (AOP_TYPE(op) == AOP_LIT) {
3288       /* FIXME: broken for
3289        *   char __at(0x456) foo;
3290        *   return &foo;
3291        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3292       pic16_movLit2f(dest, (lit >> (8ul*offset)));
3293     } else if (AOP_TYPE(op) == AOP_PCODE
3294                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3295       /* char *s= "aaa"; return s; */
3296       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3297        *      that the generic pointer is interpreted correctly
3298        *      as referring to __code space, but this is fragile! */
3299       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3300       /* XXX: should check that dest != WREG */
3301       pic16_emitpcode(POC_MOVWF, dest);
3302     } else {
3303       if(dest->type == PO_WREG && (offset == 0)) {
3304         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3305         return;
3306       }
3307       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3308     }
3309 }
3310
3311 /*-----------------------------------------------------------------*/
3312 /* genRet - generate code for return statement                     */
3313 /*-----------------------------------------------------------------*/
3314 static void genRet (iCode *ic)
3315 {
3316   int size;
3317   operand *left;
3318
3319     FENTRY;
3320         /* if we have no return value then
3321          * just generate the "ret" */
3322
3323         if (!IC_LEFT(ic))
3324                 goto jumpret;
3325
3326         /* we have something to return then
3327          * move the return value into place */
3328         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3329         size = AOP_SIZE(IC_LEFT(ic));
3330
3331         if(size <= 4) {
3332           if(size>3)
3333             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3334
3335           if(size>2)
3336             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3337
3338           if(size>1)
3339             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3340
3341           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3342
3343         } else {
3344                 /* >32-bits, setup stack and FSR0 */
3345                 while (size--) {
3346 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3347 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3348
3349                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3350
3351 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3352                         GpsuedoStkPtr++;
3353                 }
3354
3355                 /* setup FSR0 */
3356                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3357                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3358
3359                 if(STACK_MODEL_LARGE) {
3360                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3361                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3362                 } else {
3363                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3364                 }
3365         }
3366
3367         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3368
3369 jumpret:
3370         /* generate a jump to the return label
3371          * if the next is not the return statement */
3372         if (!(ic->next && ic->next->op == LABEL
3373                 && IC_LABEL(ic->next) == returnLabel)) {
3374
3375                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3376                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3377         }
3378 }
3379
3380 /*-----------------------------------------------------------------*/
3381 /* genLabel - generates a label                                    */
3382 /*-----------------------------------------------------------------*/
3383 static void genLabel (iCode *ic)
3384 {
3385   FENTRY;
3386
3387   /* special case never generate */
3388   if (IC_LABEL(ic) == entryLabel)
3389     return ;
3390
3391   pic16_emitpLabel(IC_LABEL(ic)->key);
3392 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3393 }
3394
3395 /*-----------------------------------------------------------------*/
3396 /* genGoto - generates a goto                                      */
3397 /*-----------------------------------------------------------------*/
3398 //tsd
3399 static void genGoto (iCode *ic)
3400 {
3401   FENTRY;
3402   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3403 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3404 }
3405
3406
3407 /*-----------------------------------------------------------------*/
3408 /* genMultbits :- multiplication of bits                           */
3409 /*-----------------------------------------------------------------*/
3410 static void genMultbits (operand *left,
3411                          operand *right,
3412                          operand *result)
3413 {
3414   FENTRY;
3415
3416   if(!pic16_sameRegs(AOP(result),AOP(right)))
3417     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3418
3419   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3420   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3421   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3422
3423 }
3424
3425
3426 /*-----------------------------------------------------------------*/
3427 /* genMultOneByte : 8 bit multiplication & division                */
3428 /*-----------------------------------------------------------------*/
3429 static void genMultOneByte (operand *left,
3430                             operand *right,
3431                             operand *result)
3432 {
3433
3434   FENTRY;
3435   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3436   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3437
3438   /* (if two literals, the value is computed before) */
3439   /* if one literal, literal on the right */
3440   if (AOP_TYPE(left) == AOP_LIT){
3441     operand *t = right;
3442     right = left;
3443     left = t;
3444   }
3445
3446         /* size is already checked in genMult == 1 */
3447 //      size = AOP_SIZE(result);
3448
3449         if (AOP_TYPE(right) == AOP_LIT){
3450                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3451                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3452                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3453                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3454         } else {
3455                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3456                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3457                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3458                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3459         }
3460
3461         pic16_genMult8X8_n (left, right,result);
3462 }
3463
3464 #if 0
3465 /*-----------------------------------------------------------------*/
3466 /* genMultOneWord : 16 bit multiplication                          */
3467 /*-----------------------------------------------------------------*/
3468 static void genMultOneWord (operand *left,
3469                             operand *right,
3470                             operand *result)
3471 {
3472   FENTRY;
3473   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3474   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3475
3476   /* (if two literals, the value is computed before)
3477    * if one literal, literal on the right */
3478   if (AOP_TYPE(left) == AOP_LIT){
3479     operand *t = right;
3480     right = left;
3481     left = t;
3482   }
3483
3484   /* size is checked already == 2 */
3485 //  size = AOP_SIZE(result);
3486
3487   if (AOP_TYPE(right) == AOP_LIT) {
3488     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3489       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3490       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3491       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3492   } else {
3493     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3494       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3495       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3496       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3497   }
3498
3499   pic16_genMult16X16_16(left, right,result);
3500 }
3501 #endif
3502
3503 #if 0
3504 /*-----------------------------------------------------------------*/
3505 /* genMultOneLong : 32 bit multiplication                          */
3506 /*-----------------------------------------------------------------*/
3507 static void genMultOneLong (operand *left,
3508                             operand *right,
3509                             operand *result)
3510 {
3511   FENTRY;
3512   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3513   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3514
3515   /* (if two literals, the value is computed before)
3516    * if one literal, literal on the right */
3517   if (AOP_TYPE(left) == AOP_LIT){
3518     operand *t = right;
3519     right = left;
3520     left = t;
3521   }
3522
3523   /* size is checked already == 4 */
3524 //  size = AOP_SIZE(result);
3525
3526   if (AOP_TYPE(right) == AOP_LIT) {
3527     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3528         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3529         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3530         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3531   } else {
3532     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3533         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3534         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3535         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3536   }
3537
3538   pic16_genMult32X32_32(left, right,result);
3539 }
3540 #endif
3541
3542
3543
3544 /*-----------------------------------------------------------------*/
3545 /* genMult - generates code for multiplication                     */
3546 /*-----------------------------------------------------------------*/
3547 static void genMult (iCode *ic)
3548 {
3549   operand *left = IC_LEFT(ic);
3550   operand *right = IC_RIGHT(ic);
3551   operand *result= IC_RESULT(ic);
3552
3553     FENTRY;
3554         /* assign the amsops */
3555         pic16_aopOp (left,ic,FALSE);
3556         pic16_aopOp (right,ic,FALSE);
3557         pic16_aopOp (result,ic,TRUE);
3558
3559         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3560
3561         /* special cases first *
3562         * both are bits */
3563         if (AOP_TYPE(left) == AOP_CRY
3564                 && AOP_TYPE(right)== AOP_CRY) {
3565                 genMultbits(left,right,result);
3566           goto release ;
3567         }
3568
3569         /* if both are of size == 1 */
3570         if(AOP_SIZE(left) == 1
3571                 && AOP_SIZE(right) == 1) {
3572                 genMultOneByte(left,right,result);
3573           goto release ;
3574         }
3575
3576 #if 0
3577         /* if both are of size == 2 */
3578         if(AOP_SIZE(left) == 2
3579                 && AOP_SIZE(right) == 2) {
3580                 genMultOneWord(left, right, result);
3581           goto release;
3582         }
3583
3584         /* if both are of size == 4 */
3585         if(AOP_SIZE(left) == 4
3586                 && AOP_SIZE(right) == 4) {
3587                 genMultOneLong(left, right, result);
3588           goto release;
3589         }
3590 #endif
3591
3592         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3593         assert( !"Multiplication should have been transformed into function call!" );
3594
3595         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3596
3597
3598         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3599         /* should have been converted to function call */
3600         assert(0) ;
3601
3602 release :
3603         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3604         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3605         pic16_freeAsmop(result,NULL,ic,TRUE);
3606 }
3607
3608 #if 0
3609 /*-----------------------------------------------------------------*/
3610 /* genDivbits :- division of bits                                  */
3611 /*-----------------------------------------------------------------*/
3612 static void genDivbits (operand *left,
3613                         operand *right,
3614                         operand *result)
3615 {
3616   char *l;
3617
3618     FENTRY;
3619     /* the result must be bit */
3620     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3621     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3622
3623     MOVA(l);
3624
3625     pic16_emitcode("div","ab");
3626     pic16_emitcode("rrc","a");
3627     pic16_aopPut(AOP(result),"c",0);
3628 }
3629
3630 /*-----------------------------------------------------------------*/
3631 /* genDivOneByte : 8 bit division                                  */
3632 /*-----------------------------------------------------------------*/
3633 static void genDivOneByte (operand *left,
3634                            operand *right,
3635                            operand *result)
3636 {
3637   sym_link *opetype = operandType(result);
3638   char *l ;
3639   symbol *lbl ;
3640   int size,offset;
3641
3642         /* result = divident / divisor
3643          * - divident may be a register or a literal,
3644          * - divisor may be a register or a literal,
3645          * so there are 3 cases (literal / literal is optimized
3646          * by the front-end) to handle.
3647          * In addition we must handle signed and unsigned, which
3648          * result in 6 final different cases -- VR */
3649
3650     FENTRY;
3651
3652     size = AOP_SIZE(result) - 1;
3653     offset = 1;
3654     /* signed or unsigned */
3655     if (SPEC_USIGN(opetype)) {
3656       pCodeOp *pct1,    /* count */
3657                 *pct2,  /* reste */
3658                 *pct3;  /* temp */
3659       symbol *label1, *label2, *label3;;
3660
3661
3662         /* unsigned is easy */
3663
3664         pct1 = pic16_popGetTempReg(1);
3665         pct2 = pic16_popGetTempReg(1);
3666         pct3 = pic16_popGetTempReg(1);
3667
3668         label1 = newiTempLabel(NULL);
3669         label2 = newiTempLabel(NULL);
3670         label3 = newiTempLabel(NULL);
3671
3672         /* the following algorithm is extracted from divuint.c */
3673
3674         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3675         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3676
3677         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3678
3679         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3680
3681         pic16_emitpLabel(label1->key);
3682
3683         emitCLRC;
3684         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3685
3686
3687         emitCLRC;
3688         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3689
3690
3691         emitSKPNC;
3692         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3693
3694         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3695         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3696
3697         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3698         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3699         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3700
3701         pic16_emitpLabel( label3->key );
3702         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3703         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3704
3705
3706
3707         pic16_emitpLabel(label2->key);
3708         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3709         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3710         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3711
3712         /* result is in wreg */
3713         if(AOP_TYPE(result) != AOP_ACC)
3714                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3715
3716         pic16_popReleaseTempReg( pct3, 1);
3717         pic16_popReleaseTempReg( pct2, 1);
3718         pic16_popReleaseTempReg( pct1, 1);
3719
3720         return ;
3721     }
3722
3723     /* signed is a little bit more difficult */
3724
3725     /* save the signs of the operands */
3726     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3727     MOVA(l);
3728     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3729     pic16_emitcode("push","acc"); /* save it on the stack */
3730
3731     /* now sign adjust for both left & right */
3732     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
3733     MOVA(l);
3734     lbl = newiTempLabel(NULL);
3735     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3736     pic16_emitcode("cpl","a");
3737     pic16_emitcode("inc","a");
3738     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3739     pic16_emitcode("mov","b,a");
3740
3741     /* sign adjust left side */
3742     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
3743     MOVA(l);
3744
3745     lbl = newiTempLabel(NULL);
3746     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3747     pic16_emitcode("cpl","a");
3748     pic16_emitcode("inc","a");
3749     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3750
3751     /* now the division */
3752     pic16_emitcode("div","ab");
3753     /* we are interested in the lower order
3754     only */
3755     pic16_emitcode("mov","b,a");
3756     lbl = newiTempLabel(NULL);
3757     pic16_emitcode("pop","acc");
3758     /* if there was an over flow we don't
3759     adjust the sign of the result */
3760     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3761     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3762     CLRC;
3763     pic16_emitcode("clr","a");
3764     pic16_emitcode("subb","a,b");
3765     pic16_emitcode("mov","b,a");
3766     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3767
3768     /* now we are done */
3769     pic16_aopPut(AOP(result),"b",0);
3770     if(size > 0){
3771         pic16_emitcode("mov","c,b.7");
3772         pic16_emitcode("subb","a,acc");
3773     }
3774     while (size--)
3775         pic16_aopPut(AOP(result),"a",offset++);
3776
3777 }
3778 #endif
3779
3780 /*-----------------------------------------------------------------*/
3781 /* genDiv - generates code for division                            */
3782 /*-----------------------------------------------------------------*/
3783 static void genDiv (iCode *ic)
3784 {
3785     operand *left = IC_LEFT(ic);
3786     operand *right = IC_RIGHT(ic);
3787     operand *result= IC_RESULT(ic);
3788     int negated = 0;
3789     int leftVal = 0, rightVal = 0;
3790     int signedLits = 0;
3791     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3792     int op = 0;
3793
3794         /* Division is a very lengthy algorithm, so it is better
3795          * to call support routines than inlining algorithm.
3796          * Division functions written here just in case someone
3797          * wants to inline and not use the support libraries -- VR */
3798
3799     FENTRY;
3800
3801     /* assign the amsops */
3802     pic16_aopOp (left,ic,FALSE);
3803     pic16_aopOp (right,ic,FALSE);
3804     pic16_aopOp (result,ic,TRUE);
3805
3806     if (ic->op == '/')
3807       op = 0;
3808     else if (ic->op == '%')
3809       op = 1;
3810     else
3811       assert( !"invalid operation requested in genDivMod" );
3812
3813     /* get literal values */
3814     if (IS_VALOP(left)) {
3815       leftVal = (int) ulFromVal ( OP_VALUE(left) );
3816       assert( leftVal >= -128 && leftVal < 256 );
3817       if (leftVal < 0) { signedLits++; }
3818     }
3819     if (IS_VALOP(right)) {
3820       rightVal = (int) ulFromVal ( OP_VALUE(right) );
3821       assert( rightVal >= -128 && rightVal < 256 );
3822       if (rightVal < 0) { signedLits++; }
3823     }
3824
3825     /* We should only come here to convert all
3826      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3827      * with exactly one operand being s8_t into
3828      * u8_t x u8_t -> u8_t. All other cases should have been
3829      * turned into calls to support routines beforehand... */
3830     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3831         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3832     {
3833       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3834           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3835       {
3836         /* Both operands are signed or negative, use _divschar
3837          * instead of _divuchar */
3838         pushaop(AOP(right), 0);
3839         pushaop(AOP(left), 0);
3840
3841         /* call _divschar */
3842         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3843
3844         {
3845           symbol *sym;
3846           sym = newSymbol( functions[op][0], 0 );
3847           sym->used++;
3848           strcpy(sym->rname, functions[op][0]);
3849           checkAddSym(&externs, sym);
3850         }
3851
3852         /* assign result */
3853         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3854         if (AOP_SIZE(result) > 1)
3855         {
3856           pic16_emitpcode(POC_MOVFF,
3857               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3858                 pic16_popGet(AOP(result), 1)));
3859           /* sign extend */
3860           pic16_addSign(result, 2, 1);
3861         }
3862
3863         /* clean up stack */
3864         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3865         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3866
3867         goto release;
3868       }
3869
3870       /* push right operand */
3871       if (IS_VALOP(right)) {
3872         if (rightVal < 0) {
3873           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3874           negated++;
3875         } else {
3876           pushaop(AOP(right), 0);
3877         }
3878       } else if (!IS_UNSIGNED(operandType(right))) {
3879         pic16_mov2w(AOP(right), 0);
3880         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3881         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3882         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3883         negated++;
3884       } else {
3885         pushaop(AOP(right), 0);
3886       }
3887
3888       /* push left operand */
3889       if (IS_VALOP(left)) {
3890         if (leftVal < 0) {
3891           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3892           negated++;
3893         } else {
3894           pushaop(AOP(left), 0);
3895         }
3896       } else if (!IS_UNSIGNED(operandType(left))) {
3897         pic16_mov2w(AOP(left),0);
3898         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3899         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3900         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3901         negated++;
3902       } else {
3903         pushaop(AOP(left), 0);
3904       }
3905
3906       /* call _divuchar */
3907       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3908
3909       {
3910         symbol *sym;
3911         sym = newSymbol( functions[op][1], 0 );
3912         sym->used++;
3913         strcpy(sym->rname, functions[op][1]);
3914         checkAddSym(&externs, sym);
3915       }
3916
3917       /* Revert negation(s) from above.
3918        * This is inefficient: if both operands are negative, this
3919        * should not touch WREG. However, determining that exactly
3920        * one operand was negated costs at least 3 instructions,
3921        * so there is nothing to be gained here, is there?
3922        *
3923        * I negate WREG because either operand might share registers with
3924        * result, so assigning first might destroy an operand. */
3925
3926       /* For the modulus operator, (a/b)*b == a shall hold.
3927        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3928        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
3929        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
3930        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
3931        * Only invert the result if the left operand is negative (sigh).
3932        */
3933       if (AOP_SIZE(result) <= 1 || !negated)
3934       {
3935         if (ic->op == '/')
3936         {
3937           if (IS_VALOP(right)) {
3938             if (rightVal < 0) {
3939               /* we negated this operand above */
3940               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3941             }
3942           } else if (!IS_UNSIGNED(operandType(right))) {
3943             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3944             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3945           }
3946         }
3947
3948         if (IS_VALOP(left)) {
3949           if (leftVal < 0) {
3950             /* we negated this operand above */
3951             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3952           }
3953         } else if (!IS_UNSIGNED(operandType(left))) {
3954           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3955           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3956         }
3957
3958         /* Move result to destination. */
3959         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3960
3961         /* Zero-extend:  no operand was signed (or result is just a byte). */
3962         pic16_addSign(result, 1, 0);
3963       } else {
3964         assert( AOP_SIZE(result) > 1 );
3965         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3966         if (ic->op == '/')
3967         {
3968           if (IS_VALOP(right)) {
3969             if (rightVal < 0) {
3970               /* we negated this operand above */
3971               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3972             }
3973           } else if (!IS_UNSIGNED(operandType(right))) {
3974             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3975             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3976           }
3977         }
3978
3979         if (IS_VALOP(left)) {
3980           if (leftVal < 0) {
3981             /* we negated this operand above */
3982             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3983           }
3984         } else if (!IS_UNSIGNED(operandType(left))) {
3985           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3986           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3987         }
3988
3989         /* Move result to destination. */
3990         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3991
3992         /* Negate result if required. */
3993         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
3994         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
3995
3996         /* Sign-extend. */
3997         pic16_addSign(result, 2, 1);
3998       }
3999
4000       /* clean up stack */
4001       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4002       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4003       goto release;
4004     }
4005
4006 #if 0
4007     /* special cases first */
4008     /* both are bits */
4009     if (AOP_TYPE(left) == AOP_CRY &&
4010         AOP_TYPE(right)== AOP_CRY) {
4011         genDivbits(left,right,result);
4012         goto release ;
4013     }
4014
4015     /* if both are of size == 1 */
4016     if (AOP_SIZE(left) == 1 &&
4017         AOP_SIZE(right) == 1 ) {
4018         genDivOneByte(left,right,result);
4019         goto release ;
4020     }
4021 #endif
4022
4023     /* should have been converted to function call */
4024     assert(0);
4025 release :
4026     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4027     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4028     pic16_freeAsmop(result,NULL,ic,TRUE);
4029 }
4030
4031 #if 0
4032 /*-----------------------------------------------------------------*/
4033 /* genModbits :- modulus of bits                                   */
4034 /*-----------------------------------------------------------------*/
4035 static void genModbits (operand *left,
4036                         operand *right,
4037                         operand *result)
4038 {
4039   char *l;
4040
4041     FENTRY;
4042
4043     werror(W_POSSBUG2, __FILE__, __LINE__);
4044     /* the result must be bit */
4045     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4046     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4047
4048     MOVA(l);
4049
4050     pic16_emitcode("div","ab");
4051     pic16_emitcode("mov","a,b");
4052     pic16_emitcode("rrc","a");
4053     pic16_aopPut(AOP(result),"c",0);
4054 }
4055
4056 /*-----------------------------------------------------------------*/
4057 /* genModOneByte : 8 bit modulus                                   */
4058 /*-----------------------------------------------------------------*/
4059 static void genModOneByte (operand *left,
4060                            operand *right,
4061                            operand *result)
4062 {
4063   sym_link *opetype = operandType(result);
4064   char *l ;
4065   symbol *lbl ;
4066
4067     FENTRY;
4068     werror(W_POSSBUG2, __FILE__, __LINE__);
4069
4070     /* signed or unsigned */
4071     if (SPEC_USIGN(opetype)) {
4072         /* unsigned is easy */
4073         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4074         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4075         MOVA(l);
4076         pic16_emitcode("div","ab");
4077         pic16_aopPut(AOP(result),"b",0);
4078         return ;
4079     }
4080
4081     /* signed is a little bit more difficult */
4082
4083     /* save the signs of the operands */
4084     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4085     MOVA(l);
4086
4087     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4088     pic16_emitcode("push","acc"); /* save it on the stack */
4089
4090     /* now sign adjust for both left & right */
4091     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4092     MOVA(l);
4093
4094     lbl = newiTempLabel(NULL);
4095     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4096     pic16_emitcode("cpl","a");
4097     pic16_emitcode("inc","a");
4098     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4099     pic16_emitcode("mov","b,a");
4100
4101     /* sign adjust left side */
4102     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4103     MOVA(l);
4104
4105     lbl = newiTempLabel(NULL);
4106     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4107     pic16_emitcode("cpl","a");
4108     pic16_emitcode("inc","a");
4109     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4110
4111     /* now the multiplication */
4112     pic16_emitcode("div","ab");
4113     /* we are interested in the lower order
4114     only */
4115     lbl = newiTempLabel(NULL);
4116     pic16_emitcode("pop","acc");
4117     /* if there was an over flow we don't
4118     adjust the sign of the result */
4119     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4120     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4121     CLRC ;
4122     pic16_emitcode("clr","a");
4123     pic16_emitcode("subb","a,b");
4124     pic16_emitcode("mov","b,a");
4125     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4126
4127     /* now we are done */
4128     pic16_aopPut(AOP(result),"b",0);
4129
4130 }
4131 #endif
4132
4133 /*-----------------------------------------------------------------*/
4134 /* genMod - generates code for division                            */
4135 /*-----------------------------------------------------------------*/
4136 static void genMod (iCode *ic)
4137 {
4138   /* Task deferred to genDiv */
4139   genDiv(ic);
4140 #if 0
4141   operand *left = IC_LEFT(ic);
4142   operand *right = IC_RIGHT(ic);
4143   operand *result= IC_RESULT(ic);
4144
4145     FENTRY;
4146
4147     /* assign the amsops */
4148     pic16_aopOp (left,ic,FALSE);
4149     pic16_aopOp (right,ic,FALSE);
4150     pic16_aopOp (result,ic,TRUE);
4151
4152     /* special cases first */
4153     /* both are bits */
4154     if (AOP_TYPE(left) == AOP_CRY &&
4155         AOP_TYPE(right)== AOP_CRY) {
4156         genModbits(left,right,result);
4157         goto release ;
4158     }
4159
4160     /* if both are of size == 1 */
4161     if (AOP_SIZE(left) == 1 &&
4162         AOP_SIZE(right) == 1 ) {
4163         genModOneByte(left,right,result);
4164         goto release ;
4165     }
4166
4167     /* should have been converted to function call */
4168     assert(0);
4169
4170 release :
4171     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4172     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173     pic16_freeAsmop(result,NULL,ic,TRUE);
4174 #endif
4175 }
4176
4177 /*-----------------------------------------------------------------*/
4178 /* genIfxJump :- will create a jump depending on the ifx           */
4179 /*-----------------------------------------------------------------*/
4180 /*
4181   note: May need to add parameter to indicate when a variable is in bit space.
4182 */
4183 static void genIfxJump (iCode *ic, char *jval)
4184 {
4185   FENTRY;
4186
4187     /* if true label then we jump if condition
4188     supplied is true */
4189     if ( IC_TRUE(ic) ) {
4190
4191         if(strcmp(jval,"a") == 0)
4192           emitSKPZ;
4193         else if (strcmp(jval,"c") == 0)
4194           emitSKPNC;
4195         else {
4196           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4197           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4198         }
4199
4200         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4201         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4202
4203     }
4204     else {
4205         /* false label is present */
4206         if(strcmp(jval,"a") == 0)
4207           emitSKPNZ;
4208         else if (strcmp(jval,"c") == 0)
4209           emitSKPC;
4210         else {
4211           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4212           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4213         }
4214
4215         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4216         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4217
4218     }
4219
4220
4221     /* mark the icode as generated */
4222     ic->generated = 1;
4223 }
4224
4225 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4226 {
4227   FENTRY;
4228
4229     /* if true label then we jump if condition
4230     supplied is true */
4231     if ( IC_TRUE(ic) ) {
4232       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4233       pic16_emitpcode(POC_BTFSC, jop);
4234
4235       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4236       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4237
4238     } else {
4239       /* false label is present */
4240       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4241       pic16_emitpcode(POC_BTFSS, jop);
4242
4243       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4244       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4245     }
4246
4247
4248     /* mark the icode as generated */
4249     ic->generated = 1;
4250 }
4251
4252 #if 0
4253 // not needed ATM
4254
4255 /*-----------------------------------------------------------------*/
4256 /* genSkip                                                         */
4257 /*-----------------------------------------------------------------*/
4258 static void genSkip(iCode *ifx,int status_bit)
4259 {
4260   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4261   if(!ifx)
4262     return;
4263
4264   if ( IC_TRUE(ifx) ) {
4265     switch(status_bit) {
4266     case 'z':
4267       emitSKPNZ;
4268       break;
4269
4270     case 'c':
4271       emitSKPNC;
4272       break;
4273
4274     case 'd':
4275       emitSKPDC;
4276       break;
4277
4278     }
4279
4280     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4281     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4282
4283   } else {
4284
4285     switch(status_bit) {
4286
4287     case 'z':
4288       emitSKPZ;
4289       break;
4290
4291     case 'c':
4292       emitSKPC;
4293       break;
4294
4295     case 'd':
4296       emitSKPDC;
4297       break;
4298     }
4299     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4300     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4301
4302   }
4303
4304 }
4305 #endif
4306
4307 /*-----------------------------------------------------------------*/
4308 /* genSkipc                                                        */
4309 /*-----------------------------------------------------------------*/
4310 static void genSkipc(resolvedIfx *rifx)
4311 {
4312   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4313
4314   if(!rifx)
4315     return;
4316
4317   if(rifx->condition)
4318     emitSKPNC;
4319   else
4320     emitSKPC;
4321
4322   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4323   rifx->generated = 1;
4324 }
4325
4326 /*-----------------------------------------------------------------*/
4327 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4328 /*                  aop (if it's NOT a literal) or from lit (if    */
4329 /*                  aop is a literal)                              */
4330 /*-----------------------------------------------------------------*/
4331 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4332   if (aop->type == AOP_LIT) {
4333     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4334   } else {
4335     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4336   }
4337 }
4338
4339 /*-----------------------------------------------------------------*/
4340 /* genCmp :- greater or less than comparison                       */
4341 /*-----------------------------------------------------------------*/
4342
4343 /* genCmp performs a left < right comparison, stores
4344  * the outcome in result (if != NULL) and generates
4345  * control flow code for the ifx (if != NULL).
4346  *
4347  * This version leaves in sequences like
4348  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4349  * which should be optmized by the peephole
4350  * optimizer - RN 2005-01-01 */
4351 static void genCmp (operand *left,operand *right,
4352                     operand *result, iCode *ifx, int sign)
4353 {
4354   resolvedIfx rIfx;
4355   int size;
4356   int offs;
4357   symbol *templbl;
4358   operand *dummy;
4359   unsigned long lit;
4360   unsigned long mask;
4361   int performedLt;
4362
4363   FENTRY;
4364
4365   assert (left && right);
4366   assert (AOP_SIZE(left) == AOP_SIZE(right));
4367
4368   size = AOP_SIZE(right) - 1;
4369   mask = (0x100UL << (size*8)) - 1;
4370   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4371   performedLt = 1;
4372   templbl = NULL;
4373   lit = 0;
4374
4375   resolveIfx (&rIfx, ifx);
4376
4377   /* handle for special cases */
4378   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4379       return;
4380
4381   /**********************************************************************
4382    * handle bits - bit compares are promoted to int compares seemingly! *
4383    **********************************************************************/
4384 #if 0
4385   // THIS IS COMPLETELY UNTESTED!
4386   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4387     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4388     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4389     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4390
4391     emitSETC;
4392     // 1 < {0,1} is false --> clear C by skipping the next instruction
4393     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4394     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4395     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4396     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4397     emitCLRC; // only skipped for left=0 && right=1
4398
4399     goto correct_result_in_carry;
4400   } // if
4401 #endif
4402
4403   /*************************************************
4404    * make sure that left is register (or the like) *
4405    *************************************************/
4406   if (!isAOP_REGlike(left)) {
4407     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4408     assert (isAOP_LIT(left));
4409     assert (isAOP_REGlike(right));
4410     // swap left and right
4411     // left < right <==> right > left <==> (right >= left + 1)
4412     lit = ulFromVal (AOP(left)->aopu.aop_lit);
4413
4414     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4415       // MAXVALUE < right? always false
4416       if (performedLt) emitCLRC; else emitSETC;
4417       goto correct_result_in_carry;
4418     } // if
4419
4420     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4421     // that's why we handled it above.
4422     lit++;
4423
4424     dummy = left;
4425     left = right;
4426     right = dummy;
4427
4428     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4429   } else if (isAOP_LIT(right)) {
4430     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4431   } // if
4432
4433   assert (isAOP_REGlike(left)); // left must be register or the like
4434   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4435
4436   /*************************************************
4437    * special cases go here                         *
4438    *************************************************/
4439
4440   if (isAOP_LIT(right)) {
4441     if (!sign) {
4442       // unsigned comparison to a literal
4443       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4444       if (lit == 0) {
4445         // unsigned left < 0? always false
4446         if (performedLt) emitCLRC; else emitSETC;
4447         goto correct_result_in_carry;
4448       }
4449     } else {
4450       // signed comparison to a literal
4451       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4452       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4453         // signed left < 0x80000000? always false
4454         if (performedLt) emitCLRC; else emitSETC;
4455         goto correct_result_in_carry;
4456       } else if (lit == 0) {
4457         // compare left < 0; set CARRY if SIGNBIT(left) is set
4458         if (performedLt) emitSETC; else emitCLRC;
4459         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4460         if (performedLt) emitCLRC; else emitSETC;
4461         goto correct_result_in_carry;
4462       }
4463     } // if (!sign)
4464   } // right is literal
4465
4466   /*************************************************
4467    * perform a general case comparison             *
4468    * make sure we get CARRY==1 <==> left >= right  *
4469    *************************************************/
4470   // compare most significant bytes
4471   //DEBUGpc ("comparing bytes at offset %d", size);
4472   if (!sign) {
4473     // unsigned comparison
4474     mov2w_regOrLit (AOP(right), lit, size);
4475     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4476   } else {
4477     // signed comparison
4478     // (add 2^n to both operands then perform an unsigned comparison)
4479     if (isAOP_LIT(right)) {
4480       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4481       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4482
4483       if (litbyte == 0x80) {
4484         // left >= 0x80 -- always true, but more bytes to come
4485         pic16_mov2w (AOP(left), size);
4486         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4487         emitSETC;
4488       } else {
4489         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4490         pic16_mov2w (AOP(left), size);
4491         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4492         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4493       } // if
4494     } else {
4495       /* using PRODL as a temporary register here */
4496       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4497       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4498       pic16_mov2w (AOP(left), size);
4499       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4500       pic16_emitpcode (POC_MOVWF, pctemp);
4501       pic16_mov2w (AOP(right), size);
4502       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4503       pic16_emitpcode (POC_SUBFW, pctemp);
4504       //pic16_popReleaseTempReg(pctemp, 1);
4505     }
4506   } // if (!sign)
4507
4508   // compare remaining bytes (treat as unsigned case from above)
4509   templbl = newiTempLabel ( NULL );
4510   offs = size;
4511   while (offs--) {
4512     //DEBUGpc ("comparing bytes at offset %d", offs);
4513     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4514     mov2w_regOrLit (AOP(right), lit, offs);
4515     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4516   } // while (offs)
4517   pic16_emitpLabel (templbl->key);
4518   goto result_in_carry;
4519
4520 result_in_carry:
4521
4522   /****************************************************
4523    * now CARRY contains the result of the comparison: *
4524    * SUBWF sets CARRY iff                             *
4525    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4526    * (F=left, W=right)                                *
4527    ****************************************************/
4528
4529   if (performedLt) {
4530     if (result && AOP_TYPE(result) != AOP_CRY) {
4531       // value will be stored
4532       emitTOGC;
4533     } else {
4534       // value wil only be used in the following genSkipc()
4535       rIfx.condition ^= 1;
4536     }
4537   } // if
4538
4539 correct_result_in_carry:
4540
4541   // assign result to variable (if neccessary)
4542   if (result && AOP_TYPE(result) != AOP_CRY) {
4543     //DEBUGpc ("assign result");
4544     size = AOP_SIZE(result);
4545     while (size--) {
4546       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4547     } // while
4548     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4549   } // if (result)
4550
4551   // perform conditional jump
4552   if (ifx) {
4553     //DEBUGpc ("generate control flow");
4554     genSkipc (&rIfx);
4555     ifx->generated = 1;
4556   } // if
4557 }
4558
4559 /*-----------------------------------------------------------------*/
4560 /* genCmpGt :- greater than comparison                             */
4561 /*-----------------------------------------------------------------*/
4562 static void genCmpGt (iCode *ic, iCode *ifx)
4563 {
4564   operand *left, *right, *result;
4565   sym_link *letype , *retype;
4566   int sign ;
4567
4568     FENTRY;
4569
4570     left = IC_LEFT(ic);
4571     right= IC_RIGHT(ic);
4572     result = IC_RESULT(ic);
4573
4574     letype = getSpec(operandType(left));
4575     retype =getSpec(operandType(right));
4576     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4577     /* assign the amsops */
4578     pic16_aopOp (left,ic,FALSE);
4579     pic16_aopOp (right,ic,FALSE);
4580     pic16_aopOp (result,ic,TRUE);
4581
4582     genCmp(right, left, result, ifx, sign);
4583
4584     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4585     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4586     pic16_freeAsmop(result,NULL,ic,TRUE);
4587 }
4588
4589 /*-----------------------------------------------------------------*/
4590 /* genCmpLt - less than comparisons                                */
4591 /*-----------------------------------------------------------------*/
4592 static void genCmpLt (iCode *ic, iCode *ifx)
4593 {
4594   operand *left, *right, *result;
4595   sym_link *letype , *retype;
4596   int sign ;
4597
4598     FENTRY;
4599
4600     left = IC_LEFT(ic);
4601     right= IC_RIGHT(ic);
4602     result = IC_RESULT(ic);
4603
4604     letype = getSpec(operandType(left));
4605     retype =getSpec(operandType(right));
4606     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4607
4608     /* assign the amsops */
4609     pic16_aopOp (left,ic,FALSE);
4610     pic16_aopOp (right,ic,FALSE);
4611     pic16_aopOp (result,ic,TRUE);
4612
4613     genCmp(left, right, result, ifx, sign);
4614
4615     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4616     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4617     pic16_freeAsmop(result,NULL,ic,TRUE);
4618 }
4619
4620 /*-----------------------------------------------------------------*/
4621 /* pic16_isLitOp - check if operand has to be treated as literal   */
4622 /*-----------------------------------------------------------------*/
4623 bool pic16_isLitOp(operand *op)
4624 {
4625   return ((AOP_TYPE(op) == AOP_LIT)
4626       || ( (AOP_TYPE(op) == AOP_PCODE)
4627           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4628               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4629 }
4630
4631 /*-----------------------------------------------------------------*/
4632 /* pic16_isLitAop - check if operand has to be treated as literal  */
4633 /*-----------------------------------------------------------------*/
4634 bool pic16_isLitAop(asmop *aop)
4635 {
4636   return ((aop->type == AOP_LIT)
4637       || ( (aop->type == AOP_PCODE)
4638           && ( (aop->aopu.pcop->type == PO_LITERAL)
4639               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4640 }
4641
4642
4643
4644 /*-----------------------------------------------------------------*/
4645 /* genCmpEq - generates code for equal to                          */
4646 /*-----------------------------------------------------------------*/
4647 static void genCmpEq (iCode *ic, iCode *ifx)
4648 {
4649   operand *left, *right, *result;
4650   symbol *falselbl = newiTempLabel(NULL);
4651   symbol *donelbl = newiTempLabel(NULL);
4652
4653   int preserve_result = 0;
4654   int generate_result = 0;
4655   int i=0;
4656   unsigned long lit = -1;
4657
4658   FENTRY;
4659
4660   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4661   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4662   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4663
4664   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4665
4666   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4667     {
4668       werror(W_POSSBUG2, __FILE__, __LINE__);
4669       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4670       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4671       goto release;
4672     }
4673
4674   if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4675     {
4676       operand *tmp = right ;
4677       right = left;
4678       left = tmp;
4679     }
4680
4681   if (AOP_TYPE(right) == AOP_LIT) {
4682     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4683   }
4684
4685   if ( regsInCommon(left, result) || regsInCommon(right, result) )
4686     preserve_result = 1;
4687
4688   if(result && AOP_SIZE(result))
4689     generate_result = 1;
4690
4691   if(generate_result && !preserve_result)
4692     {
4693       for(i = 0; i < AOP_SIZE(result); i++)
4694         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4695     }
4696
4697   assert( AOP_SIZE(left) == AOP_SIZE(right) );
4698   for(i=0; i < AOP_SIZE(left); i++)
4699     {
4700       if(AOP_TYPE(left) != AOP_ACC)
4701         {
4702           if(pic16_isLitOp(left))
4703             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4704           else
4705             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4706         }
4707       if(pic16_isLitOp(right)) {
4708         if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4709           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4710         }
4711       } else
4712         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4713
4714       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4715     }
4716
4717   // result == true
4718
4719   if(generate_result && preserve_result)
4720     {
4721       for(i = 0; i < AOP_SIZE(result); i++)
4722         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4723     }
4724
4725   if(generate_result)
4726     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4727
4728   if(generate_result && preserve_result)
4729     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4730
4731   if(ifx && IC_TRUE(ifx))
4732     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4733
4734   if(ifx && IC_FALSE(ifx))
4735     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4736
4737   pic16_emitpLabel(falselbl->key);
4738
4739   // result == false
4740
4741   if(ifx && IC_FALSE(ifx))
4742     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4743
4744   if(generate_result && preserve_result)
4745     {
4746       for(i = 0; i < AOP_SIZE(result); i++)
4747         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4748     }
4749
4750   pic16_emitpLabel(donelbl->key);
4751
4752   if(ifx)
4753     ifx->generated = 1;
4754
4755 release:
4756   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4757   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4758   pic16_freeAsmop(result,NULL,ic,TRUE);
4759
4760 }
4761
4762
4763 #if 0
4764 // old version kept for reference
4765
4766 /*-----------------------------------------------------------------*/
4767 /* genCmpEq - generates code for equal to                          */
4768 /*-----------------------------------------------------------------*/
4769 static void genCmpEq (iCode *ic, iCode *ifx)
4770 {
4771     operand *left, *right, *result;
4772     unsigned long lit = 0L;
4773     int size,offset=0;
4774     symbol *falselbl  = newiTempLabel(NULL);
4775
4776
4777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4778
4779     if(ifx)
4780       DEBUGpic16_emitcode ("; ifx is non-null","");
4781     else
4782       DEBUGpic16_emitcode ("; ifx is null","");
4783
4784     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4785     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4786     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4787
4788     size = max(AOP_SIZE(left),AOP_SIZE(right));
4789
4790     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4791
4792     /* if literal, literal on the right or
4793     if the right is in a pointer register and left
4794     is not */
4795     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4796       operand *tmp = right ;
4797       right = left;
4798       left = tmp;
4799     }
4800
4801
4802     if(ifx && !AOP_SIZE(result)){
4803         symbol *tlbl;
4804         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
4805         /* if they are both bit variables */
4806         if (AOP_TYPE(left) == AOP_CRY &&
4807             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4808                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
4809             if(AOP_TYPE(right) == AOP_LIT){
4810                 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4811                 if(lit == 0L){
4812                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4813                     pic16_emitcode("cpl","c");
4814                 } else if(lit == 1L) {
4815                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4816                 } else {
4817                     pic16_emitcode("clr","c");
4818                 }
4819                 /* AOP_TYPE(right) == AOP_CRY */
4820             } else {
4821                 symbol *lbl = newiTempLabel(NULL);
4822                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4823                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4824                 pic16_emitcode("cpl","c");
4825                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4826             }
4827             /* if true label then we jump if condition
4828             supplied is true */
4829             tlbl = newiTempLabel(NULL);
4830             if ( IC_TRUE(ifx) ) {
4831                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4832                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4833             } else {
4834                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4835                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4836             }
4837             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4838
4839                 {
4840                 /* left and right are both bit variables, result is carry */
4841                         resolvedIfx rIfx;
4842
4843                         resolveIfx(&rIfx,ifx);
4844
4845                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4846                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4847                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4848                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4849                         genSkipz2(&rIfx,0);
4850                 }
4851         } else {
4852
4853                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
4854
4855                         /* They're not both bit variables. Is the right a literal? */
4856                         if(AOP_TYPE(right) == AOP_LIT) {
4857                         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4858
4859                         switch(size) {
4860
4861                                 case 1:
4862                                         switch(lit & 0xff) {
4863                                                 case 1:
4864                                                                 if ( IC_TRUE(ifx) ) {
4865                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4866                                                                         emitSKPNZ;
4867                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4868                                                                 } else {
4869                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4870                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4871                                                                 }
4872                                                                 break;
4873                                                 case 0xff:
4874                                                                 if ( IC_TRUE(ifx) ) {
4875                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4876                                                                         emitSKPNZ;
4877                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4878                                                                 } else {
4879                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4880                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4881                                                                 }
4882                                                                 break;
4883                                                 default:
4884                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4885                                                                 if(lit)
4886                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4887                                                                 genSkip(ifx,'z');
4888                                         } // switch lit
4889
4890
4891                                         /* end of size == 1 */
4892                                         break;
4893
4894                                 case 2:
4895                                         genc16bit2lit(left,lit,offset);
4896                                         genSkip(ifx,'z');
4897                                         break;
4898                                         /* end of size == 2 */
4899
4900                                 default:
4901                                         /* size is 4 */
4902                                         if(lit==0) {
4903                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4904                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4905                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4906                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4907                                                 genSkip(ifx,'z');
4908                                         } else {
4909                                                 /* search for patterns that can be optimized */
4910
4911                                                 genc16bit2lit(left,lit,0);
4912                                                 lit >>= 16;
4913                                                 if(lit) {
4914                                                                 if(IC_TRUE(ifx))
4915                                                                 emitSKPZ; // if hi word unequal
4916                                                                 else
4917                                                                 emitSKPNZ; // if hi word equal
4918                                                                 // fail early
4919                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4920                                                         genc16bit2lit(left,lit,2);
4921                                                         genSkip(ifx,'z');
4922                                                 } else {
4923                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4924                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4925                                                         genSkip(ifx,'z');
4926                                                 }
4927                                         }
4928                                                 pic16_emitpLabel(falselbl->key);
4929                                                 break;
4930
4931                         } // switch size
4932
4933                         ifx->generated = 1;
4934                         goto release ;
4935
4936
4937           } else if(AOP_TYPE(right) == AOP_CRY ) {
4938             /* we know the left is not a bit, but that the right is */
4939             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4940             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4941                       pic16_popGet(AOP(right),offset));
4942             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4943
4944             /* if the two are equal, then W will be 0 and the Z bit is set
4945              * we could test Z now, or go ahead and check the high order bytes if
4946              * the variable we're comparing is larger than a byte. */
4947
4948             while(--size)
4949               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4950
4951             if ( IC_TRUE(ifx) ) {
4952               emitSKPNZ;
4953               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4954               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4955             } else {
4956               emitSKPZ;
4957               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4958               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4959             }
4960
4961           } else {
4962             /* They're both variables that are larger than bits */
4963             int s = size;
4964
4965             tlbl = newiTempLabel(NULL);
4966
4967             while(size--) {
4968               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4969               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4970
4971               if ( IC_TRUE(ifx) ) {
4972                 if(size) {
4973                   emitSKPZ;
4974
4975                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4976
4977                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4978                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4979                 } else {
4980                   emitSKPNZ;
4981
4982                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
4983
4984
4985                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4986                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4987                 }
4988               } else {
4989                 emitSKPZ;
4990
4991                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
4992
4993                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4994                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4995               }
4996               offset++;
4997             }
4998             if(s>1 && IC_TRUE(ifx)) {
4999               pic16_emitpLabel(tlbl->key);
5000               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5001             }
5002           }
5003         }
5004         /* mark the icode as generated */
5005         ifx->generated = 1;
5006         goto release ;
5007     }
5008
5009     /* if they are both bit variables */
5010     if (AOP_TYPE(left) == AOP_CRY &&
5011         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5012         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5013         if(AOP_TYPE(right) == AOP_LIT){
5014             unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5015             if(lit == 0L){
5016                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5017                 pic16_emitcode("cpl","c");
5018             } else if(lit == 1L) {
5019                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5020             } else {
5021                 pic16_emitcode("clr","c");
5022             }
5023             /* AOP_TYPE(right) == AOP_CRY */
5024         } else {
5025             symbol *lbl = newiTempLabel(NULL);
5026             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5027             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5028             pic16_emitcode("cpl","c");
5029             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5030         }
5031         /* c = 1 if egal */
5032         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5033             pic16_outBitC(result);
5034             goto release ;
5035         }
5036         if (ifx) {
5037             genIfxJump (ifx,"c");
5038             goto release ;
5039         }
5040         /* if the result is used in an arithmetic operation
5041         then put the result in place */
5042         pic16_outBitC(result);
5043     } else {
5044
5045       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5046       gencjne(left,right,result,ifx);
5047 /*
5048       if(ifx)
5049         gencjne(left,right,newiTempLabel(NULL));
5050       else {
5051         if(IC_TRUE(ifx)->key)
5052           gencjne(left,right,IC_TRUE(ifx)->key);
5053         else
5054           gencjne(left,right,IC_FALSE(ifx)->key);
5055         ifx->generated = 1;
5056         goto release ;
5057       }
5058       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5059         pic16_aopPut(AOP(result),"a",0);
5060         goto release ;
5061       }
5062
5063       if (ifx) {
5064         genIfxJump (ifx,"a");
5065         goto release ;
5066       }
5067 */
5068       /* if the result is used in an arithmetic operation
5069          then put the result in place */
5070 /*
5071       if (AOP_TYPE(result) != AOP_CRY)
5072         pic16_outAcc(result);
5073 */
5074       /* leave the result in acc */
5075     }
5076
5077 release:
5078     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5079     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5080     pic16_freeAsmop(result,NULL,ic,TRUE);
5081 }
5082 #endif
5083
5084 /*-----------------------------------------------------------------*/
5085 /* ifxForOp - returns the icode containing the ifx for operand     */
5086 /*-----------------------------------------------------------------*/
5087 static iCode *ifxForOp ( operand *op, iCode *ic )
5088 {
5089   FENTRY2;
5090
5091     /* if true symbol then needs to be assigned */
5092     if (IS_TRUE_SYMOP(op))
5093         return NULL ;
5094
5095     /* if this has register type condition and
5096     the next instruction is ifx with the same operand
5097     and live to of the operand is upto the ifx only then */
5098     if (ic->next
5099         && ic->next->op == IFX
5100         && IC_COND(ic->next)->key == op->key
5101         && OP_SYMBOL(op)->liveTo <= ic->next->seq
5102         ) {
5103                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5104           return ic->next;
5105     }
5106
5107     /*
5108     if (ic->next &&
5109         ic->next->op == IFX &&
5110         IC_COND(ic->next)->key == op->key) {
5111       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5112       return ic->next;
5113     }
5114     */
5115
5116     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5117     if (ic->next &&
5118         ic->next->op == IFX)
5119       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5120
5121     if (ic->next &&
5122         ic->next->op == IFX &&
5123         IC_COND(ic->next)->key == op->key) {
5124       DEBUGpic16_emitcode ("; "," key is okay");
5125       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5126                            OP_SYMBOL(op)->liveTo,
5127                            ic->next->seq);
5128     }
5129
5130 #if 0
5131     /* the code below is completely untested
5132      * it just allows ulong2fs.c compile -- VR */
5133
5134     ic = ic->next;
5135     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5136                                         __FILE__, __FUNCTION__, __LINE__);
5137
5138     /* if this has register type condition and
5139     the next instruction is ifx with the same operand
5140     and live to of the operand is upto the ifx only then */
5141     if (ic->next &&
5142         ic->next->op == IFX &&
5143         IC_COND(ic->next)->key == op->key &&
5144         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5145         return ic->next;
5146
5147     if (ic->next &&
5148         ic->next->op == IFX &&
5149         IC_COND(ic->next)->key == op->key) {
5150       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5151       return ic->next;
5152     }
5153
5154     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5155                                         __FILE__, __FUNCTION__, __LINE__);
5156
5157 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5158 #endif
5159
5160     return NULL;
5161 }
5162 /*-----------------------------------------------------------------*/
5163 /* genAndOp - for && operation                                     */
5164 /*-----------------------------------------------------------------*/
5165 static void genAndOp (iCode *ic)
5166 {
5167   operand *left,*right, *result;
5168 /*     symbol *tlbl; */
5169
5170     FENTRY;
5171
5172     /* note here that && operations that are in an
5173     if statement are taken away by backPatchLabels
5174     only those used in arthmetic operations remain */
5175     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5176     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5177     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5178
5179     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5180
5181     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5182     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5183     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5184
5185     /* if both are bit variables */
5186 /*     if (AOP_TYPE(left) == AOP_CRY && */
5187 /*         AOP_TYPE(right) == AOP_CRY ) { */
5188 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5189 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5190 /*         pic16_outBitC(result); */
5191 /*     } else { */
5192 /*         tlbl = newiTempLabel(NULL); */
5193 /*         pic16_toBoolean(left);     */
5194 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5195 /*         pic16_toBoolean(right); */
5196 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5197 /*         pic16_outBitAcc(result); */
5198 /*     } */
5199
5200     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5201     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5202     pic16_freeAsmop(result,NULL,ic,TRUE);
5203 }
5204
5205
5206 /*-----------------------------------------------------------------*/
5207 /* genOrOp - for || operation                                      */
5208 /*-----------------------------------------------------------------*/
5209 /*
5210   tsd pic port -
5211   modified this code, but it doesn't appear to ever get called
5212 */
5213
5214 static void genOrOp (iCode *ic)
5215 {
5216   operand *left,*right, *result;
5217   symbol *tlbl;
5218
5219     FENTRY;
5220
5221   /* note here that || operations that are in an
5222     if statement are taken away by backPatchLabels
5223     only those used in arthmetic operations remain */
5224     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5225     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5226     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5227
5228     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5229
5230     /* if both are bit variables */
5231     if (AOP_TYPE(left) == AOP_CRY &&
5232         AOP_TYPE(right) == AOP_CRY ) {
5233       pic16_emitcode("clrc","");
5234       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5235                AOP(left)->aopu.aop_dir,
5236                AOP(left)->aopu.aop_dir);
5237       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5238                AOP(right)->aopu.aop_dir,
5239                AOP(right)->aopu.aop_dir);
5240       pic16_emitcode("setc","");
5241
5242     } else {
5243         tlbl = newiTempLabel(NULL);
5244         pic16_toBoolean(left);
5245         emitSKPZ;
5246         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5247         pic16_toBoolean(right);
5248         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5249
5250         pic16_outBitAcc(result);
5251     }
5252
5253     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5254     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5255     pic16_freeAsmop(result,NULL,ic,TRUE);
5256 }
5257
5258 /*-----------------------------------------------------------------*/
5259 /* isLiteralBit - test if lit == 2^n                               */
5260 /*-----------------------------------------------------------------*/
5261 static int isLiteralBit(unsigned long lit)
5262 {
5263     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5264     0x100L,0x200L,0x400L,0x800L,
5265     0x1000L,0x2000L,0x4000L,0x8000L,
5266     0x10000L,0x20000L,0x40000L,0x80000L,
5267     0x100000L,0x200000L,0x400000L,0x800000L,
5268     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5269     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5270     int idx;
5271
5272     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5273     for(idx = 0; idx < 32; idx++)
5274         if(lit == pw[idx])
5275             return idx+1;
5276     return 0;
5277 }
5278
5279 /*-----------------------------------------------------------------*/
5280 /* continueIfTrue -                                                */
5281 /*-----------------------------------------------------------------*/
5282 static void continueIfTrue (iCode *ic)
5283 {
5284   FENTRY;
5285   if(IC_TRUE(ic))
5286     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5287   ic->generated = 1;
5288 }
5289
5290 /*-----------------------------------------------------------------*/
5291 /* jmpIfTrue -                                                     */
5292 /*-----------------------------------------------------------------*/
5293 static void jumpIfTrue (iCode *ic)
5294 {
5295   FENTRY;
5296   if(!IC_TRUE(ic))
5297     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5298   ic->generated = 1;
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* jmpTrueOrFalse -                                                */
5303 /*-----------------------------------------------------------------*/
5304 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5305 {
5306   // ugly but optimized by peephole
5307   FENTRY;
5308   if(IC_TRUE(ic)){
5309     symbol *nlbl = newiTempLabel(NULL);
5310       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5311       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5312       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5313       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5314   } else {
5315     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5316     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5317   }
5318   ic->generated = 1;
5319 }
5320
5321 /*-----------------------------------------------------------------*/
5322 /* genAnd  - code for and                                          */
5323 /*-----------------------------------------------------------------*/
5324 static void genAnd (iCode *ic, iCode *ifx)
5325 {
5326   operand *left, *right, *result;
5327   int size, offset = 0;
5328   unsigned long lit = 0L;
5329   resolvedIfx rIfx;
5330
5331   FENTRY;
5332
5333   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5334   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5335   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5336
5337   resolveIfx (&rIfx, ifx);
5338
5339   /* if left is a literal & right is not then exchange them */
5340   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5341       AOP_NEEDSACC (left))
5342     {
5343       operand *tmp = right;
5344       right = left;
5345       left = tmp;
5346     }
5347
5348   /* if result = right then exchange them */
5349   if (pic16_sameRegs (AOP (result), AOP (right)))
5350     {
5351       operand *tmp = right;
5352       right = left;
5353       left = tmp;
5354     }
5355
5356   /* if right is bit then exchange them */
5357   if (AOP_TYPE (right) == AOP_CRY &&
5358       AOP_TYPE (left) != AOP_CRY)
5359     {
5360       operand *tmp = right;
5361       right = left;
5362       left = tmp;
5363     }
5364
5365   if (AOP_TYPE (right) == AOP_LIT)
5366     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5367
5368   size = AOP_SIZE (result);
5369
5370   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5371
5372   // if(bit & yy)
5373   // result = bit & yy;
5374   if (AOP_TYPE(left) == AOP_CRY){
5375     // c = bit & literal;
5376     if(AOP_TYPE(right) == AOP_LIT){
5377       if(lit & 1) {
5378         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5379           // no change
5380           goto release;
5381         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5382       } else {
5383         // bit(result) = 0;
5384         if(size && (AOP_TYPE(result) == AOP_CRY)){
5385           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5386           goto release;
5387         }
5388         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5389           jumpIfTrue(ifx);
5390           goto release;
5391         }
5392         pic16_emitcode("clr","c");
5393       }
5394     } else {
5395       if (AOP_TYPE(right) == AOP_CRY){
5396         // c = bit & bit;
5397         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5398         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5399       } else {
5400         // c = bit & val;
5401         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5402         // c = lsb
5403         pic16_emitcode("rrc","a");
5404         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5405       }
5406     }
5407     // bit = c
5408     // val = c
5409     if(size)
5410       pic16_outBitC(result);
5411     // if(bit & ...)
5412     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5413       genIfxJump(ifx, "c");
5414     goto release ;
5415   }
5416
5417   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
5418   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5419   if ((AOP_TYPE (right) == AOP_LIT) &&
5420      (AOP_TYPE (result) == AOP_CRY) &&
5421      (AOP_TYPE (left) != AOP_CRY))
5422     {
5423       symbol *tlbl = newiTempLabel (NULL);
5424       int sizel = AOP_SIZE (left);
5425       int nonnull = 0;
5426       char emitBra;
5427
5428       if (size)
5429         emitSETC;
5430
5431       /* get number of non null bytes in literal */
5432       while (sizel--)
5433         {
5434           if (lit & (0xff << (sizel * 8)))
5435             ++nonnull;
5436         }
5437
5438       emitBra = nonnull || rIfx.condition;
5439
5440       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5441         {
5442           unsigned char bytelit = lit;
5443
5444           if (bytelit != 0)
5445             {
5446               int posbit;
5447
5448               --nonnull;
5449
5450               /* patch provided by Aaron Colwell */
5451               if ((posbit = isLiteralBit (bytelit)) != 0)
5452                 {
5453                   if (nonnull)
5454                     {
5455                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5456                       pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5457                     }
5458                   else
5459                     {
5460                       pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5461                     }
5462                 }
5463               else
5464                 {
5465                   if (bytelit == 0xff)
5466                     {
5467                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
5468                        * a peephole could optimize it out -- VR */
5469                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5470                     }
5471                   else
5472                     {
5473                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5474                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5475                     }
5476                   if (nonnull)
5477                     {
5478                       if (rIfx.condition)
5479                         {
5480                           emitSKPZ;
5481                           pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5482                         }
5483                       else
5484                         {
5485                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5486                         }
5487                     }
5488                   else
5489                     {
5490                       /* last non null byte */
5491                       if (rIfx.condition)
5492                         emitSKPZ;
5493                       else
5494                         emitSKPNZ;
5495                     }
5496                 }
5497             }
5498         }
5499
5500       // bit = left & literal
5501       if (size)
5502         {
5503           emitCLRC;
5504           pic16_emitpLabel (tlbl->key);
5505         }
5506
5507       // if(left & literal)
5508       else
5509         {
5510           if (ifx)
5511             {
5512               if (emitBra)
5513                 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
5514               ifx->generated = 1;
5515             }
5516           pic16_emitpLabel (tlbl->key);
5517           goto release;
5518         }
5519       pic16_outBitC (result);
5520       goto release;
5521     }
5522
5523   /* if left is same as result */
5524   if(pic16_sameRegs(AOP(result),AOP(left))){
5525     int know_W = -1;
5526     for(;size--; offset++,lit>>=8) {
5527       if(AOP_TYPE(right) == AOP_LIT){
5528         switch(lit & 0xff) {
5529         case 0x00:
5530           /*  and'ing with 0 has clears the result */
5531 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5532           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5533           break;
5534         case 0xff:
5535           /* and'ing with 0xff is a nop when the result and left are the same */
5536           break;
5537
5538         default:
5539           {
5540             int p = pic16_my_powof2( (~lit) & 0xff );
5541             if(p>=0) {
5542               /* only one bit is set in the literal, so use a bcf instruction */
5543 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5544               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5545
5546             } else {
5547               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5548               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5549               if(know_W != (lit&0xff))
5550                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5551               know_W = lit &0xff;
5552               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5553             }
5554           }
5555         }
5556       } else {
5557         if (AOP_TYPE(left) == AOP_ACC) {
5558           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5559         } else {
5560           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5561           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5562
5563         }
5564       }
5565     }
5566
5567   } else {
5568     // left & result in different registers
5569     if(AOP_TYPE(result) == AOP_CRY){
5570       // result = bit
5571       // if(size), result in bit
5572       // if(!size && ifx), conditional oper: if(left & right)
5573       symbol *tlbl = newiTempLabel(NULL);
5574       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5575       if(size)
5576         pic16_emitcode("setb","c");
5577       while(sizer--){
5578         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5579         pic16_emitcode("anl","a,%s",
5580                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5581         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5582         offset++;
5583       }
5584       if(size){
5585         CLRC;
5586         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5587         pic16_outBitC(result);
5588       } else if(ifx)
5589         jmpTrueOrFalse(ifx, tlbl);
5590     } else {
5591       for(;(size--);offset++) {
5592         // normal case
5593         // result = left & right
5594         if(AOP_TYPE(right) == AOP_LIT){
5595           int t = (lit >> (offset*8)) & 0x0FFL;
5596           switch(t) {
5597           case 0x00:
5598             pic16_emitcode("clrf","%s",
5599                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5600             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5601             break;
5602           case 0xff:
5603             pic16_emitcode("movf","%s,w",
5604                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5605             pic16_emitcode("movwf","%s",
5606                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5607             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5608             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5609             break;
5610           default:
5611             pic16_emitcode("movlw","0x%x",t);
5612             pic16_emitcode("andwf","%s,w",
5613                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5614             pic16_emitcode("movwf","%s",
5615                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5616
5617             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5618             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5619             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5620           }
5621           continue;
5622         }
5623
5624         if (AOP_TYPE(left) == AOP_ACC) {
5625           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5626           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5627         } else {
5628           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5629           pic16_emitcode("andwf","%s,w",
5630                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5631           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5632           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5633         }
5634         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5635         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5636       }
5637     }
5638   }
5639
5640 release :
5641   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5642   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5643   pic16_freeAsmop(result,NULL,ic,TRUE);
5644 }
5645
5646 /*-----------------------------------------------------------------*/
5647 /* genOr  - code for or                                            */
5648 /*-----------------------------------------------------------------*/
5649 static void genOr (iCode *ic, iCode *ifx)
5650 {
5651   operand *left, *right, *result;
5652   int size, offset = 0;
5653   unsigned long lit = 0L;
5654   resolvedIfx rIfx;
5655
5656   FENTRY;
5657
5658   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5659   pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5660   pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5661
5662   resolveIfx (&rIfx, ifx);
5663
5664   /* if left is a literal & right is not then exchange them */
5665   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5666       AOP_NEEDSACC (left))
5667     {
5668       operand *tmp = right;
5669       right = left;
5670       left = tmp;
5671     }
5672
5673   /* if result = right then exchange them */
5674   if (pic16_sameRegs (AOP (result), AOP (right)))
5675     {
5676       operand *tmp = right;
5677       right = left;
5678       left = tmp;
5679     }
5680
5681   /* if right is bit then exchange them */
5682   if (AOP_TYPE (right) == AOP_CRY &&
5683       AOP_TYPE (left) != AOP_CRY)
5684     {
5685       operand *tmp = right;
5686       right = left;
5687       left = tmp;
5688     }
5689
5690   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5691
5692   if (AOP_TYPE (right) == AOP_LIT)
5693       lit = ulFromVal (AOP (right)->aopu.aop_lit);
5694
5695   size = AOP_SIZE (result);
5696
5697   // if(bit | yy)
5698   // xx = bit | yy;
5699   if (AOP_TYPE(left) == AOP_CRY){
5700       if(AOP_TYPE(right) == AOP_LIT){
5701           // c = bit & literal;
5702           if(lit){
5703               // lit != 0 => result = 1
5704               if(AOP_TYPE(result) == AOP_CRY){
5705                 if(size)
5706                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5707                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5708                 //     AOP(result)->aopu.aop_dir,
5709                 //     AOP(result)->aopu.aop_dir);
5710                   else if(ifx)
5711                       continueIfTrue(ifx);
5712                   goto release;
5713               }
5714           } else {
5715               // lit == 0 => result = left
5716               if(size && pic16_sameRegs(AOP(result),AOP(left)))
5717                   goto release;
5718               pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5719           }
5720       } else {
5721           if (AOP_TYPE(right) == AOP_CRY){
5722             if(pic16_sameRegs(AOP(result),AOP(left))){
5723               // c = bit | bit;
5724               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5725               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5726               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5727
5728               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5729                        AOP(result)->aopu.aop_dir,
5730                        AOP(result)->aopu.aop_dir);
5731               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5732                        AOP(right)->aopu.aop_dir,
5733                        AOP(right)->aopu.aop_dir);
5734               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5735                        AOP(result)->aopu.aop_dir,
5736                        AOP(result)->aopu.aop_dir);
5737             } else {
5738               if( AOP_TYPE(result) == AOP_ACC) {
5739                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5740                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5741                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5742                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5743
5744               } else {
5745
5746                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5747                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5748                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5749                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5750
5751                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5752                                AOP(result)->aopu.aop_dir,
5753                                AOP(result)->aopu.aop_dir);
5754                 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5755                                AOP(right)->aopu.aop_dir,
5756                                AOP(right)->aopu.aop_dir);
5757                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5758                                AOP(left)->aopu.aop_dir,
5759                                AOP(left)->aopu.aop_dir);
5760                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5761                                AOP(result)->aopu.aop_dir,
5762                                AOP(result)->aopu.aop_dir);
5763               }
5764             }
5765           } else {
5766               // c = bit | val;
5767               symbol *tlbl = newiTempLabel(NULL);
5768               pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5769
5770
5771               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5772               if( AOP_TYPE(right) == AOP_ACC) {
5773                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5774                 emitSKPNZ;
5775                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5776                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5777               }
5778
5779
5780
5781               if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5782                   pic16_emitcode(";XXX setb","c");
5783               pic16_emitcode(";XXX jb","%s,%05d_DS_",
5784                        AOP(left)->aopu.aop_dir,tlbl->key+100);
5785               pic16_toBoolean(right);
5786               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5787               if((AOP_TYPE(result) == AOP_CRY) && ifx){
5788                   jmpTrueOrFalse(ifx, tlbl);
5789                   goto release;
5790               } else {
5791                   CLRC;
5792                   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5793               }
5794           }
5795       }
5796       // bit = c
5797       // val = c
5798       if(size)
5799           pic16_outBitC(result);
5800       // if(bit | ...)
5801       else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5802           genIfxJump(ifx, "c");
5803       goto release ;
5804   }
5805
5806   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5807   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5808   if ((AOP_TYPE (right) == AOP_LIT) &&
5809      (AOP_TYPE (result) == AOP_CRY) &&
5810      (AOP_TYPE (left) != AOP_CRY))
5811     {
5812       if (lit)
5813         {
5814           if (rIfx.condition)
5815             pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5816           ifx->generated = 1;
5817         }
5818       else
5819         wassert (0);
5820
5821       goto release;
5822   }
5823
5824   /* if left is same as result */
5825   if(pic16_sameRegs(AOP(result),AOP(left))){
5826     int know_W = -1;
5827     for(;size--; offset++,lit>>=8) {
5828       if(AOP_TYPE(right) == AOP_LIT){
5829         if((lit & 0xff) == 0)
5830           /*  or'ing with 0 has no effect */
5831           continue;
5832         else {
5833           int p = pic16_my_powof2(lit & 0xff);
5834           if(p>=0) {
5835             /* only one bit is set in the literal, so use a bsf instruction */
5836             pic16_emitpcode(POC_BSF,
5837                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5838           } else {
5839             if(know_W != (lit & 0xff))
5840               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5841             know_W = lit & 0xff;
5842             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5843           }
5844
5845         }
5846       } else {
5847         if (AOP_TYPE(left) == AOP_ACC) {
5848           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5849 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5850         } else {
5851           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5852           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5853
5854 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5855 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5856
5857         }
5858       }
5859     }
5860   } else {
5861       // left & result in different registers
5862       if(AOP_TYPE(result) == AOP_CRY){
5863           // result = bit
5864           // if(size), result in bit
5865           // if(!size && ifx), conditional oper: if(left | right)
5866           symbol *tlbl = newiTempLabel(NULL);
5867           int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5868           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5869
5870
5871           if(size)
5872               pic16_emitcode(";XXX setb","c");
5873           while(sizer--){
5874               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5875               pic16_emitcode(";XXX orl","a,%s",
5876                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5877               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5878               offset++;
5879           }
5880           if(size){
5881               CLRC;
5882               pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5883               pic16_outBitC(result);
5884           } else if(ifx)
5885               jmpTrueOrFalse(ifx, tlbl);
5886       } else for(;(size--);offset++){
5887         // normal case
5888         // result = left & right
5889         if(AOP_TYPE(right) == AOP_LIT){
5890           int t = (lit >> (offset*8)) & 0x0FFL;
5891           switch(t) {
5892           case 0x00:
5893             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5894             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5895
5896 //            pic16_emitcode("movf","%s,w",
5897 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5898 //            pic16_emitcode("movwf","%s",
5899 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5900             break;
5901           default:
5902             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5903             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5904             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5905
5906 //            pic16_emitcode("movlw","0x%x",t);
5907 //            pic16_emitcode("iorwf","%s,w",
5908 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5909 //            pic16_emitcode("movwf","%s",
5910 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5911
5912           }
5913           continue;
5914         }
5915
5916         // faster than result <- left, anl result,right
5917         // and better if result is SFR
5918         if (AOP_TYPE(left) == AOP_ACC) {
5919           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5920 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5921         } else {
5922           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5923           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5924
5925 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5926 //          pic16_emitcode("iorwf","%s,w",
5927 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5928         }
5929         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5930 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5931       }
5932   }
5933
5934 release :
5935   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5936   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5937   pic16_freeAsmop(result,NULL,ic,TRUE);
5938 }
5939
5940 /*-----------------------------------------------------------------*/
5941 /* genXor - code for xclusive or                                   */
5942 /*-----------------------------------------------------------------*/
5943 static void genXor (iCode *ic, iCode *ifx)
5944 {
5945   operand *left, *right, *result;
5946   int size, offset = 0;
5947   unsigned long lit = 0L;
5948   resolvedIfx rIfx;
5949
5950   FENTRY;
5951
5952   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5953   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5954   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5955
5956   resolveIfx (&rIfx,ifx);
5957
5958   /* if left is a literal & right is not ||
5959      if left needs acc & right does not */
5960   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5961       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5962     {
5963       operand *tmp = right;
5964       right = left;
5965       left = tmp;
5966     }
5967
5968   /* if result = right then exchange them */
5969   if (pic16_sameRegs (AOP (result), AOP (right)))
5970     {
5971       operand *tmp = right ;
5972       right = left;
5973       left = tmp;
5974     }
5975
5976   /* if right is bit then exchange them */
5977   if (AOP_TYPE (right) == AOP_CRY &&
5978       AOP_TYPE (left) != AOP_CRY)
5979     {
5980       operand *tmp = right ;
5981       right = left;
5982       left = tmp;
5983     }
5984
5985   if (AOP_TYPE (right) == AOP_LIT)
5986     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5987
5988   size = AOP_SIZE (result);
5989
5990   // if(bit ^ yy)
5991   // xx = bit ^ yy;
5992   if (AOP_TYPE(left) == AOP_CRY)
5993     {
5994       if (AOP_TYPE(right) == AOP_LIT)
5995         {
5996           // c = bit & literal;
5997           if (lit >> 1)
5998             {
5999               // lit>>1  != 0 => result = 1
6000               if (AOP_TYPE(result) == AOP_CRY)
6001                 {
6002                   if (size)
6003                     {
6004                       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
6005                       pic16_emitcode("setb", "%s", AOP(result)->aopu.aop_dir);
6006                     }
6007                   else if (ifx)
6008                     continueIfTrue(ifx);
6009                   goto release;
6010                 }
6011               pic16_emitcode("setb", "c");
6012             }
6013           else
6014             {
6015               // lit == (0 or 1)
6016               if (lit == 0)
6017                 {
6018                   // lit == 0, result = left
6019                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
6020                     goto release;
6021                   pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6022                 }
6023               else
6024                 {
6025                   // lit == 1, result = not(left)
6026                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
6027                     {
6028                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6029                       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6030                       pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6031                       goto release;
6032                     }
6033                   else
6034                     {
6035                       pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6036                       pic16_emitcode("cpl", "c");
6037                     }
6038                 }
6039             }
6040         }
6041       else
6042         {
6043           // right != literal
6044           symbol *tlbl = newiTempLabel(NULL);
6045           if (AOP_TYPE(right) == AOP_CRY)
6046             {
6047               // c = bit ^ bit;
6048               pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6049             }
6050           else
6051             {
6052               int sizer = AOP_SIZE(right);
6053               // c = bit ^ val
6054               // if val>>1 != 0, result = 1
6055               pic16_emitcode("setb", "c");
6056               while (sizer)
6057                 {
6058                   MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6059                   if (sizer == 1)
6060                     // test the msb of the lsb
6061                     pic16_emitcode("anl", "a,#0xfe");
6062                   pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6063                   sizer--;
6064                 }
6065               // val = (0,1)
6066               pic16_emitcode("rrc", "a");
6067             }
6068           pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6069           pic16_emitcode("cpl", "c");
6070           pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6071         }
6072       // bit = c
6073       // val = c
6074       if (size)
6075         pic16_outBitC(result);
6076       // if(bit | ...)
6077       else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6078         genIfxJump(ifx, "c");
6079       goto release;
6080     }
6081
6082   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
6083   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
6084   if ((AOP_TYPE (right) == AOP_LIT) &&
6085      (AOP_TYPE (result) == AOP_CRY) &&
6086      (AOP_TYPE (left) != AOP_CRY))
6087     {
6088       symbol *tlbl = newiTempLabel (NULL);
6089       int sizel;
6090
6091       if (size)
6092         emitSETC;
6093
6094       for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6095         {
6096           unsigned char bytelit = lit;
6097
6098           switch (bytelit)
6099             {
6100             case 0xff:
6101               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6102               break;
6103
6104             case 0x00:
6105               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6106               break;
6107
6108             default:
6109               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6110               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6111               break;
6112             }
6113           if (sizel)
6114             {
6115               if (rIfx.condition)
6116                 {
6117                   emitSKPZ;
6118                   pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6119                 }
6120               else
6121                 {
6122                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6123                 }
6124             }
6125           else
6126             {
6127               /* last non null byte */
6128               if (rIfx.condition)
6129                 emitSKPZ;
6130               else
6131                 emitSKPNZ;
6132             }
6133         }
6134
6135       // bit = left ^ literal
6136       if (size)
6137         {
6138           emitCLRC;
6139           pic16_emitpLabel (tlbl->key);
6140         }
6141       // if (left ^ literal)
6142       else
6143         {
6144           if (ifx)
6145             {
6146               pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
6147               ifx->generated = 1;
6148             }
6149           pic16_emitpLabel (tlbl->key);
6150           goto release;
6151         }
6152
6153       pic16_outBitC (result);
6154       goto release;
6155   }
6156
6157   if (pic16_sameRegs(AOP(result), AOP(left)))
6158     {
6159       /* if left is same as result */
6160       for (; size--; offset++)
6161         {
6162           if (AOP_TYPE(right) == AOP_LIT)
6163             {
6164               int t  = (lit >> (offset * 8)) & 0x0FFL;
6165               if  (t == 0x00L)
6166                 continue;
6167               else
6168                 {
6169                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6170                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6171                 }
6172             }
6173           else
6174             {
6175               if (AOP_TYPE(left) == AOP_ACC)
6176                 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6177               else
6178                 {
6179                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6180                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6181                 }
6182             }
6183         }
6184     }
6185   else
6186     {
6187     // left ^ result in different registers
6188     if (AOP_TYPE(result) == AOP_CRY)
6189       {
6190         // result = bit
6191         // if(size), result in bit
6192         // if(!size && ifx), conditional oper: if(left ^ right)
6193         symbol *tlbl = newiTempLabel(NULL);
6194         int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6195         if (size)
6196           pic16_emitcode("setb", "c");
6197         while (sizer--)
6198           {
6199             if ((AOP_TYPE(right) == AOP_LIT) &&
6200               (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6201               {
6202                 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6203               }
6204             else
6205               {
6206                 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6207                 pic16_emitcode("xrl", "a,%s",
6208                                pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6209               }
6210             pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6211             offset++;
6212           }
6213         if (size)
6214           {
6215             CLRC;
6216             pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6217             pic16_outBitC(result);
6218           }
6219         else if (ifx)
6220           jmpTrueOrFalse(ifx, tlbl);
6221       }
6222     else
6223       {
6224         for (; (size--); offset++)
6225           {
6226             // normal case
6227             // result = left ^ right
6228             if (AOP_TYPE(right) == AOP_LIT)
6229               {
6230                 int t = (lit >> (offset * 8)) & 0x0FFL;
6231                 switch(t)
6232                   {
6233                   case 0x00:
6234                     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6235                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6236                     pic16_emitcode("movf", "%s,w",
6237                                    pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6238                     pic16_emitcode("movwf", "%s",
6239                                    pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6240                     break;
6241
6242                   case 0xff:
6243                     pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6244                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6245                     pic16_emitcode("comf", "%s,w",
6246                                    pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6247                     pic16_emitcode("movwf", "%s",
6248                                    pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6249                     break;
6250
6251                   default:
6252                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6253                     pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6254                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6255                     pic16_emitcode("movlw", "0x%x", t);
6256                     pic16_emitcode("xorwf", "%s,w",
6257                                    pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6258                     pic16_emitcode("movwf", "%s",
6259                                    pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6260
6261                   }
6262                 continue;
6263               }
6264
6265             // faster than result <- left, anl result,right
6266             // and better if result is SFR
6267             if (AOP_TYPE(left) == AOP_ACC)
6268               {
6269                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6270                 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6271               }
6272             else
6273               {
6274                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6275                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6276                 pic16_emitcode("movf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6277                 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6278               }
6279             if ( AOP_TYPE(result) != AOP_ACC)
6280               {
6281                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6282                 pic16_emitcode("movwf", "%s", pic16_aopGet(AOP(result), offset, FALSE, FALSE));
6283               }
6284           }
6285       }
6286   }
6287
6288 release :
6289   pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6290   pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6291   pic16_freeAsmop(result, NULL, ic, TRUE);
6292 }
6293
6294 /*-----------------------------------------------------------------*/
6295 /* genInline - write the inline code out                           */
6296 /*-----------------------------------------------------------------*/
6297 static void genInline (iCode *ic)
6298 {
6299   char *buffer, *bp, *bp1;
6300   bool inComment = FALSE;
6301
6302   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6303
6304   _G.inLine += (!options.asmpeep);
6305
6306   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6307
6308   while((bp1=strstr(bp, "\\n"))) {
6309     *bp1++ = '\n';
6310     *bp1++ = ' ';
6311     bp = bp1;
6312   }
6313   bp = bp1 = buffer;
6314
6315 #if 0
6316   /* This is an experimental code for #pragma inline
6317      and is temporarily disabled for 2.5.0 release */
6318   if(asmInlineMap)
6319   {
6320     symbol *sym;
6321     char *s;
6322     char *cbuf;
6323     int cblen;
6324
6325       cbuf = Safe_strdup(buffer);
6326       cblen = strlen(buffer)+1;
6327       memset(cbuf, 0, cblen);
6328
6329       bp = buffer;
6330       bp1 = cbuf;
6331       while(*bp) {
6332         if(*bp != '%')*bp1++ = *bp++;
6333         else {
6334           int i;
6335
6336             bp++;
6337             i = *bp - '0';
6338             if(i>elementsInSet(asmInlineMap))break;
6339
6340             bp++;
6341             s = indexSet(asmInlineMap, i);
6342             DEBUGpc("searching symbol s = `%s'", s);
6343             sym = findSym(SymbolTab, NULL, s);
6344
6345             if(sym->reqv) {
6346               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6347             } else {
6348               strcat(bp1, sym->rname);
6349             }
6350
6351             while(*bp1)bp1++;
6352         }
6353
6354         if(strlen(bp1) > cblen - 16) {
6355           int i = strlen(cbuf);
6356           cblen += 50;
6357           cbuf = realloc(cbuf, cblen);
6358           memset(cbuf+i, 0, 50);
6359           bp1 = cbuf + i;
6360         }
6361       }
6362
6363       free(buffer);
6364       buffer = Safe_strdup( cbuf );
6365       free(cbuf);
6366
6367       bp = bp1 = buffer;
6368   }
6369 #endif  /* 0 */
6370
6371   /* emit each line as a code */
6372   while (*bp)
6373     {
6374       switch (*bp)
6375         {
6376         case ';':
6377           inComment = TRUE;
6378           ++bp;
6379           break;
6380
6381         case '\n':
6382           inComment = FALSE;
6383           *bp++ = '\0';
6384           if (*bp1)
6385             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6386           bp1 = bp;
6387           break;
6388
6389         default:
6390           /* Add \n for labels, not dirs such as c:\mydir */
6391           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6392             {
6393               ++bp;
6394               *bp = '\0';
6395               ++bp;
6396               /* print label, use this special format with NULL directive
6397                * to denote that the argument should not be indented with tab */
6398               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6399               bp1 = bp;
6400             }
6401           else
6402             ++bp;
6403           break;
6404         }
6405     }
6406
6407   if ((bp1 != bp) && *bp1)
6408     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6409
6410   Safe_free (buffer);
6411
6412   _G.inLine -= (!options.asmpeep);
6413 }
6414
6415 /*-----------------------------------------------------------------*/
6416 /* genRRC - rotate right with carry                                */
6417 /*-----------------------------------------------------------------*/
6418 static void genRRC (iCode *ic)
6419 {
6420   operand *left , *result ;
6421   int size, offset = 0, same;
6422
6423   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6424
6425   /* rotate right with carry */
6426   left = IC_LEFT(ic);
6427   result=IC_RESULT(ic);
6428   pic16_aopOp (left,ic,FALSE);
6429   pic16_aopOp (result,ic,TRUE);
6430
6431   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6432
6433   same = pic16_sameRegs(AOP(result),AOP(left));
6434
6435   size = AOP_SIZE(result);
6436
6437   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6438
6439   /* get the lsb and put it into the carry */
6440   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6441
6442   offset = 0 ;
6443
6444   while(size--) {
6445
6446     if(same) {
6447       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6448     } else {
6449       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6450       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6451     }
6452
6453     offset++;
6454   }
6455
6456   pic16_freeAsmop(left,NULL,ic,TRUE);
6457   pic16_freeAsmop(result,NULL,ic,TRUE);
6458 }
6459
6460 /*-----------------------------------------------------------------*/
6461 /* genRLC - generate code for rotate left with carry               */
6462 /*-----------------------------------------------------------------*/
6463 static void genRLC (iCode *ic)
6464 {
6465   operand *left , *result ;
6466   int size, offset = 0;
6467   int same;
6468
6469   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6470   /* rotate right with carry */
6471   left = IC_LEFT(ic);
6472   result=IC_RESULT(ic);
6473   pic16_aopOp (left,ic,FALSE);
6474   pic16_aopOp (result,ic,TRUE);
6475
6476   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6477
6478   same = pic16_sameRegs(AOP(result),AOP(left));
6479
6480   /* move it to the result */
6481   size = AOP_SIZE(result);
6482
6483   /* get the msb and put it into the carry */
6484   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6485
6486   offset = 0 ;
6487
6488   while(size--) {
6489
6490     if(same) {
6491       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6492     } else {
6493       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6494       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6495     }
6496
6497     offset++;
6498   }
6499
6500
6501   pic16_freeAsmop(left,NULL,ic,TRUE);
6502   pic16_freeAsmop(result,NULL,ic,TRUE);
6503 }
6504
6505
6506 /* gpasm can get the highest order bit with HIGH/UPPER
6507  * so the following probably is not needed -- VR */
6508
6509 /*-----------------------------------------------------------------*/
6510 /* genGetHbit - generates code get highest order bit               */
6511 /*-----------------------------------------------------------------*/
6512 static void genGetHbit (iCode *ic)
6513 {
6514     operand *left, *result;
6515     left = IC_LEFT(ic);
6516     result=IC_RESULT(ic);
6517     pic16_aopOp (left,ic,FALSE);
6518     pic16_aopOp (result,ic,FALSE);
6519
6520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6521     /* get the highest order byte into a */
6522     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6523     if(AOP_TYPE(result) == AOP_CRY){
6524         pic16_emitcode("rlc","a");
6525         pic16_outBitC(result);
6526     }
6527     else{
6528         pic16_emitcode("rl","a");
6529         pic16_emitcode("anl","a,#0x01");
6530         pic16_outAcc(result);
6531     }
6532
6533
6534     pic16_freeAsmop(left,NULL,ic,TRUE);
6535     pic16_freeAsmop(result,NULL,ic,TRUE);
6536 }
6537
6538 #if 0
6539 /*-----------------------------------------------------------------*/
6540 /* AccRol - rotate left accumulator by known count                 */
6541 /*-----------------------------------------------------------------*/
6542 static void AccRol (int shCount)
6543 {
6544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6545     shCount &= 0x0007;              // shCount : 0..7
6546     switch(shCount){
6547         case 0 :
6548             break;
6549         case 1 :
6550             pic16_emitcode("rl","a");
6551             break;
6552         case 2 :
6553             pic16_emitcode("rl","a");
6554             pic16_emitcode("rl","a");
6555             break;
6556         case 3 :
6557             pic16_emitcode("swap","a");
6558             pic16_emitcode("rr","a");
6559             break;
6560         case 4 :
6561             pic16_emitcode("swap","a");
6562             break;
6563         case 5 :
6564             pic16_emitcode("swap","a");
6565             pic16_emitcode("rl","a");
6566             break;
6567         case 6 :
6568             pic16_emitcode("rr","a");
6569             pic16_emitcode("rr","a");
6570             break;
6571         case 7 :
6572             pic16_emitcode("rr","a");
6573             break;
6574     }
6575 }
6576 #endif
6577
6578 /*-----------------------------------------------------------------*/
6579 /* AccLsh - left shift accumulator by known count                  */
6580 /*-----------------------------------------------------------------*/
6581 static void AccLsh (int shCount, int doMask)
6582 {
6583         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6584         switch(shCount){
6585                 case 0 :
6586                         return;
6587                         break;
6588                 case 1 :
6589                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590                         break;
6591                 case 2 :
6592                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6593                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6594                         break;
6595                 case 3 :
6596                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597                         pic16_emitpcode(POC_RRNCFW,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_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605                         break;
6606                 case 6 :
6607                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6609                         break;
6610                 case 7 :
6611                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6612                         break;
6613         }
6614         if (doMask) {
6615                 /* no masking is required in genPackBits */
6616                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6617         }
6618 }
6619
6620 /*-----------------------------------------------------------------*/
6621 /* AccRsh - right shift accumulator by known count                 */
6622 /*-----------------------------------------------------------------*/
6623 static void AccRsh (int shCount, int andmask)
6624 {
6625         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6626         assert ((shCount >= 0) && (shCount <= 8));
6627         switch (shCount) {
6628                 case 0 :
6629                         return; break;
6630                 case 1 :
6631                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6632                         break;
6633                 case 2 :
6634                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6635                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6636                         break;
6637                 case 3 :
6638                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6639                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6640                         break;
6641                 case 4 :
6642                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6643                         break;
6644                 case 5 :
6645                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6646                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6647                         break;
6648                 case 6 :
6649                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6650                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6651                         break;
6652                 case 7 :
6653                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6654                         break;
6655                 default:
6656                         // Rotating by 8 is a NOP.
6657                         break;
6658         }
6659
6660         if (andmask)
6661                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6662         else
6663                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6664 }
6665
6666 /*-----------------------------------------------------------------*/
6667 /* shiftR1Left2Result - shift right one byte from left to result   */
6668 /*-----------------------------------------------------------------*/
6669 static void shiftR1Left2ResultSigned (operand *left, int offl,
6670                                 operand *result, int offr,
6671                                 int shCount)
6672 {
6673   int same;
6674
6675   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6676   assert ((shCount >= 0) && (shCount <= 8));
6677
6678   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6679
6680   /* Do NOT use result for intermediate results, it might be an SFR!. */
6681   switch (shCount) {
6682   case 0:
6683     if (!same) {
6684       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6685       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6686     }
6687     break;
6688
6689   case 1:
6690     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6691     if (same)
6692       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6693     else {
6694       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6695       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6696     }
6697     break;
6698
6699   case 2:
6700     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6701     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6702     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6703     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6704     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6705     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6706     break;
6707
6708   case 3:
6709     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6710     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6711     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6712     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6713     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6714     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6715     break;
6716
6717   case 4:
6718     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6719     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6720     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6721     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6722     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6723     break;
6724
6725   case 5:
6726     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6727     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6728     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6729     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6730     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6731     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6732     break;
6733
6734   case 6:
6735     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6736     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6737     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6738     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6739     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6740     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6741     break;
6742
6743   case 7:
6744     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6745     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6746     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6747     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6748     break;
6749
6750   default:
6751     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6752     break;
6753   }
6754 }
6755
6756 /*-----------------------------------------------------------------*/
6757 /* shiftR1Left2Result - shift right one byte from left to result   */
6758 /*-----------------------------------------------------------------*/
6759 static void shiftR1Left2Result (operand *left, int offl,
6760                                 operand *result, int offr,
6761                                 int shCount, int sign)
6762 {
6763   int same;
6764
6765   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6766   assert ((shCount >= 0) && (shCount <= 8));
6767
6768   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6769
6770   /* Copy the msb into the carry if signed. */
6771   if (sign) {
6772     shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6773     return;
6774   }
6775
6776   /* Do NOT use result for intermediate results, it might be an SFR!. */
6777   switch (shCount) {
6778   case 0:
6779     if (!same) {
6780       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6781       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6782     }
6783     break;
6784
6785   case 1:
6786     if (same) {
6787       emitCLRC;
6788       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6789     } else {
6790       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6791       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6792       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6793     }
6794     break;
6795
6796   case 2:
6797     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6798     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6799     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6800     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6801     break;
6802
6803   case 3:
6804     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6805     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6806     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6807     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6808     break;
6809
6810   case 4:
6811     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6812     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6813     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6814     break;
6815
6816   case 5:
6817     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6818     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6819     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6820     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6821     break;
6822
6823   case 6:
6824     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6825     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6826     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6827     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6828     break;
6829
6830   case 7:
6831     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6832     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6833     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6834     break;
6835
6836   default:
6837     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6838     break;
6839   }
6840 }
6841
6842 /*-----------------------------------------------------------------*/
6843 /* shiftL1Left2Result - shift left one byte from left to result    */
6844 /*-----------------------------------------------------------------*/
6845 static void shiftL1Left2Result (operand *left, int offl,
6846                                 operand *result, int offr, int shCount)
6847 {
6848   int same;
6849
6850   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6851   assert ((shCount >= 0) && (shCount <= 8));
6852
6853   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6854
6855   /* Do NOT use result for intermediate results, it might be an SFR!. */
6856   switch (shCount) {
6857   case 0:
6858     if (!same) {
6859       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6860       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6861     }
6862     break;
6863
6864   case 1:
6865     if (same) {
6866       emitCLRC;
6867       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6868     } else {
6869       pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6870       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6871       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6872     }
6873     break;
6874
6875   case 2:
6876     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6877     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6878     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6879     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6880     break;
6881
6882   case 3:
6883     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6884     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6885     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6886     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6887     break;
6888
6889   case 4:
6890     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6891     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6892     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6893     break;
6894
6895   case 5:
6896     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6897     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6898     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6899     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6900     break;
6901
6902   case 6:
6903     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6904     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6905     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6906     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6907     break;
6908
6909   case 7:
6910     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6911     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6912     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6913     break;
6914
6915   default:
6916     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6917     break;
6918   }
6919 }
6920
6921 /*-----------------------------------------------------------------*/
6922 /* movLeft2Result - move byte from left to result                  */
6923 /*-----------------------------------------------------------------*/
6924 static void movLeft2Result (operand *left, int offl,
6925                             operand *result, int offr)
6926 {
6927   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6928   if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6929     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6930     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6931   }
6932 }
6933
6934 /*-----------------------------------------------------------------*/
6935 /* shiftL2Left2Result - shift left two bytes from left to result   */
6936 /*-----------------------------------------------------------------*/
6937 static void shiftL2Left2Result (operand *left, int offl,
6938                                 operand *result, int offr, int shCount)
6939 {
6940   int same = pic16_sameRegs(AOP(result), AOP(left));
6941   int i;
6942
6943   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6944
6945   if (same && (offl != offr)) { // shift bytes
6946     if (offr > offl) {
6947        for(i=1;i>-1;i--) {
6948          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6949          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6950        }
6951     } else { // just treat as different later on
6952                 same = 0;
6953     }
6954   }
6955
6956   if(same) {
6957     switch(shCount) {
6958     case 0:
6959       break;
6960     case 1:
6961     case 2:
6962     case 3:
6963
6964       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6965       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6966       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6967
6968       while(--shCount) {
6969                 emitCLRC;
6970                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6971                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6972       }
6973
6974       break;
6975     case 4:
6976     case 5:
6977       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6978       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6979       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6980       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6981       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6982       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6983       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6984       if(shCount >=5) {
6985                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6986                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6987       }
6988       break;
6989     case 6:
6990       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6991       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6992       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6993       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6994       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6995       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6996       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6997       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6998       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6999       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7000       break;
7001     case 7:
7002       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7003       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7004       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7005       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7006       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7007     }
7008
7009   } else {
7010     switch(shCount) {
7011     case 0:
7012       break;
7013     case 1:
7014     case 2:
7015     case 3:
7016       /* note, use a mov/add for the shift since the mov has a
7017          chance of getting optimized out */
7018       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7019       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7020       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7021       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7023
7024       while(--shCount) {
7025                 emitCLRC;
7026                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7027                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7028       }
7029       break;
7030
7031     case 4:
7032     case 5:
7033       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7034       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7035       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7036       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7037       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7038       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
7039       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7040       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7041
7042
7043       if(shCount == 5) {
7044                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7045                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7046       }
7047       break;
7048     case 6:
7049       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7051       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7052       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7053
7054       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7055       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7056       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7057       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7058       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7059       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7060       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7061       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7062       break;
7063     case 7:
7064       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7065       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7066       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7067       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7068       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7069     }
7070   }
7071
7072 }
7073 /*-----------------------------------------------------------------*/
7074 /* shiftR2Left2Result - shift right two bytes from left to result  */
7075 /*-----------------------------------------------------------------*/
7076 static void shiftR2Left2Result (operand *left, int offl,
7077                                 operand *result, int offr,
7078                                 int shCount, int sign)
7079 {
7080   int same = pic16_sameRegs(AOP(result), AOP(left));
7081   int i;
7082   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7083
7084   if (same && (offl != offr)) { // shift right bytes
7085     if (offr < offl) {
7086        for(i=0;i<2;i++) {
7087          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7088          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7089        }
7090     } else { // just treat as different later on
7091                 same = 0;
7092     }
7093   }
7094
7095   switch(shCount) {
7096   case 0:
7097     break;
7098   case 1:
7099   case 2:
7100   case 3:
7101     /* obtain sign from left operand */
7102     if(sign)
7103       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7104     else
7105       emitCLRC;
7106
7107     if(same) {
7108       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7109       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7110     } else {
7111       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7112       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7113       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7114       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7115     }
7116
7117     while(--shCount) {
7118       if(sign)
7119         /* now get sign from already assigned result (avoid BANKSEL) */
7120         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7121       else
7122         emitCLRC;
7123       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7124       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7125     }
7126     break;
7127   case 4:
7128   case 5:
7129     if(same) {
7130
7131       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7132       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7133       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7134
7135       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7136       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7137       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7138       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7139     } else {
7140       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7141       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7142       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7143
7144       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7145       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7146       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7147       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7148       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7149     }
7150
7151     if(shCount >=5) {
7152       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7153       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7154     }
7155
7156     if(sign) {
7157       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7158       pic16_emitpcode(POC_BTFSC,
7159                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7160       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7161     }
7162
7163     break;
7164
7165   case 6:
7166     if(same) {
7167
7168       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7169       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7170
7171       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7172       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7173       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7174       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7175       if(sign) {
7176         pic16_emitpcode(POC_BTFSC,
7177                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7178         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7179       }
7180       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7181       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7182       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7183       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7184     } else {
7185       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7186       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7187       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7188       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7189       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7190       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7191       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7192       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7193       if(sign) {
7194         pic16_emitpcode(POC_BTFSC,
7195                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7196         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7197       }
7198       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7199       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7200
7201
7202     }
7203
7204     break;
7205   case 7:
7206     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7207     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7208     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7209     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7210     if(sign) {
7211       emitSKPNC;
7212       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7213     } else
7214       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7215   }
7216 }
7217
7218
7219 /*-----------------------------------------------------------------*/
7220 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7221 /*-----------------------------------------------------------------*/
7222 static void shiftLLeftOrResult (operand *left, int offl,
7223                                 operand *result, int offr, int shCount)
7224 {
7225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7226
7227     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7228     /* shift left accumulator */
7229     AccLsh(shCount, 1);
7230     /* or with result */
7231     /* back to result */
7232     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7233 }
7234
7235 /*-----------------------------------------------------------------*/
7236 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7237 /*-----------------------------------------------------------------*/
7238 static void shiftRLeftOrResult (operand *left, int offl,
7239                                 operand *result, int offr, int shCount)
7240 {
7241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7242
7243     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7244     /* shift right accumulator */
7245     AccRsh(shCount, 1);
7246     /* or with result */
7247     /* back to result */
7248     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7249 }
7250
7251 /*-----------------------------------------------------------------*/
7252 /* genlshOne - left shift a one byte quantity by known count       */
7253 /*-----------------------------------------------------------------*/
7254 static void genlshOne (operand *result, operand *left, int shCount)
7255 {
7256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7257     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7258 }
7259
7260 /*-----------------------------------------------------------------*/
7261 /* genlshTwo - left shift two bytes by known amount != 0           */
7262 /*-----------------------------------------------------------------*/
7263 static void genlshTwo (operand *result,operand *left, int shCount)
7264 {
7265     int size;
7266
7267     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7268     size = pic16_getDataSize(result);
7269
7270     /* if shCount >= 8 */
7271     if (shCount >= 8) {
7272         shCount -= 8 ;
7273
7274         if (size > 1){
7275             if (shCount)
7276                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7277             else
7278                 movLeft2Result(left, LSB, result, MSB16);
7279         }
7280         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7281     }
7282
7283     /*  1 <= shCount <= 7 */
7284     else {
7285         if(size == 1)
7286             shiftL1Left2Result(left, LSB, result, LSB, shCount);
7287         else
7288             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7289     }
7290 }
7291
7292 /*-----------------------------------------------------------------*/
7293 /* shiftLLong - shift left one long from left to result            */
7294 /* offr = LSB or MSB16                                             */
7295 /*-----------------------------------------------------------------*/
7296 static void shiftLLong (operand *left, operand *result, int offr )
7297 {
7298     int size = AOP_SIZE(result);
7299     int same = pic16_sameRegs(AOP(left),AOP(result));
7300         int i;
7301
7302     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7303
7304         if (same && (offr == MSB16)) { //shift one byte
7305                 for(i=size-1;i>=MSB16;i--) {
7306                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7307                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7308                 }
7309         } else {
7310                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7311         }
7312
7313     if (size > LSB+offr ){
7314                 if (same) {
7315                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7316                 } else {
7317                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7318                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7319                 }
7320          }
7321
7322     if(size > MSB16+offr){
7323                 if (same) {
7324                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7325                 } else {
7326                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7327                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7328                 }
7329     }
7330
7331     if(size > MSB24+offr){
7332                 if (same) {
7333                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7334                 } else {
7335                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7336                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7337                 }
7338     }
7339
7340     if(size > MSB32+offr){
7341                 if (same) {
7342                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7343                 } else {
7344                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7345                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7346                 }
7347     }
7348     if(offr != LSB)
7349                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7350
7351 }
7352
7353 /*-----------------------------------------------------------------*/
7354 /* genlshFour - shift four byte by a known amount != 0             */
7355 /*-----------------------------------------------------------------*/
7356 static void genlshFour (operand *result, operand *left, int shCount)
7357 {
7358     int size;
7359
7360     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7361     size = AOP_SIZE(result);
7362
7363     /* if shifting more that 3 bytes */
7364     if (shCount >= 24 ) {
7365         shCount -= 24;
7366         if (shCount)
7367             /* lowest order of left goes to the highest
7368             order of the destination */
7369             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7370         else
7371             movLeft2Result(left, LSB, result, MSB32);
7372
7373                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7374                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7375                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7376
7377         return;
7378     }
7379
7380     /* more than two bytes */
7381     else if ( shCount >= 16 ) {
7382         /* lower order two bytes goes to higher order two bytes */
7383         shCount -= 16;
7384         /* if some more remaining */
7385         if (shCount)
7386             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7387         else {
7388             movLeft2Result(left, MSB16, result, MSB32);
7389             movLeft2Result(left, LSB, result, MSB24);
7390         }
7391                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7392                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7393         return;
7394     }
7395
7396     /* if more than 1 byte */
7397     else if ( shCount >= 8 ) {
7398         /* lower order three bytes goes to higher order  three bytes */
7399         shCount -= 8;
7400         if(size == 2){
7401             if(shCount)
7402                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7403             else
7404                 movLeft2Result(left, LSB, result, MSB16);
7405         }
7406         else{   /* size = 4 */
7407             if(shCount == 0){
7408                 movLeft2Result(left, MSB24, result, MSB32);
7409                 movLeft2Result(left, MSB16, result, MSB24);
7410                 movLeft2Result(left, LSB, result, MSB16);
7411                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7412             }
7413             else if(shCount == 1)
7414                 shiftLLong(left, result, MSB16);
7415             else{
7416                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7417                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7418                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7419                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7420             }
7421         }
7422     }
7423
7424     /* 1 <= shCount <= 7 */
7425     else if(shCount <= 3)
7426     {
7427         shiftLLong(left, result, LSB);
7428         while(--shCount >= 1)
7429             shiftLLong(result, result, LSB);
7430     }
7431     /* 3 <= shCount <= 7, optimize */
7432     else{
7433         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7434         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7435         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7436     }
7437 }
7438
7439 /*-----------------------------------------------------------------*/
7440 /* genLeftShiftLiteral - left shifting by known count              */
7441 /*-----------------------------------------------------------------*/
7442 void pic16_genLeftShiftLiteral (operand *left,
7443                                  operand *right,
7444                                  operand *result,
7445                                  iCode *ic)
7446 {
7447     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7448     int size;
7449
7450     FENTRY;
7451     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7452     pic16_freeAsmop(right,NULL,ic,TRUE);
7453
7454     pic16_aopOp(left,ic,FALSE);
7455     pic16_aopOp(result,ic,TRUE);
7456
7457     size = getSize(operandType(result));
7458
7459 #if VIEW_SIZE
7460     pic16_emitcode("; shift left ","result %d, left %d",size,
7461              AOP_SIZE(left));
7462 #endif
7463
7464     /* I suppose that the left size >= result size */
7465     if(shCount == 0){
7466         while(size--){
7467             movLeft2Result(left, size, result, size);
7468         }
7469     }
7470
7471     else if(shCount >= (size * 8))
7472         while(size--)
7473             pic16_aopPut(AOP(result),zero,size);
7474     else{
7475         switch (size) {
7476             case 1:
7477                 genlshOne (result,left,shCount);
7478                 break;
7479
7480             case 2:
7481             case 3:
7482                 genlshTwo (result,left,shCount);
7483                 break;
7484
7485             case 4:
7486                 genlshFour (result,left,shCount);
7487                 break;
7488         }
7489     }
7490     pic16_freeAsmop(left,NULL,ic,TRUE);
7491     pic16_freeAsmop(result,NULL,ic,TRUE);
7492 }
7493
7494 /*-----------------------------------------------------------------*
7495  * genMultiAsm - repeat assembly instruction for size of register.
7496  * if endian == 1, then the high byte (i.e base address + size of
7497  * register) is used first else the low byte is used first;
7498  *-----------------------------------------------------------------*/
7499 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7500 {
7501
7502   int offset = 0;
7503
7504   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7505
7506   if(!reg)
7507     return;
7508
7509   if(!endian) {
7510     endian = 1;
7511   } else {
7512     endian = -1;
7513     offset = size-1;
7514   }
7515
7516   while(size--) {
7517     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7518     offset += endian;
7519   }
7520
7521 }
7522
7523 /*-----------------------------------------------------------------*/
7524 /* genrshOne - right shift a one byte quantity by known count      */
7525 /*-----------------------------------------------------------------*/
7526 static void genrshOne (operand *result, operand *left,
7527                        int shCount, int sign)
7528 {
7529     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7530     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7531 }
7532
7533 /*-----------------------------------------------------------------*/
7534 /* genrshTwo - right shift two bytes by known amount != 0          */
7535 /*-----------------------------------------------------------------*/
7536 static void genrshTwo (operand *result,operand *left,
7537                        int shCount, int sign)
7538 {
7539   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7540   /* if shCount >= 8 */
7541   if (shCount >= 8) {
7542     shCount -= 8 ;
7543     if (shCount)
7544       shiftR1Left2Result(left, MSB16, result, LSB,
7545                          shCount, sign);
7546     else
7547       movLeft2Result(left, MSB16, result, LSB);
7548
7549     pic16_addSign (result, 1, sign);
7550   }
7551
7552   /*  1 <= shCount <= 7 */
7553   else
7554     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7555 }
7556
7557 /*-----------------------------------------------------------------*/
7558 /* shiftRLong - shift right one long from left to result           */
7559 /* offl = LSB or MSB16                                             */
7560 /*-----------------------------------------------------------------*/
7561 static void shiftRLong (operand *left, int offl,
7562                         operand *result, int sign)
7563 {
7564     int size = AOP_SIZE(result);
7565     int same = pic16_sameRegs(AOP(left),AOP(result));
7566     int i;
7567     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7568
7569         if (same && (offl == MSB16)) { //shift one byte right
7570                 for(i=MSB16;i<size;i++) {
7571                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7572                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7573                 }
7574         }
7575
7576     if(sign)
7577                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7578         else
7579                 emitCLRC;
7580
7581         if (same) {
7582                 if (offl == LSB)
7583                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7584         } else {
7585         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7586         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7587         }
7588
7589     if(offl == MSB16) {
7590         /* add sign of "a" */
7591         pic16_addSign(result, MSB32, sign);
7592         }
7593
7594         if (same) {
7595         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7596         } else {
7597         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7598         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7599         }
7600
7601         if (same) {
7602         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7603         } else {
7604         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7605         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7606         }
7607
7608         if (same) {
7609         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7610         } else {
7611         if(offl == LSB){
7612                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7613                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7614         }
7615         }
7616 }
7617
7618 /*-----------------------------------------------------------------*/
7619 /* genrshFour - shift four byte by a known amount != 0             */
7620 /*-----------------------------------------------------------------*/
7621 static void genrshFour (operand *result, operand *left,
7622                         int shCount, int sign)
7623 {
7624   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7625   /* if shifting more that 3 bytes */
7626   if(shCount >= 24 ) {
7627     shCount -= 24;
7628     if(shCount)
7629       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7630     else
7631       movLeft2Result(left, MSB32, result, LSB);
7632
7633     pic16_addSign(result, MSB16, sign);
7634   }
7635   else if(shCount >= 16){
7636     shCount -= 16;
7637     if(shCount)
7638       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7639     else{
7640       movLeft2Result(left, MSB24, result, LSB);
7641       movLeft2Result(left, MSB32, result, MSB16);
7642     }
7643     pic16_addSign(result, MSB24, sign);
7644   }
7645   else if(shCount >= 8){
7646     shCount -= 8;
7647     if(shCount == 1)
7648       shiftRLong(left, MSB16, result, sign);
7649     else if(shCount == 0){
7650       movLeft2Result(left, MSB16, result, LSB);
7651       movLeft2Result(left, MSB24, result, MSB16);
7652       movLeft2Result(left, MSB32, result, MSB24);
7653       pic16_addSign(result, MSB32, sign);
7654     }
7655     else{ //shcount >= 2
7656       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7657       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7658       /* the last shift is signed */
7659       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7660       pic16_addSign(result, MSB32, sign);
7661     }
7662   }
7663   else{   /* 1 <= shCount <= 7 */
7664     if(shCount <= 2){
7665       shiftRLong(left, LSB, result, sign);
7666       if(shCount == 2)
7667         shiftRLong(result, LSB, result, sign);
7668     }
7669     else{
7670       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7671       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7672       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7673     }
7674   }
7675 }
7676
7677 /*-----------------------------------------------------------------*/
7678 /* genRightShiftLiteral - right shifting by known count            */
7679 /*-----------------------------------------------------------------*/
7680 static void genRightShiftLiteral (operand *left,
7681                                   operand *right,
7682                                   operand *result,
7683                                   iCode *ic,
7684                                   int sign)
7685 {
7686   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7687   int lsize,res_size;
7688
7689   pic16_freeAsmop(right,NULL,ic,TRUE);
7690
7691   pic16_aopOp(left,ic,FALSE);
7692   pic16_aopOp(result,ic,TRUE);
7693
7694   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7695
7696 #if VIEW_SIZE
7697   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7698                  AOP_SIZE(left));
7699 #endif
7700
7701   lsize = pic16_getDataSize(left);
7702   res_size = pic16_getDataSize(result);
7703   /* test the LEFT size !!! */
7704
7705   /* I suppose that the left size >= result size */
7706   if (shCount == 0) {
7707     assert (res_size <= lsize);
7708     while (res_size--) {
7709       pic16_mov2f (AOP(result), AOP(left), res_size);
7710     } // for
7711   } else if (shCount >= (lsize * 8)) {
7712     if (sign) {
7713       /* 
7714        * Do NOT use
7715        *    CLRF    result
7716        *    BTFSC   left, 7
7717        *    SETF    result
7718        * even for 8-bit operands; result might be an SFR.
7719        */
7720       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7721       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7722       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7723       while (res_size--) {
7724         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7725       }
7726     } else { // unsigned
7727       while (res_size--) {
7728         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7729       }
7730     }
7731   } else { // 0 < shCount < 8*lsize
7732     switch (res_size) {
7733     case 1:
7734       genrshOne (result,left,shCount,sign);
7735       break;
7736
7737     case 2:
7738       genrshTwo (result,left,shCount,sign);
7739       break;
7740
7741     case 4:
7742       genrshFour (result,left,shCount,sign);
7743       break;
7744     default :
7745       break;
7746     }
7747   }
7748
7749   pic16_freeAsmop(left,NULL,ic,TRUE);
7750   pic16_freeAsmop(result,NULL,ic,TRUE);
7751 }
7752
7753 /*-----------------------------------------------------------------*/
7754 /* genGenericShift - generates code for left or right shifting     */
7755 /*-----------------------------------------------------------------*/
7756 static void genGenericShift (iCode *ic, int isShiftLeft)
7757 {
7758   operand *left,*right, *result;
7759   int offset;
7760   int sign, signedCount;
7761   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7762   PIC_OPCODE pos_shift, neg_shift;
7763
7764   FENTRY;
7765
7766   right = IC_RIGHT(ic);
7767   left  = IC_LEFT(ic);
7768   result = IC_RESULT(ic);
7769
7770   pic16_aopOp(right,ic,FALSE);
7771   pic16_aopOp(left,ic,FALSE);
7772   pic16_aopOp(result,ic,TRUE);
7773
7774   sign = !SPEC_USIGN(operandType (left));
7775   signedCount = !SPEC_USIGN(operandType (right));
7776
7777   /* if the shift count is known then do it
7778      as efficiently as possible */
7779   if (AOP_TYPE(right) == AOP_LIT) {
7780     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7781     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7782     // we should modify right->aopu.aop_lit here!
7783     // Instead we use abs(shCount) in genXXXShiftLiteral()...
7784     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7785     if (isShiftLeft)
7786       pic16_genLeftShiftLiteral (left,right,result,ic);
7787     else
7788       genRightShiftLiteral (left,right,result,ic, sign);
7789
7790     goto release;
7791   } // if (right is literal)
7792
7793   /* shift count is unknown then we have to form a loop.
7794    * Note: we take only the lower order byte since shifting
7795    * more than 32 bits make no sense anyway, ( the
7796    * largest size of an object can be only 32 bits )
7797    * Note: we perform arithmetic shifts if the left operand is
7798    * signed and we do an (effective) right shift, i. e. we
7799    * shift in the sign bit from the left. */
7800
7801   label_complete = newiTempLabel ( NULL );
7802   label_loop_pos = newiTempLabel ( NULL );
7803   label_loop_neg = NULL;
7804   label_negative = NULL;
7805   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7806   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7807
7808   if (signedCount) {
7809     // additional labels needed
7810     label_loop_neg = newiTempLabel ( NULL );
7811     label_negative = newiTempLabel ( NULL );
7812   } // if
7813
7814   // copy source to result -- this will effectively truncate the left operand to the size of result!
7815   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7816   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7817   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7818     pic16_mov2f (AOP(result),AOP(left), offset);
7819   } // for
7820
7821   // if result is longer than left, fill with zeros (or sign)
7822   if (AOP_SIZE(left) < AOP_SIZE(result)) {
7823     if (sign && AOP_SIZE(left) > 0) {
7824       // shift signed operand -- fill with sign
7825       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7826       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7827       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7828       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7829         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7830       } // for
7831     } else {
7832       // shift unsigned operand -- fill result with zeros
7833       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7834         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7835       } // for
7836     }
7837   } // if (size mismatch)
7838
7839   pic16_mov2w (AOP(right), 0);
7840   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7841   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7842
7843 #if 0
7844   // perform a shift by one (shift count is positive)
7845   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7846   // 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])
7847   pic16_emitpLabel (label_loop_pos->key);
7848   emitCLRC;
7849   if (sign && (pos_shift == POC_RRCF)) {
7850     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7851     emitSETC;
7852   } // if
7853   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7854   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7855   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7856 #else
7857   // perform a shift by one (shift count is positive)
7858   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7859   // 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])
7860   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7861   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7862   emitCLRC;
7863   pic16_emitpLabel (label_loop_pos->key);
7864   if (sign && (pos_shift == POC_RRCF)) {
7865     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7866     emitSETC;
7867   } // if
7868   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7869   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7870   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7871   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7872 #endif
7873
7874   if (signedCount) {
7875     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7876
7877     pic16_emitpLabel (label_negative->key);
7878     // perform a shift by -1 (shift count is negative)
7879     // 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)
7880     emitCLRC;
7881     pic16_emitpLabel (label_loop_neg->key);
7882     if (sign && (neg_shift == POC_RRCF)) {
7883       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7884       emitSETC;
7885     } // if
7886     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7887     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7888     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7889     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7890   } // if (signedCount)
7891
7892   pic16_emitpLabel (label_complete->key);
7893
7894 release:
7895   pic16_freeAsmop (right,NULL,ic,TRUE);
7896   pic16_freeAsmop(left,NULL,ic,TRUE);
7897   pic16_freeAsmop(result,NULL,ic,TRUE);
7898 }
7899
7900 static void genLeftShift (iCode *ic) {
7901   genGenericShift (ic, 1);
7902 }
7903
7904 static void genRightShift (iCode *ic) {
7905   genGenericShift (ic, 0);
7906 }
7907
7908
7909 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7910 void pic16_loadFSR0(operand *op, int lit)
7911 {
7912   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7913     if (AOP_TYPE(op) == AOP_LIT) {
7914       /* handle 12 bit integers correctly */
7915       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7916       if ((val & 0x0fff) != val) {
7917         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7918                 val, (val & 0x0fff) );
7919         val &= 0x0fff;
7920       }
7921       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7922     } else {
7923       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7924     }
7925   } else {
7926     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7927     // set up FSR0 with address of result
7928     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7929     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7930   }
7931 }
7932
7933 /*----------------------------------------------------------------*/
7934 /* pic16_derefPtr - move one byte from the location ptr points to */
7935 /*                  to WREG (doWrite == 0) or one byte from WREG   */
7936 /*                  to the location ptr points to (doWrite != 0)   */
7937 /*----------------------------------------------------------------*/
7938 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7939 {
7940   if (!IS_PTR(operandType(ptr)))
7941   {
7942     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7943     else pic16_mov2w (AOP(ptr), 0);
7944     return;
7945   }
7946
7947   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7948   /* We might determine pointer type right here: */
7949   p_type = DCL_TYPE(operandType(ptr));
7950
7951   switch (p_type) {
7952     case FPOINTER:
7953     case POINTER:
7954       if (!fsr0_setup || !*fsr0_setup)
7955       {
7956         pic16_loadFSR0( ptr, 0 );
7957         if (fsr0_setup) *fsr0_setup = 1;
7958       }
7959       if (doWrite)
7960         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7961       else
7962         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7963       break;
7964
7965     case GPOINTER:
7966       if (AOP(ptr)->aopu.aop_reg[2]) {
7967         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7968         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7969         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7970         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7971         pic16_mov2w(AOP(ptr), 2);
7972         pic16_callGenericPointerRW(doWrite, 1);
7973       } else {
7974         // data pointer (just 2 byte given)
7975         if (!fsr0_setup || !*fsr0_setup)
7976         {
7977           pic16_loadFSR0( ptr, 0 );
7978           if (fsr0_setup) *fsr0_setup = 1;
7979         }
7980         if (doWrite)
7981           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7982         else
7983           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7984       }
7985       break;
7986
7987     default:
7988       assert (0 && "invalid pointer type specified");
7989       break;
7990   }
7991 }
7992
7993 /*-----------------------------------------------------------------*/
7994 /* genUnpackBits - generates code for unpacking bits               */
7995 /*-----------------------------------------------------------------*/
7996 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7997 {
7998   int shCnt ;
7999   sym_link *etype, *letype;
8000   int blen=0, bstr=0;
8001   int lbstr;
8002   int same;
8003   pCodeOp *op;
8004
8005   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8006   etype = getSpec(operandType(result));
8007   letype = getSpec(operandType(left));
8008
8009   //    if(IS_BITFIELD(etype)) {
8010   blen = SPEC_BLEN(etype);
8011   bstr = SPEC_BSTR(etype);
8012   //    }
8013
8014   lbstr = SPEC_BSTR( letype );
8015
8016   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
8017       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
8018
8019 #if 1
8020   if((blen == 1) && (bstr < 8)
8021       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
8022     /* it is a single bit, so use the appropriate bit instructions */
8023     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
8024
8025     same = pic16_sameRegs(AOP(left),AOP(result));
8026     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
8027     pic16_emitpcode(POC_CLRF, op);
8028
8029     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8030       /* workaround to reduce the extra lfsr instruction */
8031       pic16_emitpcode(POC_BTFSC,
8032           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
8033     } else {
8034       assert (PIC_IS_DATA_PTR (operandType(left)));
8035       pic16_loadFSR0 (left, 0);
8036       pic16_emitpcode(POC_BTFSC,
8037           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8038     }
8039
8040     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8041       /* unsigned bitfields result in either 0 or 1 */
8042       pic16_emitpcode(POC_INCF, op);
8043     } else {
8044       /* signed bitfields result in either 0 or -1 */
8045       pic16_emitpcode(POC_DECF, op);
8046     }
8047     if (same) {
8048       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8049     }
8050
8051     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8052     return;
8053   }
8054
8055 #endif
8056
8057   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8058     // access symbol directly
8059     pic16_mov2w (AOP(left), 0);
8060   } else {
8061     pic16_derefPtr (left, ptype, 0, NULL);
8062   }
8063
8064   /* if we have bitdisplacement then it fits   */
8065   /* into this byte completely or if length is */
8066   /* less than a byte                          */
8067   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
8068
8069     /* shift right acc */
8070     AccRsh(shCnt, 0);
8071
8072     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8073           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8074
8075     /* VR -- normally I would use the following, but since we use the hack,
8076      * to avoid the masking from AccRsh, why not mask it right now? */
8077
8078     /*
8079        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8080      */
8081
8082     /* extend signed bitfields to 8 bits */
8083     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8084     {
8085       assert (blen + bstr > 0);
8086       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8087       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8088     }
8089
8090     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8091
8092     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8093     return ;
8094   }
8095
8096   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8097   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8098   exit(EXIT_FAILURE);
8099
8100   return ;
8101 }
8102
8103
8104 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8105 {
8106   int size, offset = 0, leoffset=0 ;
8107
8108         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8109         pic16_aopOp(result, ic, TRUE);
8110
8111         FENTRY;
8112
8113         size = AOP_SIZE(result);
8114 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8115
8116
8117 #if 1
8118         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8119                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8120                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8121                 goto release;
8122         }
8123 #endif
8124
8125         if(AOP(left)->aopu.pcop->type == PO_DIR)
8126                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8127
8128         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8129
8130         while (size--) {
8131                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8132
8133 //              pic16_DumpOp("(result)",result);
8134                 if(pic16_isLitAop(AOP(result))) {
8135                         pic16_mov2w(AOP(left), offset); // patch 8
8136                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8137                 } else {
8138                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8139                                 pic16_popGet(AOP(left), offset), //patch 8
8140                                 pic16_popGet(AOP(result), offset)));
8141                 }
8142
8143                 offset++;
8144                 leoffset++;
8145         }
8146
8147 release:
8148     pic16_freeAsmop(result,NULL,ic,TRUE);
8149 }
8150
8151
8152
8153 /*-----------------------------------------------------------------*/
8154 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8155 /*-----------------------------------------------------------------*/
8156 static void genNearPointerGet (operand *left,
8157                                operand *result,
8158                                iCode *ic)
8159 {
8160 //  asmop *aop = NULL;
8161   //regs *preg = NULL ;
8162   sym_link *rtype, *retype;
8163   sym_link *ltype, *letype;
8164
8165     FENTRY;
8166
8167     rtype = operandType(result);
8168     retype= getSpec(rtype);
8169     ltype = operandType(left);
8170     letype= getSpec(ltype);
8171
8172     pic16_aopOp(left,ic,FALSE);
8173
8174 //    pic16_DumpOp("(left)",left);
8175 //    pic16_DumpOp("(result)",result);
8176
8177     /* if left is rematerialisable and
8178      * result is not bit variable type and
8179      * the left is pointer to data space i.e
8180      * lower 128 bytes of space */
8181
8182     if (AOP_TYPE(left) == AOP_PCODE
8183       && !IS_BITFIELD(retype)
8184       && DCL_TYPE(ltype) == POINTER) {
8185
8186         genDataPointerGet (left,result,ic);
8187         pic16_freeAsmop(left, NULL, ic, TRUE);
8188         return ;
8189     }
8190
8191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8192     pic16_aopOp (result,ic,TRUE);
8193
8194     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8195
8196 #if 1
8197     if(IS_BITFIELD( retype )
8198       && (SPEC_BLEN(operandType(result))==1)
8199     ) {
8200       iCode *nextic;
8201       pCodeOp *jop;
8202       int bitstrt, bytestrt;
8203
8204         /* if this is bitfield of size 1, see if we are checking the value
8205          * of a single bit in an if-statement,
8206          * if yes, then don't generate usual code, but execute the
8207          * genIfx directly -- VR */
8208
8209         nextic = ic->next;
8210
8211         /* CHECK: if next iCode is IFX
8212          * and current result operand is nextic's conditional operand
8213          * and current result operand live ranges ends at nextic's key number
8214          */
8215         if((nextic->op == IFX)
8216           && (result == IC_COND(nextic))
8217           && (OP_LIVETO(result) == nextic->seq)
8218           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
8219           ) {
8220             /* everything is ok then */
8221             /* find a way to optimize the genIfx iCode */
8222
8223             bytestrt = SPEC_BSTR(operandType(result))/8;
8224             bitstrt = SPEC_BSTR(operandType(result))%8;
8225
8226             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8227
8228             genIfxpCOpJump(nextic, jop);
8229
8230             pic16_freeAsmop(left, NULL, ic, TRUE);
8231             pic16_freeAsmop(result, NULL, ic, TRUE);
8232             return;
8233         }
8234     }
8235 #endif
8236
8237     /* if bitfield then unpack the bits */
8238     if (IS_BITFIELD(letype))
8239       genUnpackBits (result, left, NULL, POINTER);
8240     else {
8241       /* we have can just get the values */
8242       int size = AOP_SIZE(result);
8243       int offset = 0;
8244
8245       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8246
8247       pic16_loadFSR0( left, 0 );
8248
8249       while(size--) {
8250         if(size) {
8251           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8252                 pic16_popGet(AOP(result), offset++)));
8253         } else {
8254           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8255                 pic16_popGet(AOP(result), offset++)));
8256         }
8257       }
8258     }
8259
8260 #if 0
8261     /* now some housekeeping stuff */
8262     if (aop) {
8263       /* we had to allocate for this iCode */
8264       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8265       pic16_freeAsmop(NULL,aop,ic,TRUE);
8266     } else {
8267       /* we did not allocate which means left
8268        * already in a pointer register, then
8269        * if size > 0 && this could be used again
8270        * we have to point it back to where it
8271        * belongs */
8272       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8273       if (AOP_SIZE(result) > 1
8274         && !OP_SYMBOL(left)->remat
8275         && ( OP_SYMBOL(left)->liveTo > ic->seq
8276             || ic->depth )) {
8277 //        int size = AOP_SIZE(result) - 1;
8278 //        while (size--)
8279 //          pic16_emitcode("dec","%s",rname);
8280         }
8281     }
8282 #endif
8283
8284     /* done */
8285     pic16_freeAsmop(left,NULL,ic,TRUE);
8286     pic16_freeAsmop(result,NULL,ic,TRUE);
8287 }
8288
8289 /*-----------------------------------------------------------------*/
8290 /* genGenPointerGet - gget value from generic pointer space        */
8291 /*-----------------------------------------------------------------*/
8292 static void genGenPointerGet (operand *left,
8293                               operand *result, iCode *ic)
8294 {
8295   int size;
8296   sym_link *letype = getSpec(operandType(left));
8297
8298   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8299   pic16_aopOp(left,ic,FALSE);
8300   pic16_aopOp(result,ic,TRUE);
8301   size = AOP_SIZE(result);
8302
8303   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8304
8305   /* if bit then unpack */
8306   if (IS_BITFIELD(letype)) {
8307     genUnpackBits(result,left,"BAD",GPOINTER);
8308     goto release;
8309   }
8310
8311   /* set up WREG:PRODL:FSR0L with address from left */
8312   mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8313   mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8314   pic16_mov2w(AOP(left), 2);
8315   pic16_callGenericPointerRW(0, size);
8316
8317   assignResultValue(result, size, 1);
8318
8319 release:
8320   pic16_freeAsmop(left,NULL,ic,TRUE);
8321   pic16_freeAsmop(result,NULL,ic,TRUE);
8322 }
8323
8324 /*-----------------------------------------------------------------*/
8325 /* genConstPointerGet - get value from const generic pointer space */
8326 /*-----------------------------------------------------------------*/
8327 static void genConstPointerGet (operand *left,
8328                                 operand *result, iCode *ic)
8329 {
8330   //sym_link *retype = getSpec(operandType(result));
8331   // symbol *albl = newiTempLabel(NULL);        // patch 15
8332   // symbol *blbl = newiTempLabel(NULL);        //
8333   // PIC_OPCODE poc;                            // patch 15
8334   int size;
8335   int offset = 0;
8336
8337   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8338   pic16_aopOp(left,ic,FALSE);
8339   pic16_aopOp(result,ic,TRUE);
8340   size = AOP_SIZE(result);
8341
8342   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8343
8344   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8345
8346   // set up table pointer
8347   if( (AOP_TYPE(left) == AOP_PCODE)
8348       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8349           || (AOP(left)->aopu.pcop->type == PO_DIR)))
8350     {
8351       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8352       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8353       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8354       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8355       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8356       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8357   } else {
8358     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8359     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8360     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8361   }
8362
8363   while(size--) {
8364     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8365     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8366     offset++;
8367   }
8368
8369   pic16_freeAsmop(left,NULL,ic,TRUE);
8370   pic16_freeAsmop(result,NULL,ic,TRUE);
8371 }
8372
8373
8374 /*-----------------------------------------------------------------*/
8375 /* genPointerGet - generate code for pointer get                   */
8376 /*-----------------------------------------------------------------*/
8377 static void genPointerGet (iCode *ic)
8378 {
8379   operand *left, *result ;
8380   sym_link *type, *etype;
8381   int p_type;
8382
8383     FENTRY;
8384
8385     left = IC_LEFT(ic);
8386     result = IC_RESULT(ic) ;
8387
8388     /* depending on the type of pointer we need to
8389     move it to the correct pointer register */
8390     type = operandType(left);
8391     etype = getSpec(type);
8392
8393 #if 0
8394     if (IS_PTR_CONST(type))
8395 #else
8396     if (IS_CODEPTR(type))
8397 #endif
8398       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8399
8400     /* if left is of type of pointer then it is simple */
8401     if (IS_PTR(type) && !IS_FUNC(type->next))
8402       p_type = DCL_TYPE(type);
8403     else {
8404       /* we have to go by the storage class */
8405       p_type = PTR_TYPE(SPEC_OCLS(etype));
8406
8407       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8408
8409       if (SPEC_OCLS(etype)->codesp ) {
8410         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8411         //p_type = CPOINTER ;
8412       } else
8413       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8414         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8415         /*p_type = FPOINTER ;*/
8416       } else
8417       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8418         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8419         /* p_type = PPOINTER; */
8420       } else
8421       if (SPEC_OCLS(etype) == idata ) {
8422         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8423         /* p_type = IPOINTER; */
8424       } else {
8425         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8426         /* p_type = POINTER ; */
8427       }
8428     }
8429
8430     /* now that we have the pointer type we assign
8431     the pointer values */
8432     switch (p_type) {
8433       case POINTER:
8434       case FPOINTER:
8435       case IPOINTER:
8436         genNearPointerGet (left,result,ic);
8437         break;
8438
8439 #if 0
8440       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8441       case PPOINTER:
8442         genPagedPointerGet(left,result,ic);
8443         break;
8444
8445       case FPOINTER:
8446         genFarPointerGet (left,result,ic);
8447         break;
8448 #endif
8449
8450       case CPOINTER:
8451         genConstPointerGet (left,result,ic);
8452         //pic16_emitcodePointerGet (left,result,ic);
8453         break;
8454
8455       case GPOINTER:
8456 #if 0
8457       if (IS_PTR_CONST(type))
8458         genConstPointerGet (left,result,ic);
8459       else
8460 #endif
8461         genGenPointerGet (left,result,ic);
8462       break;
8463
8464     default:
8465       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8466               "genPointerGet: illegal pointer type");
8467
8468     }
8469 }
8470
8471 /*-----------------------------------------------------------------*/
8472 /* genPackBits - generates code for packed bit storage             */
8473 /*-----------------------------------------------------------------*/
8474 static void genPackBits (sym_link    *etype , operand *result,
8475                          operand *right ,
8476                          char *rname, int p_type)
8477 {
8478   int shCnt = 0 ;
8479   int offset = 0  ;
8480   int rLen = 0 ;
8481   int blen, bstr ;
8482   int shifted_and_masked = 0;
8483   unsigned long lit = (unsigned long)-1;
8484   sym_link *retype;
8485
8486   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8487   blen = SPEC_BLEN(etype);
8488   bstr = SPEC_BSTR(etype);
8489
8490   retype = getSpec(operandType(right));
8491
8492   if(AOP_TYPE(right) == AOP_LIT) {
8493     lit = ulFromVal (AOP(right)->aopu.aop_lit);
8494
8495     if((blen == 1) && (bstr < 8)) {
8496       /* it is a single bit, so use the appropriate bit instructions */
8497
8498       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8499
8500       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8501         /* workaround to reduce the extra lfsr instruction */
8502         if(lit) {
8503           pic16_emitpcode(POC_BSF,
8504               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8505         } else {
8506           pic16_emitpcode(POC_BCF,
8507               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8508         }
8509       } else {
8510         if (PIC_IS_DATA_PTR(operandType(result))) {
8511           pic16_loadFSR0(result, 0);
8512           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8513               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8514         } else {
8515           /* get old value */
8516           pic16_derefPtr (result, p_type, 0, NULL);
8517           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8518               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8519           /* write back new value */
8520           pic16_derefPtr (result, p_type, 1, NULL);
8521         }
8522       }
8523
8524       return;
8525     }
8526     /* IORLW below is more efficient */
8527     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8528     lit = (lit & ((1UL << blen) - 1)) << bstr;
8529     shifted_and_masked = 1;
8530     offset++;
8531   } else
8532     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8533         && IS_BITFIELD(retype)
8534         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8535         && (blen == 1)) {
8536       int rblen, rbstr;
8537
8538       rblen = SPEC_BLEN( retype );
8539       rbstr = SPEC_BSTR( retype );
8540
8541       if(IS_BITFIELD(etype)) {
8542         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8543         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8544       } else {
8545         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8546       }
8547
8548       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8549
8550       if(IS_BITFIELD(etype)) {
8551         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8552       } else {
8553         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8554       }
8555
8556       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8557
8558       return;
8559     } else {
8560       /* move right to W */
8561       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8562     }
8563
8564   /* if the bit length is less than or   */
8565   /* it exactly fits a byte then         */
8566   if((shCnt=SPEC_BSTR(etype))
8567       || SPEC_BLEN(etype) <= 8 )  {
8568     int fsr0_setup = 0;
8569
8570     if (blen != 8 || (bstr % 8) != 0) {
8571       // we need to combine the value with the old value
8572       if(!shifted_and_masked)
8573       {
8574         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8575
8576         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8577             SPEC_BSTR(etype), SPEC_BLEN(etype));
8578
8579         /* shift left acc, do NOT mask the result again */
8580         AccLsh(shCnt, 0);
8581
8582         /* using PRODH as a temporary register here */
8583         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8584       }
8585
8586       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8587         || IS_DIRECT(result)) {
8588         /* access symbol directly */
8589         pic16_mov2w (AOP(result), 0);
8590       } else {
8591         /* get old value */
8592         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8593       }
8594 #if 1
8595       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8596             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8597                             (unsigned char)(0xff >> (8-bstr))) ));
8598       if (!shifted_and_masked) {
8599         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8600       } else {
8601         /* We have the shifted and masked (literal) right value in `lit' */
8602         if (lit != 0)
8603           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8604       }
8605     } else { // if (blen == 8 && (bstr % 8) == 0)
8606         if (shifted_and_masked) {
8607             // move right (literal) to WREG (only case where right is not yet in WREG)
8608             pic16_mov2w(AOP(right), (bstr / 8));
8609         }
8610     }
8611
8612     /* write new value back */
8613     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8614         || IS_DIRECT(result)) {
8615       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8616     } else {
8617       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8618     }
8619 #endif
8620
8621     return;
8622   }
8623
8624
8625 #if 0
8626   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8627   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8628   exit(EXIT_FAILURE);
8629 #endif
8630
8631
8632   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
8633   rLen = SPEC_BLEN(etype)-8;
8634
8635   /* now generate for lengths greater than one byte */
8636   while (1) {
8637     rLen -= 8 ;
8638     if (rLen <= 0 ) {
8639       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8640       break ;
8641     }
8642
8643     switch (p_type) {
8644       case POINTER:
8645         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8646         break;
8647
8648         /*
8649            case FPOINTER:
8650            MOVA(l);
8651            pic16_emitcode("movx","@dptr,a");
8652            break;
8653
8654            case GPOINTER:
8655            MOVA(l);
8656            DEBUGpic16_emitcode(";lcall","__gptrput");
8657            break;
8658          */
8659       default:
8660         assert(0);
8661     }
8662
8663
8664     pic16_mov2w(AOP(right), offset++);
8665   }
8666
8667   /* last last was not complete */
8668   if (rLen)   {
8669     /* save the byte & read byte */
8670     switch (p_type) {
8671       case POINTER:
8672         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8673         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8674         break;
8675
8676         /*
8677            case FPOINTER:
8678            pic16_emitcode ("mov","b,a");
8679            pic16_emitcode("movx","a,@dptr");
8680            break;
8681
8682            case GPOINTER:
8683            pic16_emitcode ("push","b");
8684            pic16_emitcode ("push","acc");
8685            pic16_emitcode ("lcall","__gptrget");
8686            pic16_emitcode ("pop","b");
8687            break;
8688          */
8689       default:
8690         assert(0);
8691     }
8692     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8693     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8694     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8695     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8696     //        pic16_emitcode ("orl","a,b");
8697   }
8698
8699   //    if (p_type == GPOINTER)
8700   //        pic16_emitcode("pop","b");
8701
8702   switch (p_type) {
8703
8704     case POINTER:
8705       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8706       //        pic16_emitcode("mov","@%s,a",rname);
8707       break;
8708       /*
8709          case FPOINTER:
8710          pic16_emitcode("movx","@dptr,a");
8711          break;
8712
8713          case GPOINTER:
8714          DEBUGpic16_emitcode(";lcall","__gptrput");
8715          break;
8716        */
8717     default:
8718       assert(0);
8719   }
8720
8721   //    pic16_freeAsmop(right, NULL, ic, TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genDataPointerSet - remat pointer to data space                 */
8726 /*-----------------------------------------------------------------*/
8727 static void genDataPointerSet(operand *right,
8728                               operand *result,
8729                               iCode *ic)
8730 {
8731   int size, offset = 0, resoffset=0 ;
8732
8733     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8734     pic16_aopOp(right,ic,FALSE);
8735
8736     size = AOP_SIZE(right);
8737
8738 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8739
8740 #if 0
8741     if ( AOP_TYPE(result) == AOP_PCODE) {
8742       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8743               AOP(result)->aopu.pcop->name,
8744                 (AOP(result)->aopu.pcop->type == PO_DIR)?
8745               PCOR(AOP(result)->aopu.pcop)->instance:
8746               PCOI(AOP(result)->aopu.pcop)->offset);
8747     }
8748 #endif
8749
8750     if(AOP(result)->aopu.pcop->type == PO_DIR)
8751       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8752
8753     while (size--) {
8754       if (AOP_TYPE(right) == AOP_LIT) {
8755         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8756         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8757       } else {
8758         pic16_mov2w(AOP(right), offset);
8759         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8760       }
8761       offset++;
8762       resoffset++;
8763     }
8764
8765     pic16_freeAsmop(right,NULL,ic,TRUE);
8766 }
8767
8768
8769
8770 /*-----------------------------------------------------------------*/
8771 /* genNearPointerSet - pic16_emitcode for near pointer put         */
8772 /*-----------------------------------------------------------------*/
8773 static void genNearPointerSet (operand *right,
8774                                operand *result,
8775                                iCode *ic)
8776 {
8777   asmop *aop = NULL;
8778   sym_link *retype;
8779   sym_link *ptype = operandType(result);
8780   sym_link *resetype;
8781
8782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8783     retype= getSpec(operandType(right));
8784     resetype = getSpec(operandType(result));
8785
8786     pic16_aopOp(result,ic,FALSE);
8787
8788     /* if the result is rematerializable &
8789      * in data space & not a bit variable */
8790
8791     /* and result is not a bit variable */
8792     if (AOP_TYPE(result) == AOP_PCODE
8793       && DCL_TYPE(ptype) == POINTER
8794       && !IS_BITFIELD(retype)
8795       && !IS_BITFIELD(resetype)) {
8796
8797         genDataPointerSet (right,result,ic);
8798         pic16_freeAsmop(result,NULL,ic,TRUE);
8799       return;
8800     }
8801
8802     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8803     pic16_aopOp(right,ic,FALSE);
8804     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8805
8806     /* if bitfield then unpack the bits */
8807     if (IS_BITFIELD(resetype)) {
8808       genPackBits (resetype, result, right, NULL, POINTER);
8809     } else {
8810       /* we have can just get the values */
8811       int size = AOP_SIZE(right);
8812       int offset = 0 ;
8813
8814         pic16_loadFSR0(result, 0);
8815
8816         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8817         while (size--) {
8818           if (pic16_isLitOp(right)) {
8819             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8820             if (size) {
8821               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8822             } else {
8823               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8824             }
8825           } else { // no literal
8826             if(size) {
8827               pic16_emitpcode(POC_MOVFF,
8828                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8829                   pic16_popCopyReg(&pic16_pc_postinc0)));
8830             } else {
8831               pic16_emitpcode(POC_MOVFF,
8832                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8833                   pic16_popCopyReg(&pic16_pc_indf0)));
8834             }
8835           }
8836
8837           offset++;
8838         }
8839     }
8840
8841     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8842     /* now some housekeeping stuff */
8843     if (aop) {
8844       /* we had to allocate for this iCode */
8845       pic16_freeAsmop(NULL,aop,ic,TRUE);
8846     } else {
8847       /* we did not allocate which means left
8848        * already in a pointer register, then
8849        * if size > 0 && this could be used again
8850        * we have to point it back to where it
8851        * belongs */
8852       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8853       if (AOP_SIZE(right) > 1
8854         && !OP_SYMBOL(result)->remat
8855         && ( OP_SYMBOL(result)->liveTo > ic->seq
8856         || ic->depth )) {
8857
8858           int size = AOP_SIZE(right) - 1;
8859
8860             while (size--)
8861               pic16_emitcode("decf","fsr0,f");
8862               //pic16_emitcode("dec","%s",rname);
8863       }
8864     }
8865
8866     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8867     /* done */
8868 //release:
8869     pic16_freeAsmop(right,NULL,ic,TRUE);
8870     pic16_freeAsmop(result,NULL,ic,TRUE);
8871 }
8872
8873 /*-----------------------------------------------------------------*/
8874 /* genGenPointerSet - set value from generic pointer space         */
8875 /*-----------------------------------------------------------------*/
8876 static void genGenPointerSet (operand *right,
8877                               operand *result, iCode *ic)
8878 {
8879   int size;
8880   sym_link *retype = getSpec(operandType(result));
8881
8882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8883
8884     pic16_aopOp(result,ic,FALSE);
8885     pic16_aopOp(right,ic,FALSE);
8886     size = AOP_SIZE(right);
8887
8888     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8889
8890
8891     /* if bit then unpack */
8892     if (IS_BITFIELD(retype)) {
8893 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8894       genPackBits(retype,result,right,"dptr",GPOINTER);
8895       goto release;
8896     }
8897
8898     size = AOP_SIZE(right);
8899
8900     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8901
8902
8903     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8904
8905     /* value of right+0 is placed on stack, which will be retrieved
8906      * by the support function thus restoring the stack. The important
8907      * thing is that there is no need to manually restore stack pointer
8908      * here */
8909     pushaop(AOP(right), 0);
8910 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8911     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8912     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8913     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8914
8915     /* load address to write to in WREG:FSR0H:FSR0L */
8916     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8917                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
8918     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8919                                 pic16_popCopyReg(&pic16_pc_prodl)));
8920     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8921
8922     pic16_callGenericPointerRW(1, size);
8923
8924 release:
8925     pic16_freeAsmop(right,NULL,ic,TRUE);
8926     pic16_freeAsmop(result,NULL,ic,TRUE);
8927 }
8928
8929 /*-----------------------------------------------------------------*/
8930 /* genPointerSet - stores the value into a pointer location        */
8931 /*-----------------------------------------------------------------*/
8932 static void genPointerSet (iCode *ic)
8933 {
8934   operand *right, *result ;
8935   sym_link *type, *etype;
8936   int p_type;
8937
8938     FENTRY;
8939
8940     right = IC_RIGHT(ic);
8941     result = IC_RESULT(ic) ;
8942
8943     /* depending on the type of pointer we need to
8944     move it to the correct pointer register */
8945     type = operandType(result);
8946     etype = getSpec(type);
8947
8948     /* if left is of type of pointer then it is simple */
8949     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8950         p_type = DCL_TYPE(type);
8951     }
8952     else {
8953         /* we have to go by the storage class */
8954         p_type = PTR_TYPE(SPEC_OCLS(etype));
8955
8956 /*      if (SPEC_OCLS(etype)->codesp ) { */
8957 /*          p_type = CPOINTER ;  */
8958 /*      } */
8959 /*      else */
8960 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8961 /*              p_type = FPOINTER ; */
8962 /*          else */
8963 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8964 /*                  p_type = PPOINTER ; */
8965 /*              else */
8966 /*                  if (SPEC_OCLS(etype) == idata ) */
8967 /*                      p_type = IPOINTER ; */
8968 /*                  else */
8969 /*                      p_type = POINTER ; */
8970     }
8971
8972     /* now that we have the pointer type we assign
8973     the pointer values */
8974     switch (p_type) {
8975       case POINTER:
8976       case FPOINTER:
8977       case IPOINTER:
8978         genNearPointerSet (right,result,ic);
8979         break;
8980
8981 #if 0
8982       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8983       case PPOINTER:
8984         genPagedPointerSet (right,result,ic);
8985         break;
8986
8987       case FPOINTER:
8988         genFarPointerSet (right,result,ic);
8989         break;
8990 #endif
8991
8992       case GPOINTER:
8993         genGenPointerSet (right,result,ic);
8994         break;
8995
8996       default:
8997         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8998           "genPointerSet: illegal pointer type");
8999     }
9000 }
9001
9002 /*-----------------------------------------------------------------*/
9003 /* genIfx - generate code for Ifx statement                        */
9004 /*-----------------------------------------------------------------*/
9005 static void genIfx (iCode *ic, iCode *popIc)
9006 {
9007   operand *cond = IC_COND(ic);
9008   int isbit =0;
9009
9010     FENTRY;
9011
9012     pic16_aopOp(cond,ic,FALSE);
9013
9014     /* get the value into acc */
9015     if (AOP_TYPE(cond) != AOP_CRY)
9016       pic16_toBoolean(cond);
9017     else
9018       isbit = 1;
9019     /* the result is now in the accumulator */
9020     pic16_freeAsmop(cond,NULL,ic,TRUE);
9021
9022     /* if there was something to be popped then do it */
9023     if (popIc)
9024       genIpop(popIc);
9025
9026     /* if the condition is  a bit variable */
9027     if (isbit && IS_ITEMP(cond) &&
9028         SPIL_LOC(cond)) {
9029       genIfxJump(ic,"c");
9030       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9031     } else {
9032       if (isbit && !IS_ITEMP(cond))
9033         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9034         else
9035         genIfxJump(ic,"a");
9036     }
9037     ic->generated = 1;
9038 }
9039
9040 /*-----------------------------------------------------------------*/
9041 /* genAddrOf - generates code for address of                       */
9042 /*-----------------------------------------------------------------*/
9043 static void genAddrOf (iCode *ic)
9044 {
9045   operand *result, *left;
9046   int size;
9047   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9048   pCodeOp *pcop0, *pcop1, *pcop2;
9049
9050     FENTRY;
9051
9052     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9053
9054     sym = OP_SYMBOL( IC_LEFT(ic) );
9055
9056     if(sym->onStack) {
9057       /* get address of symbol on stack */
9058       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9059 #if 0
9060       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9061                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9062 #endif
9063
9064       // operands on stack are accessible via "FSR2 + index" with index
9065       // starting at 2 for arguments and growing from 0 downwards for
9066       // local variables (index == 0 is not assigned so we add one here)
9067       {
9068         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9069
9070           if (soffs <= 0) {
9071             assert (soffs < 0);
9072             soffs++;
9073           } // if
9074
9075           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9076           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9077           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9078           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9079           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9080           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9081           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9082       }
9083
9084       goto release;
9085     }
9086
9087 //      if(pic16_debug_verbose) {
9088 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9089 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9090 //      }
9091
9092     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9093     size = AOP_SIZE(IC_RESULT(ic));
9094
9095     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9096     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9097     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9098
9099     if (size == 3) {
9100       pic16_emitpcode(POC_MOVLW, pcop0);
9101       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9102       pic16_emitpcode(POC_MOVLW, pcop1);
9103       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9104       pic16_emitpcode(POC_MOVLW, pcop2);
9105       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9106     } else
9107     if (size == 2) {
9108       pic16_emitpcode(POC_MOVLW, pcop0);
9109       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9110       pic16_emitpcode(POC_MOVLW, pcop1);
9111     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9112     } else {
9113       pic16_emitpcode(POC_MOVLW, pcop0);
9114       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9115     }
9116
9117     pic16_freeAsmop(left, NULL, ic, FALSE);
9118 release:
9119     pic16_freeAsmop(result,NULL,ic,TRUE);
9120 }
9121
9122
9123 /*-----------------------------------------------------------------*/
9124 /* genAssign - generate code for assignment                        */
9125 /*-----------------------------------------------------------------*/
9126 static void genAssign (iCode *ic)
9127 {
9128   operand *result, *right;
9129   sym_link *restype, *rtype;
9130   int size, offset,know_W;
9131   unsigned long lit = 0L;
9132
9133     result = IC_RESULT(ic);
9134     right  = IC_RIGHT(ic) ;
9135
9136     FENTRY;
9137
9138     /* if they are the same */
9139     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9140       return ;
9141
9142     /* reversed order operands are aopOp'ed so that result operand
9143      * is effective in case right is a stack symbol. This maneauver
9144      * allows to use the _G.resDirect flag later */
9145      pic16_aopOp(result,ic,TRUE);
9146     pic16_aopOp(right,ic,FALSE);
9147
9148     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9149
9150     /* if they are the same registers */
9151     if (pic16_sameRegs(AOP(right),AOP(result)))
9152       goto release;
9153
9154     /* if the result is a bit */
9155     if (AOP_TYPE(result) == AOP_CRY) {
9156       /* if the right size is a literal then
9157          we know what the value is */
9158       if (AOP_TYPE(right) == AOP_LIT) {
9159
9160         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9161             pic16_popGet(AOP(result),0));
9162
9163         if (((int) operandLitValue(right)))
9164           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9165               AOP(result)->aopu.aop_dir,
9166               AOP(result)->aopu.aop_dir);
9167         else
9168           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9169               AOP(result)->aopu.aop_dir,
9170               AOP(result)->aopu.aop_dir);
9171
9172         goto release;
9173       }
9174
9175       /* the right is also a bit variable */
9176       if (AOP_TYPE(right) == AOP_CRY) {
9177         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9178         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9179         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9180
9181         goto release ;
9182       }
9183
9184       /* we need to or */
9185       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9186       pic16_toBoolean(right);
9187       emitSKPZ;
9188       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9189       //pic16_aopPut(AOP(result),"a",0);
9190       goto release ;
9191     }
9192
9193     /* bit variables done */
9194     /* general case */
9195     size = AOP_SIZE(result);
9196     offset = 0 ;
9197
9198   /* bit variables done */
9199   /* general case */
9200   size = AOP_SIZE(result);
9201   restype = operandType(result);
9202   rtype = operandType(right);
9203   offset = 0 ;
9204
9205   if(AOP_TYPE(right) == AOP_LIT) {
9206     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9207     {
9208       lit = ulFromVal (AOP(right)->aopu.aop_lit);
9209
9210       /* patch tag for literals that are cast to pointers */
9211       if (IS_CODEPTR(restype)) {
9212         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9213         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9214       } else {
9215         if (IS_GENPTR(restype))
9216         {
9217           if (IS_CODEPTR(rtype)) {
9218             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9219             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9220           } else if (PIC_IS_DATA_PTR(rtype)) {
9221             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9222             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9223           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9224             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9225           } else if (IS_PTR(rtype)) {
9226             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9227             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9228           }
9229         }
9230       }
9231     } else {
9232       union {
9233         unsigned long lit_int;
9234         float lit_float;
9235       } info;
9236
9237
9238       if(IS_FIXED16X16(operandType(right))) {
9239         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9240       } else {
9241         /* take care if literal is a float */
9242         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9243         lit = info.lit_int;
9244       }
9245     }
9246   }
9247
9248 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9249 //                      sizeof(unsigned long int), sizeof(float));
9250
9251
9252     if (AOP_TYPE(right) == AOP_REG) {
9253       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9254       while (size--) {
9255         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9256       } // while
9257       goto release;
9258     }
9259
9260     /* when do we have to read the program memory?
9261      * - if right itself is a symbol in code space
9262      *   (we don't care what it points to if it's a pointer)
9263      * - AND right is not a function (we would want its address)
9264      */
9265     if(AOP_TYPE(right) != AOP_LIT
9266       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9267       && !IS_FUNC(OP_SYM_TYPE(right))
9268       && !IS_ITEMP(right)) {
9269
9270       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9271       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9272
9273       // set up table pointer
9274       if(pic16_isLitOp(right)) {
9275 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9276         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9277         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9278         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9279         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9280         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9281         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9282       } else {
9283 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9284         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9285             pic16_popCopyReg(&pic16_pc_tblptrl)));
9286         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9287             pic16_popCopyReg(&pic16_pc_tblptrh)));
9288         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9289             pic16_popCopyReg(&pic16_pc_tblptru)));
9290       }
9291
9292       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9293       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9294       while(size--) {
9295         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9296         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9297             pic16_popGet(AOP(result),offset)));
9298         offset++;
9299       }
9300
9301       /* FIXME: for pointers we need to extend differently (according
9302        * to pointer type DATA/CODE/EEPROM/... :*/
9303       size = getSize(OP_SYM_TYPE(right));
9304       if(AOP_SIZE(result) > size) {
9305         size = AOP_SIZE(result) - size;
9306         while(size--) {
9307           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9308           offset++;
9309         }
9310       }
9311       goto release;
9312     }
9313
9314 #if 0
9315     /* VR - What is this?! */
9316     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9317       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9318
9319       if(aopIdx(AOP(result),0) == 4) {
9320         /* this is a workaround to save value of right into wreg too,
9321          * value of wreg is going to be used later */
9322         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9323         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9324         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9325         goto release;
9326       } else
9327 //      assert(0);
9328       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9329     }
9330 #endif
9331
9332     size = AOP_SIZE(right);
9333     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9334     know_W=-1;
9335     while (size--) {
9336       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
9337       if(AOP_TYPE(right) == AOP_LIT) {
9338         if(lit&0xff) {
9339           if(know_W != (lit&0xff))
9340             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9341           know_W = lit&0xff;
9342           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9343         } else
9344           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9345
9346         lit >>= 8;
9347
9348       } else if (AOP_TYPE(right) == AOP_CRY) {
9349         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9350         if(offset == 0) {
9351           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9352           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9353           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9354         }
9355       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9356         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9357         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9358       } else {
9359         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9360
9361         if(!_G.resDirect) {                                             /* use this aopForSym feature */
9362           if(AOP_TYPE(result) == AOP_ACC) {
9363             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9364           } else
9365             if(AOP_TYPE(right) == AOP_ACC) {
9366               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9367             } else {
9368               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9369             }
9370         }
9371       }
9372
9373       offset++;
9374     }
9375     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9376
9377 release:
9378   pic16_freeAsmop (right,NULL,ic,FALSE);
9379   pic16_freeAsmop (result,NULL,ic,TRUE);
9380 }
9381
9382 /*-----------------------------------------------------------------*/
9383 /* genJumpTab - generates code for jump table                       */
9384 /*-----------------------------------------------------------------*/
9385 static void genJumpTab (iCode *ic)
9386 {
9387   symbol *jtab;
9388   char *l;
9389   pCodeOp *jt_offs;
9390   pCodeOp *jt_offs_hi;
9391   pCodeOp *jt_label;
9392
9393     FENTRY;
9394
9395     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9396     /* get the condition into accumulator */
9397     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9398     MOVA(l);
9399     /* multiply by three */
9400     pic16_emitcode("add","a,acc");
9401     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9402
9403     jtab = newiTempLabel(NULL);
9404     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9405     pic16_emitcode("jmp","@a+dptr");
9406     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9407
9408 #if 0
9409     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9410     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9411     emitSKPNC;
9412     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9413     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9414     pic16_emitpLabel(jtab->key);
9415
9416 #else
9417
9418     jt_offs = pic16_popGetTempReg(0);
9419     jt_offs_hi = pic16_popGetTempReg(1);
9420     jt_label = pic16_popGetLabel (jtab->key);
9421     //fprintf (stderr, "Creating jump table...\n");
9422
9423     // calculate offset into jump table (idx * sizeof (GOTO))
9424     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
9425     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9426     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9427     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9428     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9429     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9430     pic16_emitpcode(POC_MOVWF , jt_offs);
9431
9432     // prepare PCLATx (set to first entry in jump table)
9433     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9434     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9435     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9436     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9437     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9438
9439     // set PCLATx to selected entry (new PCL is stored in jt_offs)
9440     pic16_emitpcode(POC_ADDWF , jt_offs);
9441     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9442     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9443     emitSKPNC;
9444     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
9445
9446     // release temporaries and prepare jump into table (new PCL --> WREG)
9447     pic16_emitpcode(POC_MOVFW , jt_offs);
9448     pic16_popReleaseTempReg (jt_offs_hi, 1);
9449     pic16_popReleaseTempReg (jt_offs, 0);
9450
9451     // jump into the table
9452     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9453
9454     pic16_emitpLabelFORCE(jtab->key);
9455 #endif
9456
9457     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9458 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9459
9460     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9461     /* now generate the jump labels */
9462     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9463          jtab = setNextItem(IC_JTLABELS(ic))) {
9464 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9465         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9466
9467     }
9468     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9469
9470 }
9471
9472 /*-----------------------------------------------------------------*/
9473 /* genMixedOperation - gen code for operators between mixed types  */
9474 /*-----------------------------------------------------------------*/
9475 /*
9476   TSD - Written for the PIC port - but this unfortunately is buggy.
9477   This routine is good in that it is able to efficiently promote
9478   types to different (larger) sizes. Unfortunately, the temporary
9479   variables that are optimized out by this routine are sometimes
9480   used in other places. So until I know how to really parse the
9481   iCode tree, I'm going to not be using this routine :(.
9482 */
9483 static int genMixedOperation (iCode *ic)
9484 {
9485 #if 0
9486   operand *result = IC_RESULT(ic);
9487   sym_link *ctype = operandType(IC_LEFT(ic));
9488   operand *right = IC_RIGHT(ic);
9489   int ret = 0;
9490   int big,small;
9491   int offset;
9492
9493   iCode *nextic;
9494   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9495
9496   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9497
9498   nextic = ic->next;
9499   if(!nextic)
9500     return 0;
9501
9502   nextright = IC_RIGHT(nextic);
9503   nextleft  = IC_LEFT(nextic);
9504   nextresult = IC_RESULT(nextic);
9505
9506   pic16_aopOp(right,ic,FALSE);
9507   pic16_aopOp(result,ic,FALSE);
9508   pic16_aopOp(nextright,  nextic, FALSE);
9509   pic16_aopOp(nextleft,   nextic, FALSE);
9510   pic16_aopOp(nextresult, nextic, FALSE);
9511
9512   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9513
9514     operand *t = right;
9515     right = nextright;
9516     nextright = t;
9517
9518     pic16_emitcode(";remove right +","");
9519
9520   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9521 /*
9522     operand *t = right;
9523     right = nextleft;
9524     nextleft = t;
9525 */
9526     pic16_emitcode(";remove left +","");
9527   } else
9528     return 0;
9529
9530   big = AOP_SIZE(nextleft);
9531   small = AOP_SIZE(nextright);
9532
9533   switch(nextic->op) {
9534
9535   case '+':
9536     pic16_emitcode(";optimize a +","");
9537     /* if unsigned or not an integral type */
9538     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9539       pic16_emitcode(";add a bit to something","");
9540     } else {
9541
9542       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9543
9544       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9545         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9546         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9547       } else
9548         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9549
9550       offset = 0;
9551       while(--big) {
9552
9553         offset++;
9554
9555         if(--small) {
9556           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9557             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9558             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9559           }
9560
9561           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9562           emitSKPNC;
9563           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9564                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9565                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9566           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9567           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9568
9569         } else {
9570           pic16_emitcode("rlf","known_zero,w");
9571
9572           /*
9573             if right is signed
9574               btfsc  right,7
9575                addlw ff
9576           */
9577           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9578             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9579             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9580           } else {
9581             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9582           }
9583         }
9584       }
9585       ret = 1;
9586     }
9587   }
9588   ret = 1;
9589
9590 release:
9591   pic16_freeAsmop(right,NULL,ic,TRUE);
9592   pic16_freeAsmop(result,NULL,ic,TRUE);
9593   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9594   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9595   if(ret)
9596     nextic->generated = 1;
9597
9598   return ret;
9599 #else
9600   return 0;
9601 #endif
9602 }
9603 /*-----------------------------------------------------------------*/
9604 /* genCast - gen code for casting                                  */
9605 /*-----------------------------------------------------------------*/
9606 static void genCast (iCode *ic)
9607 {
9608   operand *result = IC_RESULT(ic);
9609   sym_link *ctype = operandType(IC_LEFT(ic));
9610   sym_link *rtype = operandType(IC_RIGHT(ic));
9611   sym_link *restype = operandType(IC_RESULT(ic));
9612   operand *right = IC_RIGHT(ic);
9613   int size, offset ;
9614
9615
9616     FENTRY;
9617
9618         /* if they are equivalent then do nothing */
9619 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9620 //              return ;
9621
9622         pic16_aopOp(result,ic,FALSE);
9623         pic16_aopOp(right,ic,FALSE) ;
9624
9625         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9626
9627
9628         /* if the result is a bit */
9629         if (AOP_TYPE(result) == AOP_CRY) {
9630
9631                 /* if the right size is a literal then
9632                  * we know what the value is */
9633                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9634
9635                 if (AOP_TYPE(right) == AOP_LIT) {
9636                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9637                                 pic16_popGet(AOP(result),0));
9638
9639                         if (((int) operandLitValue(right)))
9640                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9641                                         AOP(result)->aopu.aop_dir,
9642                                         AOP(result)->aopu.aop_dir);
9643                         else
9644                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9645                                         AOP(result)->aopu.aop_dir,
9646                                         AOP(result)->aopu.aop_dir);
9647                         goto release;
9648                 }
9649
9650                 /* the right is also a bit variable */
9651                 if (AOP_TYPE(right) == AOP_CRY) {
9652                         emitCLRC;
9653                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9654
9655                         pic16_emitcode("clrc","");
9656                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9657                                 AOP(right)->aopu.aop_dir,
9658                                 AOP(right)->aopu.aop_dir);
9659                         pic16_aopPut(AOP(result),"c",0);
9660                         goto release ;
9661                 }
9662
9663                 /* we need to or */
9664                 if (AOP_TYPE(right) == AOP_REG) {
9665                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9666                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9667                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9668                 }
9669                 pic16_toBoolean(right);
9670                 pic16_aopPut(AOP(result),"a",0);
9671                 goto release ;
9672         }
9673
9674         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9675           int offset = 1;
9676
9677                 size = AOP_SIZE(result);
9678
9679                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9680
9681                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9682                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9683                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9684
9685                 while (size--)
9686                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9687
9688                 goto release;
9689         }
9690
9691         if(IS_BITFIELD(getSpec(restype))
9692           && IS_BITFIELD(getSpec(rtype))) {
9693           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9694         }
9695
9696         /* port from pic14 to cope with generic pointers */
9697         if (PIC_IS_TAGGED(restype))
9698         {
9699           operand *result = IC_RESULT(ic);
9700           //operand *left = IC_LEFT(ic);
9701           operand *right = IC_RIGHT(ic);
9702           int tag = 0xff;
9703
9704           /* copy common part */
9705           int max, size = AOP_SIZE(result);
9706           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9707           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9708
9709           max = size;
9710           while (size--)
9711           {
9712             pic16_mov2w (AOP(right), size);
9713             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9714           } // while
9715
9716           /* upcast into generic pointer type? */
9717           if (IS_GENPTR(restype)
9718               && !PIC_IS_TAGGED(rtype)
9719               && (AOP_SIZE(result) > max))
9720           {
9721             /* determine appropriate tag for right */
9722             if (PIC_IS_DATA_PTR(rtype))
9723               tag = GPTR_TAG_DATA;
9724             else if (IS_CODEPTR(rtype))
9725               tag = GPTR_TAG_CODE;
9726             else if (PIC_IS_DATA_PTR(ctype)) {
9727               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9728               tag = GPTR_TAG_DATA;
9729             } else if (IS_CODEPTR(ctype)) {
9730               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9731               tag = GPTR_TAG_CODE;
9732             } else if (IS_PTR(rtype)) {
9733               PERFORM_ONCE(weirdcast,
9734               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9735               );
9736               tag = GPTR_TAG_DATA;
9737             } else {
9738               PERFORM_ONCE(weirdcast,
9739               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9740               );
9741               tag = GPTR_TAG_DATA;
9742             }
9743
9744             assert (AOP_SIZE(result) == 3);
9745             /* zero-extend address... */
9746             for (size = max; size < AOP_SIZE(result)-1; size++)
9747               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9748             /* ...and add tag */
9749             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9750           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9751             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9752             for (size = max; size < AOP_SIZE(result)-1; size++)
9753               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9754             /* add __code tag */
9755             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9756           } else if (AOP_SIZE(result) > max) {
9757             /* extend non-pointers */
9758             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9759             pic16_addSign(result, max, 0);
9760           } // if
9761           goto release;
9762         }
9763
9764         /* if they are the same size : or less */
9765         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9766
9767                 /* if they are in the same place */
9768                 if (pic16_sameRegs(AOP(right),AOP(result)))
9769                         goto release;
9770
9771                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9772 #if 0
9773                 if (IS_PTR_CONST(rtype))
9774 #else
9775                 if (IS_CODEPTR(rtype))
9776 #endif
9777                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9778
9779 #if 0
9780                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9781 #else
9782                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9783 #endif
9784                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9785
9786                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9787                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9788                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9789
9790                         if(AOP_SIZE(result) < 2) {
9791                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9792                         } else {
9793                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9794                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9795                         }
9796                 } else {
9797                         /* if they in different places then copy */
9798                         size = AOP_SIZE(result);
9799                         offset = 0 ;
9800                         while (size--) {
9801                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9802                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9803                                 offset++;
9804                         }
9805                 }
9806                 goto release;
9807         }
9808
9809         /* if the result is of type pointer */
9810         if (IS_PTR(ctype)) {
9811           int p_type;
9812           sym_link *type = operandType(right);
9813           sym_link *etype = getSpec(type);
9814
9815                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9816
9817                 /* pointer to generic pointer */
9818                 if (IS_GENPTR(ctype)) {
9819                   char *l = zero;
9820
9821                         if (IS_PTR(type))
9822                                 p_type = DCL_TYPE(type);
9823                         else {
9824                 /* we have to go by the storage class */
9825                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9826
9827 /*              if (SPEC_OCLS(etype)->codesp )  */
9828 /*                  p_type = CPOINTER ;  */
9829 /*              else */
9830 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9831 /*                      p_type = FPOINTER ; */
9832 /*                  else */
9833 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9834 /*                          p_type = PPOINTER; */
9835 /*                      else */
9836 /*                          if (SPEC_OCLS(etype) == idata ) */
9837 /*                              p_type = IPOINTER ; */
9838 /*                          else */
9839 /*                              p_type = POINTER ; */
9840             }
9841
9842             /* the first two bytes are known */
9843       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9844             size = GPTRSIZE - 1;
9845             offset = 0 ;
9846             while (size--) {
9847               if(offset < AOP_SIZE(right)) {
9848                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9849                 pic16_mov2f(AOP(result), AOP(right), offset);
9850 /*
9851                 if ((AOP_TYPE(right) == AOP_PCODE) &&
9852                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9853                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9854                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9855                 } else {
9856
9857                   pic16_aopPut(AOP(result),
9858                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9859                          offset);
9860                 }
9861 */
9862               } else
9863                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9864               offset++;
9865             }
9866             /* the last byte depending on type */
9867             switch (p_type) {
9868             case IPOINTER:
9869             case POINTER:
9870             case FPOINTER:
9871                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9872                 break;
9873
9874             case CPOINTER:
9875                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9876                 break;
9877
9878             case PPOINTER:
9879               pic16_emitcode(";BUG!? ","%d",__LINE__);
9880                 l = "#0x03";
9881                 break;
9882
9883             case GPOINTER:
9884                 if (GPTRSIZE > AOP_SIZE(right)) {
9885                   // assume __data pointer... THIS MIGHT BE WRONG!
9886                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9887                 } else {
9888                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9889                 }
9890               break;
9891
9892             default:
9893                 /* this should never happen */
9894                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9895                        "got unknown pointer type");
9896                 exit(1);
9897             }
9898             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9899             goto release ;
9900         }
9901
9902
9903         assert( 0 );
9904         /* just copy the pointers */
9905         size = AOP_SIZE(result);
9906         offset = 0 ;
9907         while (size--) {
9908             pic16_aopPut(AOP(result),
9909                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9910                    offset);
9911             offset++;
9912         }
9913         goto release ;
9914     }
9915
9916
9917
9918     /* so we now know that the size of destination is greater
9919     than the size of the source.
9920     Now, if the next iCode is an operator then we might be
9921     able to optimize the operation without performing a cast.
9922     */
9923     if(genMixedOperation(ic))
9924       goto release;
9925
9926     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9927
9928     /* we move to result for the size of source */
9929     size = AOP_SIZE(right);
9930     offset = 0 ;
9931
9932     while (size--) {
9933       if(!_G.resDirect)
9934         pic16_mov2f(AOP(result), AOP(right), offset);
9935       offset++;
9936     }
9937
9938     /* now depending on the sign of the destination */
9939     size = AOP_SIZE(result) - AOP_SIZE(right);
9940     /* if unsigned or not an integral type */
9941     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9942       while (size--)
9943         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9944     } else {
9945       /* we need to extend the sign :( */
9946
9947       if(size == 1) {
9948         /* Save one instruction of casting char to int */
9949         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9950         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9951         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
9952       } else {
9953         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9954
9955         if(offset)
9956           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9957         else
9958           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9959
9960         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9961
9962         while (size--)
9963           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9964       }
9965     }
9966
9967 release:
9968     pic16_freeAsmop(right,NULL,ic,TRUE);
9969     pic16_freeAsmop(result,NULL,ic,TRUE);
9970
9971 }
9972
9973 /*-----------------------------------------------------------------*/
9974 /* genDjnz - generate decrement & jump if not zero instrucion      */
9975 /*-----------------------------------------------------------------*/
9976 static int genDjnz (iCode *ic, iCode *ifx)
9977 {
9978     symbol *lbl, *lbl1;
9979     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9980
9981     if (!ifx)
9982         return 0;
9983
9984     /* if the if condition has a false label
9985        then we cannot save */
9986     if (IC_FALSE(ifx))
9987         return 0;
9988
9989     /* if the minus is not of the form
9990        a = a - 1 */
9991     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9992         !IS_OP_LITERAL(IC_RIGHT(ic)))
9993         return 0;
9994
9995     if (operandLitValue(IC_RIGHT(ic)) != 1)
9996         return 0;
9997
9998     /* if the size of this greater than one then no
9999        saving */
10000     if (getSize(operandType(IC_RESULT(ic))) > 1)
10001         return 0;
10002
10003     /* otherwise we can save BIG */
10004     lbl = newiTempLabel(NULL);
10005     lbl1= newiTempLabel(NULL);
10006
10007     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10008
10009     pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10010     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10011
10012     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10013     ifx->generated = 1;
10014     return 1;
10015 }
10016
10017 /*-----------------------------------------------------------------*/
10018 /* genReceive - generate code for a receive iCode                  */
10019 /*-----------------------------------------------------------------*/
10020 static void genReceive (iCode *ic)
10021 {
10022
10023   FENTRY;
10024
10025 #if 0
10026   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
10027         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
10028 #endif
10029 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
10030
10031   if (isOperandInFarSpace(IC_RESULT(ic))
10032       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
10033           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10034
10035     int size = getSize(operandType(IC_RESULT(ic)));
10036     int offset =  pic16_fReturnSizePic - size;
10037
10038       assert( 0 );
10039       while (size--) {
10040         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10041                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10042                       offset++;
10043         }
10044
10045       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10046
10047       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10048       size = AOP_SIZE(IC_RESULT(ic));
10049       offset = 0;
10050       while (size--) {
10051         pic16_emitcode ("pop","acc");
10052         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10053       }
10054   } else {
10055     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10056     _G.accInUse++;
10057     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10058     _G.accInUse--;
10059
10060     /* set pseudo stack pointer to where it should be - dw*/
10061     GpsuedoStkPtr = ic->parmBytes;
10062
10063     /* setting GpsuedoStkPtr has side effects here: */
10064     /* FIXME: What's the correct size of the return(ed) value?
10065      *        For now, assuming '4' as before... */
10066     assignResultValue(IC_RESULT(ic), 4, 0);
10067   }
10068
10069   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10070 }
10071
10072 /*-----------------------------------------------------------------*/
10073 /* genDummyRead - generate code for dummy read of volatiles        */
10074 /*-----------------------------------------------------------------*/
10075 static void
10076 genDummyRead (iCode * ic)
10077 {
10078   operand *op;
10079   int i;
10080
10081   op = IC_RIGHT(ic);
10082   if (op && IS_SYMOP(op)) {
10083     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10084       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10085       return;
10086     }
10087     pic16_aopOp (op, ic, FALSE);
10088     for (i=0; i < AOP_SIZE(op); i++) {
10089       // may need to protect this from the peepholer -- this is not nice but works...
10090       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
10091       pic16_mov2w (AOP(op),i);
10092       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
10093     } // for i
10094     pic16_freeAsmop (op, NULL, ic, TRUE);
10095   } else if (op) {
10096     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10097   } // if
10098 }
10099
10100 /*-----------------------------------------------------------------*/
10101 /* genpic16Code - generate code for pic16 based controllers        */
10102 /*-----------------------------------------------------------------*/
10103 /*
10104  * At this point, ralloc.c has gone through the iCode and attempted
10105  * to optimize in a way suitable for a PIC. Now we've got to generate
10106  * PIC instructions that correspond to the iCode.
10107  *
10108  * Once the instructions are generated, we'll pass through both the
10109  * peep hole optimizer and the pCode optimizer.
10110  *-----------------------------------------------------------------*/
10111
10112 void genpic16Code (iCode *lic)
10113 {
10114   iCode *ic;
10115   int cln = 0;
10116
10117     lineHead = lineCurr = NULL;
10118
10119     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10120     pic16_addpBlock(pb);
10121
10122 #if 0
10123     /* if debug information required */
10124     if (options.debug && currFunc) {
10125       if (currFunc) {
10126         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10127       }
10128     }
10129 #endif
10130
10131     for (ic = lic ; ic ; ic = ic->next ) {
10132
10133       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10134       if ( cln != ic->lineno ) {
10135         if ( options.debug ) {
10136           debugFile->writeCLine (ic);
10137         }
10138
10139         if(!options.noCcodeInAsm) {
10140           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10141               printCLine(ic->filename, ic->lineno)));
10142         }
10143
10144         cln = ic->lineno ;
10145       }
10146
10147       if(options.iCodeInAsm) {
10148         const char *iLine;
10149
10150         /* insert here code to print iCode as comment */
10151         iLine = printILine(ic);
10152         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10153         dbuf_free(iLine);
10154       }
10155
10156       /* if the result is marked as
10157        * spilt and rematerializable or code for
10158        * this has already been generated then
10159        * do nothing */
10160       if (resultRemat(ic) || ic->generated )
10161         continue ;
10162
10163       /* depending on the operation */
10164       switch (ic->op) {
10165         case '!' :
10166           pic16_genNot(ic);
10167           break;
10168
10169         case '~' :
10170           pic16_genCpl(ic);
10171           break;
10172
10173         case UNARYMINUS:
10174           genUminus (ic);
10175           break;
10176
10177         case IPUSH:
10178           genIpush (ic);
10179           break;
10180
10181         case IPOP:
10182           /* IPOP happens only when trying to restore a
10183            * spilt live range, if there is an ifx statement
10184            * following this pop then the if statement might
10185            * be using some of the registers being popped which
10186            * would destroy the contents of the register so
10187            * we need to check for this condition and handle it */
10188            if (ic->next
10189              && ic->next->op == IFX
10190              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10191                genIfx (ic->next,ic);
10192           else
10193             genIpop (ic);
10194           break;
10195
10196         case CALL:
10197           genCall (ic);
10198           break;
10199
10200         case PCALL:
10201           genPcall (ic);
10202           break;
10203
10204         case FUNCTION:
10205           genFunction (ic);
10206           break;
10207
10208         case ENDFUNCTION:
10209           genEndFunction (ic);
10210           break;
10211
10212         case RETURN:
10213           genRet (ic);
10214           break;
10215
10216         case LABEL:
10217           genLabel (ic);
10218           break;
10219
10220         case GOTO:
10221           genGoto (ic);
10222           break;
10223
10224         case '+' :
10225           pic16_genPlus (ic) ;
10226           break;
10227
10228         case '-' :
10229           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10230             pic16_genMinus (ic);
10231           break;
10232
10233         case '*' :
10234           genMult (ic);
10235           break;
10236
10237         case '/' :
10238           genDiv (ic) ;
10239           break;
10240
10241         case '%' :
10242           genMod (ic);
10243           break;
10244
10245         case '>' :
10246           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10247           break;
10248
10249         case '<' :
10250           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10251           break;
10252
10253         case LE_OP:
10254         case GE_OP:
10255         case NE_OP:
10256           /* note these two are xlated by algebraic equivalence
10257            * during parsing SDCC.y */
10258           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10259             "got '>=' or '<=' shouldn't have come here");
10260           break;
10261
10262         case EQ_OP:
10263           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10264           break;
10265
10266         case AND_OP:
10267           genAndOp (ic);
10268           break;
10269
10270         case OR_OP:
10271           genOrOp (ic);
10272           break;
10273
10274         case '^' :
10275           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10276           break;
10277
10278         case '|' :
10279           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10280           break;
10281
10282         case BITWISEAND:
10283           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10284           break;
10285
10286         case INLINEASM:
10287           genInline (ic);
10288           break;
10289
10290         case RRC:
10291           genRRC (ic);
10292           break;
10293
10294         case RLC:
10295           genRLC (ic);
10296           break;
10297
10298         case GETHBIT:
10299           genGetHbit (ic);
10300           break;
10301
10302         case LEFT_OP:
10303           genLeftShift (ic);
10304           break;
10305
10306         case RIGHT_OP:
10307           genRightShift (ic);
10308           break;
10309
10310         case GET_VALUE_AT_ADDRESS:
10311           genPointerGet(ic);
10312           break;
10313
10314         case '=' :
10315           if (POINTER_SET(ic))
10316             genPointerSet(ic);
10317           else
10318             genAssign(ic);
10319           break;
10320
10321         case IFX:
10322           genIfx (ic,NULL);
10323           break;
10324
10325         case ADDRESS_OF:
10326           genAddrOf (ic);
10327           break;
10328
10329         case JUMPTABLE:
10330           genJumpTab (ic);
10331           break;
10332
10333         case CAST:
10334           genCast (ic);
10335           break;
10336
10337         case RECEIVE:
10338           genReceive(ic);
10339           break;
10340
10341         case SEND:
10342           addSet(&_G.sendSet,ic);
10343           break;
10344
10345         case DUMMY_READ_VOLATILE:
10346           genDummyRead (ic);
10347           break;
10348
10349         default :
10350           ic = ic;
10351       }
10352     }
10353
10354
10355     /* now we are ready to call the
10356        peep hole optimizer */
10357     if (!options.nopeep)
10358       peepHole (&lineHead);
10359
10360     /* now do the actual printing */
10361     printLine (lineHead, codeOutBuf);
10362
10363 #ifdef PCODE_DEBUG
10364     DFPRINTF((stderr,"printing pBlock\n\n"));
10365     pic16_printpBlock(stdout,pb);
10366 #endif
10367
10368     return;
10369 }