* applied patch from bug-report #1076292,
[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@otenet.gr (2003,2004)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static void mov2f(asmop *dst, asmop *src, int offset);
62 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
63 static pCodeOp *pic16_popRegFromIdx(int rIdx);
64
65 //static int aopIdx (asmop *aop, int offset);
66
67 int pic16_labelOffset=0;
68 extern int pic16_debug_verbose;
69 static int optimized_for_speed = 0;
70 /*
71   hack hack
72
73 */
74
75 extern set *externs;
76
77 /* max_key keeps track of the largest label number used in 
78    a function. This is then used to adjust the label offset
79    for the next function.
80 */
81 static int max_key=0;
82 static int GpsuedoStkPtr=0;
83
84 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
85
86 unsigned int pic16aopLiteral (value *val, int offset);
87 const char *pic16_AopType(short type);
88 static iCode *ifxForOp ( operand *op, iCode *ic );
89
90 void pic16_pushpCodeOp(pCodeOp *pcop);
91 void pic16_poppCodeOp(pCodeOp *pcop);
92
93 static bool is_LitOp(operand *op);
94 static bool is_LitAOp(asmop *aop);
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
109 static char *zero = "#0x00";
110 static char *one  = "#0x01";
111 //static char *spname = "sp";
112
113
114 /*
115  * Function return value policy (MSB-->LSB):
116  *  8 bits      -> WREG
117  * 16 bits      -> PRODL:WREG
118  * 24 bits      -> PRODH:PRODL:WREG
119  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
120  * >32 bits     -> on stack, and FSR0 points to the beginning
121  *
122  */
123  
124
125 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
126 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
127 static char **fReturn = fReturnpic16;
128
129 static char *accUse[] = {"WREG"};
130
131 //static short rbank = -1;
132
133 static struct {
134     short r0Pushed;
135     short r1Pushed;
136     short fsr0Pushed;
137     short accInUse;
138     short inLine;
139     short debugLine;
140     short nRegsSaved;
141     short ipushRegs;
142     set *sendSet;
143     set *stackRegSet;
144     int interruptvector;
145     int usefastretfie;
146     bitVect *fregsUsed;
147     int stack_lat;                      /* stack offset latency */
148     int resDirect;
149     int useWreg;                        /* flag when WREG is used to pass function parameter */
150 } _G;
151
152 /* Resolved ifx structure. This structure stores information
153    about an iCode ifx that makes it easier to generate code.
154 */
155 typedef struct resolvedIfx {
156   symbol *lbl;     /* pointer to a label */
157   int condition;   /* true or false ifx */
158   int generated;   /* set true when the code associated with the ifx
159                     * is generated */
160 } resolvedIfx;
161
162 extern int pic16_ptrRegReq ;
163 extern int pic16_nRegs;
164 extern FILE *codeOutFile;
165 //static void saverbank (int, iCode *,bool);
166
167 static lineNode *lineHead = NULL;
168 static lineNode *lineCurr = NULL;
169
170 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
171 0xE0, 0xC0, 0x80, 0x00};
172 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
173 0x07, 0x03, 0x01, 0x00};
174
175 static  pBlock *pb;
176
177 /*-----------------------------------------------------------------*/
178 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
179 /*                 exponent of 2 is returned, otherwise -1 is      */
180 /*                 returned.                                       */
181 /* note that this is similar to the function `powof2' in SDCCsymt  */
182 /* if(n == 2^y)                                                    */
183 /*   return y;                                                     */
184 /* return -1;                                                      */
185 /*-----------------------------------------------------------------*/
186 int pic16_my_powof2 (unsigned long num)
187 {
188   if(num) {
189     if( (num & (num-1)) == 0) {
190       int nshifts = -1;
191       while(num) {
192         num>>=1;
193         nshifts++;
194       }
195       return nshifts;
196     }
197   }
198
199   return -1;
200 }
201
202 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
203 {
204   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
205                        line_no,
206                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
207                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
208                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
209                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
210                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
211                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
212                        ((result) ? AOP_SIZE(result) : 0));
213 }
214
215 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
216 {
217
218   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
219                        line_no,
220                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
221                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
222                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
223                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
224                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
225                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
226
227 }
228
229 void pic16_emitpcomment (char *fmt, ...)
230 {
231     va_list ap;
232     char lb[INITIAL_INLINEASM];  
233     char *lbp = lb;
234
235     va_start(ap,fmt);   
236
237     lb[0] = ';';
238     vsprintf(lb+1,fmt,ap);
239
240     while (isspace(*lbp)) lbp++;
241
242     if (lbp && *lbp) 
243         lineCurr = (lineCurr ?
244                     connectLine(lineCurr,newLineNode(lb)) :
245                     (lineHead = newLineNode(lb)));
246     lineCurr->isInline = _G.inLine;
247     lineCurr->isDebug  = _G.debugLine;
248
249     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
250     va_end(ap);
251
252 //      fprintf(stderr, "%s\n", lb);
253 }
254
255 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
256 {
257     va_list ap;
258     char lb[INITIAL_INLINEASM];  
259     char *lbp = lb;
260
261     if(!pic16_debug_verbose)
262       return;
263
264     va_start(ap,fmt);   
265
266     if (inst && *inst) {
267         if (fmt && *fmt)
268             sprintf(lb,"%s\t",inst);
269         else
270             sprintf(lb,"%s",inst);
271         vsprintf(lb+(strlen(lb)),fmt,ap);
272     }  else
273         vsprintf(lb,fmt,ap);
274
275     while (isspace(*lbp)) lbp++;
276
277     if (lbp && *lbp) 
278         lineCurr = (lineCurr ?
279                     connectLine(lineCurr,newLineNode(lb)) :
280                     (lineHead = newLineNode(lb)));
281     lineCurr->isInline = _G.inLine;
282     lineCurr->isDebug  = _G.debugLine;
283
284     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
285     va_end(ap);
286
287 //      fprintf(stderr, "%s\n", lb);
288 }
289
290
291
292 void pic16_emitpLabel(int key)
293 {
294   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
295 }
296
297 void pic16_emitpLabelFORCE(int key)
298 {
299   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
300 }
301
302 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
303 {
304
305   if(pcop)
306     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
307   else
308     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
309 }
310
311 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
312 {
313   if(pcop)
314     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
315   else
316     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
317 }
318   
319 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
320 {
321
322   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
323
324 }
325
326
327 #if 1
328 #define pic16_emitcode  DEBUGpic16_emitcode
329 #else
330 /*-----------------------------------------------------------------*/
331 /* pic16_emitcode - writes the code into a file : for now it is simple    */
332 /*-----------------------------------------------------------------*/
333 void pic16_emitcode (char *inst,char *fmt, ...)
334 {
335     va_list ap;
336     char lb[INITIAL_INLINEASM];  
337     char *lbp = lb;
338
339     va_start(ap,fmt);   
340
341     if (inst && *inst) {
342         if (fmt && *fmt)
343             sprintf(lb,"%s\t",inst);
344         else
345             sprintf(lb,"%s",inst);
346         vsprintf(lb+(strlen(lb)),fmt,ap);
347     }  else
348         vsprintf(lb,fmt,ap);
349
350     while (isspace(*lbp)) lbp++;
351
352     if (lbp && *lbp) 
353         lineCurr = (lineCurr ?
354                     connectLine(lineCurr,newLineNode(lb)) :
355                     (lineHead = newLineNode(lb)));
356     lineCurr->isInline = _G.inLine;
357     lineCurr->isDebug  = _G.debugLine;
358
359 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
360
361 //    if(pic16_debug_verbose)
362 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
363
364     va_end(ap);
365 }
366 #endif
367
368
369 /*-----------------------------------------------------------------*/
370 /* pic16_emitDebuggerSymbol - associate the current code location  */
371 /*   with a debugger symbol                                        */
372 /*-----------------------------------------------------------------*/
373 void
374 pic16_emitDebuggerSymbol (char * debugSym)
375 {
376   _G.debugLine = 1;
377   pic16_emitcode (";", "%s ==.", debugSym);
378   _G.debugLine = 0;
379 }
380
381
382 /*-----------------------------------------------------------------*/
383 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
384 /*-----------------------------------------------------------------*/
385 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
386 {
387 //    bool r0iu = FALSE , r1iu = FALSE;
388 //    bool r0ou = FALSE , r1ou = FALSE;
389     bool fsr0iu = FALSE, fsr0ou;
390     bool fsr2iu = FALSE, fsr2ou;
391     
392     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
393
394     
395     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
396     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
397     
398     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
399     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
400
401     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
402         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
403         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
404     }
405
406     if(!fsr0iu && !fsr0ou) {
407         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
408         (*aopp)->type = AOP_FSR0;
409
410         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
411         
412       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
413     }
414
415 #if 0
416     /* no usage of FSR2 */
417     if(!fsr2iu && !fsr2ou) {
418         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
419         (*aopp)->type = AOP_FSR2;
420
421       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
422     }
423 #endif
424         
425     /* now we know they both have usage */
426     /* if fsr0 not used in this instruction */
427     if (!fsr0iu) {
428         if (!_G.fsr0Pushed) {
429                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
430                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
431                 _G.fsr0Pushed++;
432         }
433
434         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
435         (*aopp)->type = AOP_FSR0;
436
437 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
438
439       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
440     }
441         
442
443     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
444     assert( 0 );
445
446     return NULL;
447 #if 0
448     /* the logic: if r0 & r1 used in the instruction
449     then we are in trouble otherwise */
450
451     /* first check if r0 & r1 are used by this
452     instruction, in which case we are in trouble */
453     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
454         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
455     {
456         goto endOfWorld;      
457     }
458
459     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
460     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
461
462     /* if no usage of r0 then return it */
463     if (!r0iu && !r0ou) {
464         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
465         (*aopp)->type = AOP_R0; 
466         
467         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
468     }
469
470     /* if no usage of r1 then return it */
471     if (!r1iu && !r1ou) {
472         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
473         (*aopp)->type = AOP_R1;
474
475         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
476     }    
477
478     /* now we know they both have usage */
479     /* if r0 not used in this instruction */
480     if (!r0iu) {
481         /* push it if not already pushed */
482         if (!_G.r0Pushed) {
483           //pic16_emitcode ("push","%s",
484           //          pic16_regWithIdx(R0_IDX)->dname);
485             _G.r0Pushed++ ;
486         }
487         
488         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
489         (*aopp)->type = AOP_R0;
490
491         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
492     }
493
494     /* if r1 not used then */
495
496     if (!r1iu) {
497         /* push it if not already pushed */
498         if (!_G.r1Pushed) {
499           //pic16_emitcode ("push","%s",
500           //          pic16_regWithIdx(R1_IDX)->dname);
501             _G.r1Pushed++ ;
502         }
503         
504         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
505         (*aopp)->type = AOP_R1;
506         return pic16_regWithIdx(R1_IDX);
507     }
508
509 endOfWorld :
510     /* I said end of world but not quite end of world yet */
511     /* if this is a result then we can push it on the stack*/
512     if (result) {
513         (*aopp)->type = AOP_STK;    
514         return NULL;
515     }
516
517     /* other wise this is true end of the world */
518     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
519            "getFreePtr should never reach here");
520     exit(0);
521 #endif
522 }
523
524 /*-----------------------------------------------------------------*/
525 /* newAsmop - creates a new asmOp                                  */
526 /*-----------------------------------------------------------------*/
527 static asmop *newAsmop (short type)
528 {
529     asmop *aop;
530
531     aop = Safe_calloc(1,sizeof(asmop));
532     aop->type = type;
533     return aop;
534 }
535
536 static void genSetDPTR(int n)
537 {
538     if (!n)
539     {
540         pic16_emitcode(";", "Select standard DPTR");
541         pic16_emitcode("mov", "dps, #0x00");
542     }
543     else
544     {
545         pic16_emitcode(";", "Select alternate DPTR");
546         pic16_emitcode("mov", "dps, #0x01");
547     }
548 }
549
550 /*-----------------------------------------------------------------*/
551 /* resolveIfx - converts an iCode ifx into a form more useful for  */
552 /*              generating code                                    */
553 /*-----------------------------------------------------------------*/
554 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
555 {
556   FENTRY2;
557   
558 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
559
560   if(!resIfx) 
561     return;
562
563
564   resIfx->condition = 1;    /* assume that the ifx is true */
565   resIfx->generated = 0;    /* indicate that the ifx has not been used */
566
567   if(!ifx) {
568     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
569
570 #if 1
571     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
572                         __FUNCTION__,__LINE__,resIfx->lbl->key);
573 #endif
574
575   } else {
576     if(IC_TRUE(ifx)) {
577       resIfx->lbl = IC_TRUE(ifx);
578     } else {
579       resIfx->lbl = IC_FALSE(ifx);
580       resIfx->condition = 0;
581     }
582
583 #if 1
584     if(IC_TRUE(ifx)) 
585       DEBUGpic16_emitcode("; +++","ifx true is non-null");
586     else
587       DEBUGpic16_emitcode("; +++","ifx true is null");
588     if(IC_FALSE(ifx)) 
589       DEBUGpic16_emitcode("; +++","ifx false is non-null");
590     else
591       DEBUGpic16_emitcode("; +++","ifx false is null");
592 #endif
593   }
594
595   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
596
597 }
598 #if 0
599 /*-----------------------------------------------------------------*/
600 /* pointerCode - returns the code for a pointer type               */
601 /*-----------------------------------------------------------------*/
602 static int pointerCode (sym_link *etype)
603 {
604
605     return PTR_TYPE(SPEC_OCLS(etype));
606
607 }
608 #endif
609
610 /*-----------------------------------------------------------------*/
611 /* aopForSym - for a true symbol                                   */
612 /*-----------------------------------------------------------------*/
613 static asmop *aopForSym (iCode *ic, operand *op, bool result)
614 {
615     symbol *sym=OP_SYMBOL(op);
616     asmop *aop;
617     memmap *space= SPEC_OCLS(sym->etype);
618
619     FENTRY2;
620     
621     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
622     
623 //    sym = OP_SYMBOL(op);
624
625     /* if already has one */
626     if (sym->aop) {
627             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
628         return sym->aop;
629     }
630
631 #if 0
632     /* if symbol was initially placed onStack then we must re-place it
633      * to direct memory, since pic16 does not have a specific stack */
634     if(sym->onStack) {
635         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
636     }
637 #endif
638
639 #if 1
640     /* assign depending on the storage class */
641     /* if it is on the stack or indirectly addressable */
642     /* space we need to assign either r0 or r1 to it   */    
643     if (sym->onStack || sym->iaccess) {
644       pCodeOp *pcop[4];
645       int i;
646       
647         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
648                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
649         
650         /* acquire a temporary register -- it is saved in function */
651
652         sym->aop = aop = newAsmop(AOP_STA);
653         aop->aopu.stk.stk = sym->stack;
654         aop->size = getSize(sym->type);
655
656
657         DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__);
658         pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
659         if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
660           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
661           
662           for(i=0;i<aop->size;i++)
663             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
664             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
665         } else
666           for(i=0;i<aop->size;i++) {
667             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 );
668             _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx);
669           }
670
671
672 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
673
674 #if 1
675         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
676         
677         if(_G.accInUse) {
678                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
679         }
680         
681         for(i=0;i<aop->size;i++) {
682
683           /* initialise for stack access via frame pointer */
684           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack + i + _G.stack_lat));
685
686           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
687                           pic16_popCopyReg(&pic16_pc_plusw2), pcop[i]));
688         }
689         
690         if(_G.accInUse) {
691                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
692         }
693         
694         return (aop);
695 #endif
696
697 #if 0
698         /* now assign the address of the variable to 
699         the pointer register */
700         if (aop->type != AOP_STK) {
701
702             if (sym->onStack) {
703                     if ( _G.accInUse )
704                         pic16_emitcode("push","acc");
705
706                     pic16_emitcode("mov","a,_bp");
707                     pic16_emitcode("add","a,#0x%02x",
708                              ((sym->stack < 0) ?
709                               ((char)(sym->stack - _G.nRegsSaved )) :
710                               ((char)sym->stack)) & 0xff);
711                     pic16_emitcode("mov","%s,a",
712                              aop->aopu.aop_ptr->name);
713
714                     if ( _G.accInUse )
715                         pic16_emitcode("pop","acc");
716             } else
717                 pic16_emitcode("mov","%s,#%s",
718                          aop->aopu.aop_ptr->name,
719                          sym->rname);
720             aop->paged = space->paged;
721         } else
722             aop->aopu.aop_stk = sym->stack;
723         return aop;
724 #endif
725
726     }
727 #endif
728
729 #if 0
730     if (sym->onStack && options.stack10bit)
731     {
732         /* It's on the 10 bit stack, which is located in
733          * far data space.
734          */
735          
736       //DEBUGpic16_emitcode(";","%d",__LINE__);
737
738         if ( _G.accInUse )
739                 pic16_emitcode("push","acc");
740
741         pic16_emitcode("mov","a,_bp");
742         pic16_emitcode("add","a,#0x%02x",
743                  ((sym->stack < 0) ?
744                    ((char)(sym->stack - _G.nRegsSaved )) :
745                    ((char)sym->stack)) & 0xff);
746         
747         genSetDPTR(1);
748         pic16_emitcode ("mov","dpx1,#0x40");
749         pic16_emitcode ("mov","dph1,#0x00");
750         pic16_emitcode ("mov","dpl1, a");
751         genSetDPTR(0);
752         
753         if ( _G.accInUse )
754             pic16_emitcode("pop","acc");
755             
756         sym->aop = aop = newAsmop(AOP_DPTR2);
757         aop->size = getSize(sym->type); 
758         return aop;
759     }
760 #endif
761
762 #if 0
763     /* special case for a function */
764     if (IS_FUNC(sym->type)) {   
765         sym->aop = aop = newAsmop(AOP_PCODE);
766         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
767         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
768         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
769         PCOI(aop->aopu.pcop)->index = 0;
770         aop->size = FPTRSIZE; 
771         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
772         return aop;
773     }
774 #endif
775
776
777
778     //DEBUGpic16_emitcode(";","%d",__LINE__);
779     /* if in bit space */
780     if (IN_BITSPACE(space)) {
781         sym->aop = aop = newAsmop (AOP_CRY);
782         aop->aopu.aop_dir = sym->rname ;
783         aop->size = getSize(sym->type);
784         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
785         return aop;
786     }
787     /* if it is in direct space */
788     if (IN_DIRSPACE(space)) {
789         sym->aop = aop = newAsmop (AOP_DIR);
790         aop->aopu.aop_dir = sym->rname ;
791         aop->size = getSize(sym->type);
792         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
793         pic16_allocDirReg( IC_LEFT(ic) );
794         return aop;
795     }
796
797
798     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
799         sym->aop = aop = newAsmop (AOP_DIR);
800         aop->aopu.aop_dir = sym->rname ;
801         aop->size = getSize(sym->type);
802         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
803         pic16_allocDirReg( IC_LEFT(ic) );
804         return aop;
805     }
806
807
808     /* only remaining is far space */
809     sym->aop = aop = newAsmop(AOP_PCODE);
810
811 /* change the next if to 1 to revert to good old immediate code */
812         if(IN_CODESPACE(space)) {
813                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
814                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
815                 PCOI(aop->aopu.pcop)->index = 0;
816         } else {
817                 /* try to allocate via direct register */
818                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
819 //              aop->size = getSize( sym->type );
820         }
821
822         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
823                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
824
825 #if 0
826         if(!pic16_allocDirReg (IC_LEFT(ic)))
827                 return NULL;
828 #endif
829
830         if(IN_DIRSPACE( space ))
831                 aop->size = PTRSIZE;
832         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
833                 aop->size = FPTRSIZE;
834         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
835         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
836         else if(sym->onStack) {
837                 aop->size = PTRSIZE;
838         } else {
839                 assert( 0 );
840         }
841
842     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
843
844     /* if it is in code space */
845     if (IN_CODESPACE(space))
846         aop->code = 1;
847
848     return aop;     
849 }
850
851 /*-----------------------------------------------------------------*/
852 /* aopForRemat - rematerialzes an object                           */
853 /*-----------------------------------------------------------------*/
854 static asmop *aopForRemat (operand *op) // x symbol *sym)
855 {
856   symbol *sym = OP_SYMBOL(op);
857   operand *refop;
858   iCode *ic = NULL, *oldic;
859   asmop *aop = newAsmop(AOP_PCODE);
860   int val = 0;
861   int offset = 0;
862   int viaimmd=0;
863
864     FENTRY2;
865     
866         ic = sym->rematiCode;
867
868         if(IS_OP_POINTER(op)) {
869                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
870         }
871
872         for (;;) {
873                 oldic = ic;
874
875 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
876         
877                 if (ic->op == '+') {
878                         val += (int) operandLitValue(IC_RIGHT(ic));
879                 } else if (ic->op == '-') {
880                         val -= (int) operandLitValue(IC_RIGHT(ic));
881                 } else
882                         break;
883                 
884                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
885         }
886
887         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
888         refop = IC_LEFT(ic);
889
890         if(!op->isaddr)viaimmd++; else viaimmd=0;
891                 
892 /* set the following if to 1 to revert to good old immediate code */
893         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
894                 || viaimmd) {
895
896                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
897
898                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
899
900 #if 0
901                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
902 #else
903                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
904 #endif
905
906                 PCOI(aop->aopu.pcop)->index = val;
907                 
908                 aop->size = getSize( sym->type );
909         } else {
910                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
911
912                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
913                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
914
915                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
916         }
917
918
919         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
920                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
921 #if 0
922                 val, IS_PTR_CONST(operandType(op)));
923 #else
924                 val, IS_CODEPTR(operandType(op)));
925 #endif
926
927 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
928
929         pic16_allocDirReg (IC_LEFT(ic));
930
931         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
932                 aop->code = 1;
933
934   return aop;        
935 }
936
937 #if 0
938 static int aopIdx (asmop *aop, int offset)
939 {
940   if(!aop)
941     return -1;
942
943   if(aop->type !=  AOP_REG)
944     return -2;
945         
946   return aop->aopu.aop_reg[offset]->rIdx;
947
948 }
949 #endif
950
951 /*-----------------------------------------------------------------*/
952 /* regsInCommon - two operands have some registers in common       */
953 /*-----------------------------------------------------------------*/
954 static bool regsInCommon (operand *op1, operand *op2)
955 {
956     symbol *sym1, *sym2;
957     int i;
958
959     /* if they have registers in common */
960     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
961         return FALSE ;
962
963     sym1 = OP_SYMBOL(op1);
964     sym2 = OP_SYMBOL(op2);
965
966     if (sym1->nRegs == 0 || sym2->nRegs == 0)
967         return FALSE ;
968
969     for (i = 0 ; i < sym1->nRegs ; i++) {
970         int j;
971         if (!sym1->regs[i])
972             continue ;
973
974         for (j = 0 ; j < sym2->nRegs ;j++ ) {
975             if (!sym2->regs[j])
976                 continue ;
977
978             if (sym2->regs[j] == sym1->regs[i])
979                 return TRUE ;
980         }
981     }
982
983     return FALSE ;
984 }
985
986 /*-----------------------------------------------------------------*/
987 /* operandsEqu - equivalent                                        */
988 /*-----------------------------------------------------------------*/
989 static bool operandsEqu ( operand *op1, operand *op2)
990 {
991     symbol *sym1, *sym2;
992
993     /* if they not symbols */
994     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
995         return FALSE;
996
997     sym1 = OP_SYMBOL(op1);
998     sym2 = OP_SYMBOL(op2);
999
1000     /* if both are itemps & one is spilt
1001        and the other is not then false */
1002     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1003         sym1->isspilt != sym2->isspilt )
1004         return FALSE ;
1005
1006     /* if they are the same */
1007     if (sym1 == sym2)
1008         return TRUE ;
1009
1010     if (sym1->rname[0] && sym2->rname[0]
1011         && strcmp (sym1->rname, sym2->rname) == 0)
1012         return TRUE;
1013
1014
1015     /* if left is a tmp & right is not */
1016     if (IS_ITEMP(op1)  && 
1017         !IS_ITEMP(op2) &&
1018         sym1->isspilt  &&
1019         (sym1->usl.spillLoc == sym2))
1020         return TRUE;
1021
1022     if (IS_ITEMP(op2)  && 
1023         !IS_ITEMP(op1) &&
1024         sym2->isspilt  &&
1025         sym1->level > 0 &&
1026         (sym2->usl.spillLoc == sym1))
1027         return TRUE ;
1028
1029     return FALSE ;
1030 }
1031
1032 /*-----------------------------------------------------------------*/
1033 /* pic16_sameRegs - two asmops have the same registers                   */
1034 /*-----------------------------------------------------------------*/
1035 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1036 {
1037     int i;
1038
1039     if (aop1 == aop2)
1040         return TRUE ;
1041
1042     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1043                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1044
1045     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1046
1047     if (aop1->type != AOP_REG ||
1048         aop2->type != AOP_REG )
1049         return FALSE ;
1050
1051     if (aop1->size != aop2->size )
1052         return FALSE ;
1053
1054     for (i = 0 ; i < aop1->size ; i++ ) {
1055 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1056
1057 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1058         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1059             return FALSE ;
1060     }
1061
1062     return TRUE ;
1063 }
1064
1065 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1066 {
1067     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1068                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1069
1070     if(aop1 == aop2)return TRUE;
1071     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1072       
1073       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1074     
1075   return TRUE;
1076 }
1077
1078
1079 /*-----------------------------------------------------------------*/
1080 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1081 /*-----------------------------------------------------------------*/
1082 void pic16_aopOp (operand *op, iCode *ic, bool result)
1083 {
1084     asmop *aop;
1085     symbol *sym;
1086     int i;
1087
1088     if (!op)
1089         return ;
1090
1091     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1092
1093     /* if this a literal */
1094     if (IS_OP_LITERAL(op)) {
1095         op->aop = aop = newAsmop(AOP_LIT);
1096         aop->aopu.aop_lit = op->operand.valOperand;
1097         aop->size = getSize(operandType(op));
1098         return;
1099     }
1100
1101     {
1102       sym_link *type = operandType(op);
1103 #if 0
1104       if(IS_PTR_CONST(type))
1105 #else
1106       if(IS_CODEPTR(type))
1107 #endif
1108         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1109     }
1110
1111     /* if already has a asmop then continue */
1112     if (op->aop)
1113         return ;
1114
1115     /* if the underlying symbol has a aop */
1116     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1117       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1118         op->aop = OP_SYMBOL(op)->aop;
1119         return;
1120     }
1121
1122     /* if this is a true symbol */
1123     if (IS_TRUE_SYMOP(op)) {    
1124         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1125       op->aop = aopForSym(ic, op, result);
1126       return ;
1127     }
1128
1129     /* this is a temporary : this has
1130     only four choices :
1131     a) register
1132     b) spillocation
1133     c) rematerialize 
1134     d) conditional   
1135     e) can be a return use only */
1136
1137     sym = OP_SYMBOL(op);
1138
1139     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1140     /* if the type is a conditional */
1141     if (sym->regType == REG_CND) {
1142         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1143         aop->size = 0;
1144         return;
1145     }
1146
1147     /* if it is spilt then two situations
1148     a) is rematerialize 
1149     b) has a spill location */
1150     if (sym->isspilt || sym->nRegs == 0) {
1151
1152       DEBUGpic16_emitcode(";","%d",__LINE__);
1153         /* rematerialize it NOW */
1154         if (sym->remat) {
1155
1156             sym->aop = op->aop = aop = aopForRemat (op);
1157 //            aop->size = getSize(sym->type);
1158 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1159             return;
1160         }
1161
1162 #if 1
1163         if (sym->accuse) {
1164             int i;
1165             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1166             aop->size = getSize(sym->type);
1167             for ( i = 0 ; i < 1 ; i++ ) {
1168                 aop->aopu.aop_str[i] = accUse[i];
1169 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1170             }
1171             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1172             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1173             return;  
1174         }
1175 #endif
1176
1177 #if 1
1178         if (sym->ruonly ) {
1179           /*
1180           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1181           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1182           //pic16_allocDirReg (IC_LEFT(ic));
1183           aop->size = getSize(sym->type);
1184           */
1185
1186           unsigned i;
1187
1188           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1189           aop->size = getSize(sym->type);
1190           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1191             aop->aopu.aop_str[i] = fReturn[i];
1192
1193           DEBUGpic16_emitcode(";","%d",__LINE__);
1194           return;
1195         }
1196 #endif
1197         /* else spill location  */
1198         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1199             /* force a new aop if sizes differ */
1200             sym->usl.spillLoc->aop = NULL;
1201         }
1202
1203 #if 0
1204         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1205                             __FUNCTION__,__LINE__,
1206                             sym->usl.spillLoc->rname,
1207                             sym->rname, sym->usl.spillLoc->offset);
1208 #endif
1209
1210         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1211         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1212         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1213                                           getSize(sym->type), 
1214                                           sym->usl.spillLoc->offset, op);
1215         aop->size = getSize(sym->type);
1216
1217         return;
1218     }
1219
1220     {
1221       sym_link *type = operandType(op);
1222 #if 0
1223       if(IS_PTR_CONST(type)) 
1224 #else
1225       if(IS_CODEPTR(type)) 
1226 #endif
1227         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1228     }
1229
1230     /* must be in a register */
1231     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1232     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1233     aop->size = sym->nRegs;
1234     for ( i = 0 ; i < sym->nRegs ;i++)
1235         aop->aopu.aop_reg[i] = sym->regs[i];
1236 }
1237
1238 /*-----------------------------------------------------------------*/
1239 /* pic16_freeAsmop - free up the asmop given to an operand               */
1240 /*----------------------------------------------------------------*/
1241 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1242 {   
1243     asmop *aop ;
1244
1245     if (!op)
1246         aop = aaop;
1247     else 
1248         aop = op->aop;
1249
1250     if (!aop)
1251         return ;
1252
1253     if (aop->freed)
1254         goto dealloc; 
1255
1256     aop->freed = 1;
1257
1258     /* depending on the asmop type only three cases need work AOP_RO
1259        , AOP_R1 && AOP_STK */
1260 #if 1
1261     switch (aop->type) {
1262         case AOP_FSR0 :
1263             if (_G.fsr0Pushed ) {
1264                 if (pop) {
1265                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1266                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1267 //                    pic16_emitcode ("pop","ar0");
1268                     _G.fsr0Pushed--;
1269                 }
1270             }
1271             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1272             break;
1273
1274         case AOP_FSR2 :
1275             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1276             break;
1277
1278         case AOP_R0 :
1279             if (_G.r0Pushed ) {
1280                 if (pop) {
1281                     pic16_emitcode ("pop","ar0");     
1282                     _G.r0Pushed--;
1283                 }
1284             }
1285             bitVectUnSetBit(ic->rUsed,R0_IDX);
1286             break;
1287
1288         case AOP_R1 :
1289             if (_G.r1Pushed ) {
1290                 if (pop) {
1291                     pic16_emitcode ("pop","ar1");
1292                     _G.r1Pushed--;
1293                 }
1294             }
1295             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1296             break;
1297
1298         case AOP_STA:
1299           {
1300             int i;
1301
1302               /* we must store the result on stack */
1303               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1304                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1305                 for(i=0;i<aop->size;i++) {
1306                   /* initialise for stack access via frame pointer */
1307                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(OP_SYMBOL(IC_RESULT(ic))->stack + i + _G.stack_lat));
1308
1309                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1310                         aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2)));
1311                 }
1312         
1313                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1314               }
1315
1316               if(!_G.resDirect) {
1317                 for(i=0;i<aop->size;i++)
1318                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1319               }
1320               _G.resDirect = 0;
1321           }
1322           break;
1323 #if 0
1324         case AOP_STK :
1325         {
1326             int sz = aop->size;    
1327             int stk = aop->aopu.aop_stk + aop->size;
1328             bitVectUnSetBit(ic->rUsed,R0_IDX);
1329             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1330
1331             getFreePtr(ic,&aop,FALSE);
1332             
1333             if (options.stack10bit)
1334             {
1335                 /* I'm not sure what to do here yet... */
1336                 /* #STUB */
1337                 fprintf(stderr, 
1338                         "*** Warning: probably generating bad code for "
1339                         "10 bit stack mode.\n");
1340             }
1341             
1342             if (stk) {
1343                 pic16_emitcode ("mov","a,_bp");
1344                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1345                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1346             } else {
1347                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1348             }
1349
1350             while (sz--) {
1351                 pic16_emitcode("pop","acc");
1352                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1353                 if (!sz) break;
1354                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1355             }
1356             op->aop = aop;
1357             pic16_freeAsmop(op,NULL,ic,TRUE);
1358             if (_G.r0Pushed) {
1359                 pic16_emitcode("pop","ar0");
1360                 _G.r0Pushed--;
1361             }
1362
1363             if (_G.r1Pushed) {
1364                 pic16_emitcode("pop","ar1");
1365                 _G.r1Pushed--;
1366             }       
1367         }
1368 #endif
1369
1370     }
1371 #endif
1372
1373 dealloc:
1374     /* all other cases just dealloc */
1375     if (op ) {
1376         op->aop = NULL;
1377         if (IS_SYMOP(op)) {
1378             OP_SYMBOL(op)->aop = NULL;    
1379             /* if the symbol has a spill */
1380             if (SPIL_LOC(op))
1381                 SPIL_LOC(op)->aop = NULL;
1382         }
1383     }
1384 }
1385
1386 /*-----------------------------------------------------------------*/
1387 /* pic16_aopGet - for fetching value of the aop                          */
1388 /*-----------------------------------------------------------------*/
1389 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1390 {
1391     char *s = buffer ;
1392     char *rs;
1393
1394     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1395
1396     /* offset is greater than size then zero */
1397     if (offset > (aop->size - 1) &&
1398         aop->type != AOP_LIT)
1399         return zero;
1400
1401     /* depending on type */
1402     switch (aop->type) {
1403
1404     case AOP_FSR0:
1405     case AOP_FSR2:
1406       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1407       rs = Safe_calloc(1, strlen(s)+1);
1408       strcpy(rs, s);
1409       return (rs);
1410       
1411 #if 0
1412       /* if we need to increment it */
1413       while (offset > aop->coff)
1414         {
1415           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1416           aop->coff++;
1417         }
1418
1419       while (offset < aop->coff)
1420         {
1421           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1422           aop->coff--;
1423         }
1424       aop->coff = offset;
1425       if (aop->paged)
1426         {
1427           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1428           return (dname ? "acc" : "a");
1429         }
1430       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1431       rs = Safe_calloc (1, strlen (s) + 1);
1432       strcpy (rs, s);
1433       return rs;
1434 #endif
1435
1436         
1437     case AOP_IMMD:
1438         if (bit16) 
1439             sprintf (s,"%s",aop->aopu.aop_immd);
1440         else
1441             if (offset) 
1442                 sprintf(s,"(%s >> %d)",
1443                         aop->aopu.aop_immd,
1444                         offset*8);
1445             else
1446                 sprintf(s,"%s",
1447                         aop->aopu.aop_immd);
1448         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1449         rs = Safe_calloc(1,strlen(s)+1);
1450         strcpy(rs,s);   
1451         return rs;
1452         
1453     case AOP_DIR:
1454       if (offset) {
1455         sprintf(s,"(%s + %d)",
1456                 aop->aopu.aop_dir,
1457                 offset);
1458         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1459       } else
1460             sprintf(s,"%s",aop->aopu.aop_dir);
1461         rs = Safe_calloc(1,strlen(s)+1);
1462         strcpy(rs,s);   
1463         return rs;
1464         
1465     case AOP_REG:
1466       //if (dname) 
1467       //    return aop->aopu.aop_reg[offset]->dname;
1468       //else
1469             return aop->aopu.aop_reg[offset]->name;
1470         
1471     case AOP_CRY:
1472       //pic16_emitcode(";","%d",__LINE__);
1473       return aop->aopu.aop_dir;
1474         
1475     case AOP_ACC:
1476         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1477 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1478 //        assert( 0 );
1479 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1480         rs = Safe_strdup("WREG");
1481         return (rs);
1482
1483     case AOP_LIT:
1484         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1485         rs = Safe_calloc(1,strlen(s)+1);
1486         strcpy(rs,s);   
1487         return rs;
1488         
1489     case AOP_STR:
1490         aop->coff = offset ;
1491         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1492             dname)
1493             return "acc";
1494         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1495         
1496         return aop->aopu.aop_str[offset];
1497         
1498     case AOP_PCODE:
1499       {
1500         pCodeOp *pcop = aop->aopu.pcop;
1501         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1502         if(pcop->name) {
1503           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1504           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1505           sprintf(s,"%s", pcop->name);
1506         } else
1507           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1508
1509       }
1510       rs = Safe_calloc(1,strlen(s)+1);
1511       strcpy(rs,s);   
1512       return rs;
1513
1514     case AOP_STA:
1515         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1516         return (rs);
1517         
1518     case AOP_STK:
1519 //        pCodeOp *pcop = aop->aop
1520         break;
1521
1522     }
1523
1524     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1525     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1526            "aopget got unsupported aop->type");
1527     exit(0);
1528 }
1529
1530
1531
1532 /* lock has the following meaning: When allocating temporary registers
1533  * for stack variables storage, the value of the temporary register is
1534  * saved on stack. Its value is restored at the end. This procedure is
1535  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1536  * a possibility that before a call to pic16_aopOp, a temporary register
1537  * is allocated for a while and it is freed after some time, this will
1538  * mess the stack and values will not be restored properly. So use lock=1
1539  * to allocate temporary registers used internally by the programmer, and
1540  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1541  * to inform the compiler developer about a possible bug. This is an internal
1542  * feature for developing the compiler -- VR */
1543  
1544 int _TempReg_lock = 0;
1545 /*-----------------------------------------------------------------*/
1546 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1547 /*-----------------------------------------------------------------*/
1548 pCodeOp *pic16_popGetTempReg(int lock)
1549 {
1550   pCodeOp *pcop;
1551   symbol *cfunc;
1552
1553 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1554     if(_TempReg_lock) {
1555 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1556     }
1557     
1558     _TempReg_lock += lock;
1559     
1560     cfunc = currFunc;
1561     currFunc = NULL;
1562
1563     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1564     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1565       PCOR(pcop)->r->wasUsed=1;
1566       PCOR(pcop)->r->isFree=0;
1567
1568       /* push value on stack */
1569       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1570     }
1571
1572     currFunc = cfunc;
1573
1574   return pcop;
1575 }
1576
1577 /*-----------------------------------------------------------------*/
1578 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but   */
1579 /*                            don't save if inside v               */
1580 /*-----------------------------------------------------------------*/
1581 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1582 {
1583   pCodeOp *pcop;
1584   symbol *cfunc;
1585
1586 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1587
1588     if(_TempReg_lock) {
1589 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1590     }
1591
1592     _TempReg_lock += lock;
1593
1594     cfunc = currFunc;
1595     currFunc = NULL;
1596
1597     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1598     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1599       PCOR(pcop)->r->wasUsed=1;
1600       PCOR(pcop)->r->isFree=0;
1601
1602       if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1603       /* push value on stack */
1604         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1605       }
1606     }
1607
1608     currFunc = cfunc;
1609
1610   return pcop;
1611 }
1612
1613
1614 /*-----------------------------------------------------------------*/
1615 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1616 /*-----------------------------------------------------------------*/
1617 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1618 {
1619   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1620
1621   _TempReg_lock -= lock;
1622
1623   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1624     PCOR(pcop)->r->isFree = 1;
1625     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1626   }
1627 }
1628 /*-----------------------------------------------------------------*/
1629 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1630 /*-----------------------------------------------------------------*/
1631 pCodeOp *pic16_popGetLabel(unsigned int key)
1632 {
1633
1634   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1635
1636   if(key>max_key)
1637     max_key = key;
1638
1639   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* pic16_popCopyReg - copy a pcode operator                              */
1644 /*-----------------------------------------------------------------*/
1645 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1646 {
1647   pCodeOpReg *pcor;
1648
1649   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1650   pcor->pcop.type = pc->pcop.type;
1651   if(pc->pcop.name) {
1652     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1653       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1654   } else
1655     pcor->pcop.name = NULL;
1656
1657   pcor->r = pc->r;
1658   pcor->rIdx = pc->rIdx;
1659   pcor->r->wasUsed=1;
1660
1661 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1662
1663   return PCOP(pcor);
1664 }
1665
1666 /*-----------------------------------------------------------------*/
1667 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1668 /*-----------------------------------------------------------------*/
1669 pCodeOp *pic16_popGetLit(int lit)
1670 {
1671   return pic16_newpCodeOpLit(lit);
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1676 /*-----------------------------------------------------------------*/
1677 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1678 {
1679   return pic16_newpCodeOpLit2(lit, arg2);
1680 }
1681
1682
1683 /*-----------------------------------------------------------------*/
1684 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1685 /*-----------------------------------------------------------------*/
1686 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1687 {
1688   return pic16_newpCodeOpImmd(name, offset,index, 0);
1689 }
1690
1691
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popGet - asm operator to pcode operator conversion              */
1694 /*-----------------------------------------------------------------*/
1695 pCodeOp *pic16_popGetWithString(char *str)
1696 {
1697   pCodeOp *pcop;
1698
1699
1700   if(!str) {
1701     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1702     exit (1);
1703   }
1704
1705   pcop = pic16_newpCodeOp(str,PO_STR);
1706
1707   return pcop;
1708 }
1709
1710 /*-----------------------------------------------------------------*/
1711 /* pic16_popRegFromString -                                        */
1712 /*-----------------------------------------------------------------*/
1713 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1714 {
1715
1716   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1717   pcop->type = PO_DIR;
1718
1719   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1720   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1721
1722   if(!str)
1723     str = "BAD_STRING";
1724
1725   pcop->name = Safe_calloc(1,strlen(str)+1);
1726   strcpy(pcop->name,str);
1727
1728   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1729
1730   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1731
1732   /* make sure that register doesn't exist,
1733    * and operand isn't NULL
1734    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1735   if((PCOR(pcop)->r == NULL) 
1736     && (op)
1737     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1738 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1739 //              __FUNCTION__, __LINE__, str, size, offset);
1740
1741     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1742     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1743
1744   }
1745   PCOR(pcop)->instance = offset;
1746
1747   return pcop;
1748 }
1749
1750 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1751 {
1752   pCodeOp *pcop;
1753
1754 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1755
1756         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1757         PCOR(pcop)->rIdx = rIdx;
1758         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1759
1760         PCOR(pcop)->r->isFree = 0;
1761         PCOR(pcop)->r->wasUsed = 1;
1762
1763         pcop->type = PCOR(pcop)->r->pc_type;
1764
1765   return pcop;
1766 }
1767
1768 /*---------------------------------------------------------------------------------*/
1769 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1770 /*                 VR 030601                                                       */
1771 /*---------------------------------------------------------------------------------*/
1772 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1773 {
1774   pCodeOpReg2 *pcop2;
1775   pCodeOp *temp;
1776   
1777         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1778
1779         /* comment the following check, so errors to throw up */
1780 //      if(!pcop2)return NULL;
1781
1782         temp = pic16_popGet(aop_dst, offset);
1783         pcop2->pcop2 = temp;
1784         
1785   return PCOP(pcop2);
1786 }
1787
1788
1789
1790 /*--------------------------------------------------------------------------------.-*/
1791 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1792 /*                  VR 030601 , adapted by Hans Dorn                                */
1793 /*--------------------------------------------------------------------------------.-*/
1794 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1795 {
1796   pCodeOpReg2 *pcop2;
1797  
1798         pcop2 = (pCodeOpReg2 *)src;
1799         pcop2->pcop2 = dst;
1800         
1801         return PCOP(pcop2);
1802 }
1803
1804
1805
1806 /*---------------------------------------------------------------------------------*/
1807 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1808 /*                     movff instruction                                           */
1809 /*---------------------------------------------------------------------------------*/
1810 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1811 {
1812   pCodeOpReg2 *pcop2;
1813
1814         if(!noalloc) {
1815                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1816                 pcop2->pcop2 = pic16_popCopyReg(dst);
1817         } else {
1818                 /* the pCodeOp may be already allocated */
1819                 pcop2 = (pCodeOpReg2 *)(src);
1820                 pcop2->pcop2 = (pCodeOp *)(dst);
1821         }
1822
1823   return PCOP(pcop2);
1824 }
1825
1826
1827 /*-----------------------------------------------------------------*/
1828 /* pic16_popGet - asm operator to pcode operator conversion              */
1829 /*-----------------------------------------------------------------*/
1830 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1831 {
1832   //char *s = buffer ;
1833   char *rs;
1834   pCodeOp *pcop;
1835
1836     FENTRY2;
1837     /* offset is greater than
1838     size then zero */
1839
1840 //    if (offset > (aop->size - 1) &&
1841 //        aop->type != AOP_LIT)
1842 //      return NULL;  //zero;
1843
1844     /* depending on type */
1845     switch (aop->type) {
1846         
1847     case AOP_R0:
1848     case AOP_R1:
1849     case AOP_DPTR:
1850     case AOP_DPTR2:
1851         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1852         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1853         assert( 0 );
1854         return NULL;
1855
1856
1857     case AOP_FSR0:
1858     case AOP_FSR2:
1859       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1860       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1861       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1862       PCOR(pcop)->r->wasUsed = 1;
1863       PCOR(pcop)->r->isFree = 0;
1864       
1865       PCOR(pcop)->instance = offset;
1866       pcop->type = PCOR(pcop)->r->pc_type;
1867       return (pcop);
1868
1869     case AOP_IMMD:
1870       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1871       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1872
1873     case AOP_STA:
1874       /* pCodeOp is already allocated from aopForSym */
1875         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1876         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1877           
1878       return (pcop);
1879       
1880     case AOP_ACC:
1881       {
1882         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1883
1884         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1885
1886         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1887         
1888         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1889         PCOR(pcop)->rIdx = rIdx;
1890         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1891         PCOR(pcop)->r->wasUsed=1;
1892         PCOR(pcop)->r->isFree=0;
1893
1894         PCOR(pcop)->instance = offset;
1895         pcop->type = PCOR(pcop)->r->pc_type;
1896 //      rs = aop->aopu.aop_reg[offset]->name;
1897 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1898         return pcop;
1899
1900
1901 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1902 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1903
1904 //      assert( 0 );
1905       }
1906         
1907     case AOP_DIR:
1908       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1909       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1910         
1911     case AOP_REG:
1912       {
1913         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1914
1915         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1916         
1917         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1918 //      pcop->type = PO_GPR_REGISTER;
1919         PCOR(pcop)->rIdx = rIdx;
1920         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1921         PCOR(pcop)->r->wasUsed=1;
1922         PCOR(pcop)->r->isFree=0;
1923
1924         PCOR(pcop)->instance = offset;
1925         pcop->type = PCOR(pcop)->r->pc_type;
1926         
1927         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1928         rs = aop->aopu.aop_reg[offset]->name;
1929         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1930         return pcop;
1931       }
1932
1933     case AOP_CRY:
1934         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1935
1936       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1937       PCOR(pcop)->instance = offset;
1938       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1939       //if(PCOR(pcop)->r == NULL)
1940       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1941       return pcop;
1942         
1943     case AOP_LIT:
1944         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1945       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1946
1947     case AOP_STR:
1948       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1949       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1950
1951       /*
1952       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1953       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1954       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1955       pcop->type = PCOR(pcop)->r->pc_type;
1956       pcop->name = PCOR(pcop)->r->name;
1957
1958       return pcop;
1959       */
1960
1961     case AOP_PCODE:
1962       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1963                           __LINE__, 
1964                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1965       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1966 #if 1
1967         switch( aop->aopu.pcop->type ) {
1968                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1969                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1970                 default:
1971                         assert( 0 );    /* should never reach here */;
1972         }
1973 #else
1974       PCOI(pcop)->offset = offset;
1975 #endif
1976       return pcop;
1977     }
1978
1979     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1980            "pic16_popGet got unsupported aop->type");
1981     exit(0);
1982 }
1983 /*-----------------------------------------------------------------*/
1984 /* pic16_aopPut - puts a string for a aop                                */
1985 /*-----------------------------------------------------------------*/
1986 void pic16_aopPut (asmop *aop, char *s, int offset)
1987 {
1988     char *d = buffer ;
1989     symbol *lbl ;
1990
1991     return;
1992
1993     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1994
1995     if (aop->size && offset > ( aop->size - 1)) {
1996         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1997                "pic16_aopPut got offset > aop->size");
1998         exit(0);
1999     }
2000
2001     /* will assign value to value */
2002     /* depending on where it is ofcourse */
2003     switch (aop->type) {
2004     case AOP_DIR:
2005       if (offset) {
2006         sprintf(d,"(%s + %d)",
2007                 aop->aopu.aop_dir,offset);
2008         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2009
2010       } else
2011             sprintf(d,"%s",aop->aopu.aop_dir);
2012         
2013         if (strcmp(d,s)) {
2014           DEBUGpic16_emitcode(";","%d",__LINE__);
2015           if(strcmp(s,"W"))
2016             pic16_emitcode("movf","%s,w",s);
2017           pic16_emitcode("movwf","%s",d);
2018
2019           if(strcmp(s,"W")) {
2020             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2021             if(offset >= aop->size) {
2022               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2023               break;
2024             } else
2025               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2026           }
2027
2028           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2029
2030
2031         }
2032         break;
2033         
2034     case AOP_REG:
2035       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2036         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2037           /*
2038             if (*s == '@'           ||
2039                 strcmp(s,"r0") == 0 ||
2040                 strcmp(s,"r1") == 0 ||
2041                 strcmp(s,"r2") == 0 ||
2042                 strcmp(s,"r3") == 0 ||
2043                 strcmp(s,"r4") == 0 ||
2044                 strcmp(s,"r5") == 0 ||
2045                 strcmp(s,"r6") == 0 || 
2046                 strcmp(s,"r7") == 0 )
2047                 pic16_emitcode("mov","%s,%s  ; %d",
2048                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2049             else
2050           */
2051
2052           if(strcmp(s,"W")==0 )
2053             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2054
2055           pic16_emitcode("movwf","%s",
2056                    aop->aopu.aop_reg[offset]->name);
2057
2058           if(strcmp(s,zero)==0) {
2059             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2060
2061           } else if(strcmp(s,"W")==0) {
2062             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2063             pcop->type = PO_GPR_REGISTER;
2064
2065             PCOR(pcop)->rIdx = -1;
2066             PCOR(pcop)->r = NULL;
2067
2068             DEBUGpic16_emitcode(";","%d",__LINE__);
2069             pcop->name = Safe_strdup(s);
2070             pic16_emitpcode(POC_MOVFW,pcop);
2071             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2072           } else if(strcmp(s,one)==0) {
2073             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2074             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2075           } else {
2076             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2077           }
2078         }
2079         break;
2080         
2081     case AOP_DPTR:
2082     case AOP_DPTR2:
2083     
2084     if (aop->type == AOP_DPTR2)
2085     {
2086         genSetDPTR(1);
2087     }
2088     
2089         if (aop->code) {
2090             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2091                    "pic16_aopPut writting to code space");
2092             exit(0);
2093         }
2094         
2095         while (offset > aop->coff) {
2096             aop->coff++;
2097             pic16_emitcode ("inc","dptr");
2098         }
2099         
2100         while (offset < aop->coff) {
2101             aop->coff-- ;
2102             pic16_emitcode("lcall","__decdptr");
2103         }
2104         
2105         aop->coff = offset;
2106         
2107         /* if not in accumulater */
2108         MOVA(s);        
2109         
2110         pic16_emitcode ("movx","@dptr,a");
2111         
2112     if (aop->type == AOP_DPTR2)
2113     {
2114         genSetDPTR(0);
2115     }
2116         break;
2117         
2118     case AOP_R0:
2119     case AOP_R1:
2120         while (offset > aop->coff) {
2121             aop->coff++;
2122             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2123         }
2124         while (offset < aop->coff) {
2125             aop->coff-- ;
2126             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2127         }
2128         aop->coff = offset;
2129         
2130         if (aop->paged) {
2131             MOVA(s);           
2132             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2133             
2134         } else
2135             if (*s == '@') {
2136                 MOVA(s);
2137                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2138             } else
2139                 if (strcmp(s,"r0") == 0 ||
2140                     strcmp(s,"r1") == 0 ||
2141                     strcmp(s,"r2") == 0 ||
2142                     strcmp(s,"r3") == 0 ||
2143                     strcmp(s,"r4") == 0 ||
2144                     strcmp(s,"r5") == 0 ||
2145                     strcmp(s,"r6") == 0 || 
2146                     strcmp(s,"r7") == 0 ) {
2147                     char buffer[10];
2148                     sprintf(buffer,"a%s",s);
2149                     pic16_emitcode("mov","@%s,%s",
2150                              aop->aopu.aop_ptr->name,buffer);
2151                 } else
2152                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2153         
2154         break;
2155         
2156     case AOP_STK:
2157         if (strcmp(s,"a") == 0)
2158             pic16_emitcode("push","acc");
2159         else
2160             pic16_emitcode("push","%s",s);
2161         
2162         break;
2163         
2164     case AOP_CRY:
2165         /* if bit variable */
2166         if (!aop->aopu.aop_dir) {
2167             pic16_emitcode("clr","a");
2168             pic16_emitcode("rlc","a");
2169         } else {
2170             if (s == zero) 
2171                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2172             else
2173                 if (s == one)
2174                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2175                 else
2176                     if (!strcmp(s,"c"))
2177                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2178                     else {
2179                         lbl = newiTempLabel(NULL);
2180                         
2181                         if (strcmp(s,"a")) {
2182                             MOVA(s);
2183                         }
2184                         pic16_emitcode("clr","c");
2185                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2186                         pic16_emitcode("cpl","c");
2187                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2188                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2189                     }
2190         }
2191         break;
2192         
2193     case AOP_STR:
2194         aop->coff = offset;
2195         if (strcmp(aop->aopu.aop_str[offset],s))
2196             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2197         break;
2198         
2199     case AOP_ACC:
2200         aop->coff = offset;
2201         if (!offset && (strcmp(s,"acc") == 0))
2202             break;
2203         
2204         if (strcmp(aop->aopu.aop_str[offset],s))
2205             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2206         break;
2207
2208     default :
2209         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2210 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2211 //             "pic16_aopPut got unsupported aop->type");
2212 //      exit(0);    
2213     }    
2214
2215 }
2216
2217 /*-----------------------------------------------------------------*/
2218 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2219 /*-----------------------------------------------------------------*/
2220 static void mov2w (asmop *aop, int offset)
2221 {
2222   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2223
2224   if(is_LitAOp(aop))
2225     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2226   else
2227     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2228 }
2229
2230 static void mov2f(asmop *dst, asmop *src, int offset)
2231 {
2232   if(is_LitAOp(src)) {
2233     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2234     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2235   } else {
2236     if(pic16_sameRegsOfs(src, dst, offset))return;
2237     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2238                       pic16_popGet(dst, offset)));
2239   }
2240 }
2241
2242 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2243 {
2244   if(is_LitAOp(src)) {
2245     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2246     pic16_emitpcode(POC_MOVWF, dst);
2247   } else {
2248     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2249   }
2250 }
2251
2252 void pic16_testStackOverflow(void)
2253 {
2254 #define GSTACK_TEST_NAME        "__gstack_test"
2255
2256   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2257   
2258   {
2259     symbol *sym;
2260
2261       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2262       strcpy(sym->rname, GSTACK_TEST_NAME);
2263       checkAddSym(&externs, sym);
2264   }
2265
2266 }
2267
2268 /* push pcop into stack */
2269 void pic16_pushpCodeOp(pCodeOp *pcop)
2270 {
2271 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2273   if(pic16_options.gstack)
2274     pic16_testStackOverflow();
2275     
2276 }
2277
2278 /* pop pcop from stack */
2279 void pic16_poppCodeOp(pCodeOp *pcop)
2280 {
2281   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2282   if(pic16_options.gstack)
2283     pic16_testStackOverflow();
2284 }
2285
2286
2287 /*-----------------------------------------------------------------*/
2288 /* pushw - pushes wreg to stack                                    */
2289 /*-----------------------------------------------------------------*/
2290 void pushw(void)
2291 {
2292   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2293   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2294   if(pic16_options.gstack)
2295     pic16_testStackOverflow();
2296 }
2297
2298                 
2299 /*-----------------------------------------------------------------*/
2300 /* pushaop - pushes aop to stack                                   */
2301 /*-----------------------------------------------------------------*/
2302 void pushaop(asmop *aop, int offset)
2303 {
2304   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2305
2306   if(is_LitAOp(aop)) {
2307     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2308     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2309   } else {
2310     pic16_emitpcode(POC_MOVFF,
2311       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2312   }
2313
2314 //  pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2315   if(pic16_options.gstack)
2316     pic16_testStackOverflow();
2317 }
2318
2319 /*-----------------------------------------------------------------*/
2320 /* popaop - pops aop from stack                                    */
2321 /*-----------------------------------------------------------------*/
2322 void popaop(asmop *aop, int offset)
2323 {
2324   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2325   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2326   if(pic16_options.gstack)
2327     pic16_testStackOverflow();
2328 }
2329
2330 void popaopidx(asmop *aop, int offset, int index)
2331 {
2332   int ofs=1;
2333
2334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2335
2336     if(STACK_MODEL_LARGE)ofs++;
2337
2338     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2339     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2340     if(pic16_options.gstack)
2341       pic16_testStackOverflow();
2342 }
2343
2344 /*-----------------------------------------------------------------*/
2345 /* reAdjustPreg - points a register back to where it should        */
2346 /*-----------------------------------------------------------------*/
2347 static void reAdjustPreg (asmop *aop)
2348 {
2349     int size ;
2350
2351     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2352     aop->coff = 0;
2353     if ((size = aop->size) <= 1)
2354         return ;
2355     size-- ;
2356     switch (aop->type) {
2357         case AOP_R0 :
2358         case AOP_R1 :
2359             while (size--)
2360                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2361             break;          
2362         case AOP_DPTR :
2363         case AOP_DPTR2:
2364             if (aop->type == AOP_DPTR2)
2365             {
2366                 genSetDPTR(1);
2367             } 
2368             while (size--)
2369             {
2370                 pic16_emitcode("lcall","__decdptr");
2371             }
2372                 
2373             if (aop->type == AOP_DPTR2)
2374             {
2375                 genSetDPTR(0);
2376             }                
2377             break;  
2378
2379     }   
2380
2381 }
2382
2383
2384 #if 0
2385 /*-----------------------------------------------------------------*/
2386 /* opIsGptr: returns non-zero if the passed operand is             */   
2387 /* a generic pointer type.                                         */
2388 /*-----------------------------------------------------------------*/ 
2389 static int opIsGptr(operand *op)
2390 {
2391     sym_link *type = operandType(op);
2392     
2393     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2394     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2395     {
2396         return 1;
2397     }
2398     return 0;        
2399 }
2400 #endif
2401
2402 /*-----------------------------------------------------------------*/
2403 /* pic16_getDataSize - get the operand data size                         */
2404 /*-----------------------------------------------------------------*/
2405 int pic16_getDataSize(operand *op)
2406 {
2407     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2408
2409
2410     return AOP_SIZE(op);
2411
2412     // tsd- in the pic port, the genptr size is 1, so this code here
2413     // fails. ( in the 8051 port, the size was 4).
2414 #if 0
2415     int size;
2416     size = AOP_SIZE(op);
2417     if (size == GPTRSIZE)
2418     {
2419         sym_link *type = operandType(op);
2420         if (IS_GENPTR(type))
2421         {
2422             /* generic pointer; arithmetic operations
2423              * should ignore the high byte (pointer type).
2424              */
2425             size--;
2426     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2427         }
2428     }
2429     return size;
2430 #endif
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* pic16_outAcc - output Acc                                             */
2435 /*-----------------------------------------------------------------*/
2436 void pic16_outAcc(operand *result)
2437 {
2438   int size,offset;
2439   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2440   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2441
2442
2443   size = pic16_getDataSize(result);
2444   if(size){
2445     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2446     size--;
2447     offset = 1;
2448     /* unsigned or positive */
2449     while(size--)
2450       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2451   }
2452
2453 }
2454
2455 /*-----------------------------------------------------------------*/
2456 /* pic16_outBitC - output a bit C                                  */
2457 /*                 Move to result the value of Carry flag -- VR    */
2458 /*-----------------------------------------------------------------*/
2459 void pic16_outBitC(operand *result)
2460 {
2461   int i;
2462
2463     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2464
2465     /* if the result is bit */
2466     if (AOP_TYPE(result) == AOP_CRY) {
2467         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2468         pic16_aopPut(AOP(result),"c",0);
2469     } else {
2470
2471         i = AOP_SIZE(result);
2472         while(i--) {
2473                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2474         }
2475         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2476     }
2477 }
2478
2479 /*-----------------------------------------------------------------*/
2480 /* pic16_outBitOp - output a bit from Op                           */
2481 /*                 Move to result the value of set/clr op -- VR    */
2482 /*-----------------------------------------------------------------*/
2483 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2484 {
2485   int i;
2486
2487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2488
2489     /* if the result is bit */
2490     if (AOP_TYPE(result) == AOP_CRY) {
2491         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2492         pic16_aopPut(AOP(result),"c",0);
2493     } else {
2494
2495         i = AOP_SIZE(result);
2496         while(i--) {
2497                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2498         }
2499         pic16_emitpcode(POC_RRCF, pcop);          
2500         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2501     }
2502 }
2503
2504 /*-----------------------------------------------------------------*/
2505 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2506 /*-----------------------------------------------------------------*/
2507 void pic16_toBoolean(operand *oper)
2508 {
2509     int size = AOP_SIZE(oper) - 1;
2510     int offset = 1;
2511
2512     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2513
2514     if ( AOP_TYPE(oper) != AOP_ACC) {
2515       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2516     }
2517     while (size--) {
2518       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2519     }
2520 }
2521
2522
2523 #if !defined(GEN_Not)
2524 /*-----------------------------------------------------------------*/
2525 /* genNot - generate code for ! operation                          */
2526 /*-----------------------------------------------------------------*/
2527 static void pic16_genNot (iCode *ic)
2528 {
2529   symbol *tlbl;
2530   int size;
2531
2532   FENTRY;
2533   /* assign asmOps to operand & result */
2534   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2535   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2536
2537   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2538   /* if in bit space then a special case */
2539   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2540     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2541       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2542       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2543     } else {
2544       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2545       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2546       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2547     }
2548     goto release;
2549   }
2550
2551   size = AOP_SIZE(IC_LEFT(ic));
2552   if(size == 1) {
2553     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2554     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2555     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2556     goto release;
2557   }
2558   pic16_toBoolean(IC_LEFT(ic));
2559
2560   tlbl = newiTempLabel(NULL);
2561   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2562   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2563   pic16_outBitC(IC_RESULT(ic));
2564
2565  release:    
2566   /* release the aops */
2567   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2568   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2569 }
2570 #endif
2571
2572
2573 #if !defined(GEN_Cpl)
2574 /*-----------------------------------------------------------------*/
2575 /* genCpl - generate code for complement                           */
2576 /*-----------------------------------------------------------------*/
2577 static void pic16_genCpl (iCode *ic)
2578 {
2579   int offset = 0;
2580   int size ;
2581
2582     FENTRY;
2583     /* assign asmOps to operand & result */
2584     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2585     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2586
2587     /* if both are in bit space then 
2588     a special case */
2589     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2590         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2591
2592         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2593         pic16_emitcode("cpl","c"); 
2594         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2595         goto release; 
2596     } 
2597
2598     size = AOP_SIZE(IC_RESULT(ic));
2599     while (size--) {
2600 /*
2601         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2602         MOVA(l);       
2603         pic16_emitcode("cpl","a");
2604         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2605 */
2606         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2607               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2608         } else {
2609                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2610                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2611         }
2612         offset++;
2613
2614     }
2615
2616
2617 release:
2618     /* release the aops */
2619     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2620     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2621 }
2622 #endif
2623
2624 /*-----------------------------------------------------------------*/
2625 /* genUminusFloat - unary minus for floating points                */
2626 /*-----------------------------------------------------------------*/
2627 static void genUminusFloat(operand *op,operand *result)
2628 {
2629   int size ,offset =0 ;
2630   
2631     FENTRY;
2632     /* for this we just need to flip the 
2633     first it then copy the rest in place */
2634     size = AOP_SIZE(op);
2635
2636     while(size--) {
2637       mov2f(AOP(result), AOP(op), offset);
2638       offset++;
2639     }
2640     
2641     /* toggle the MSB's highest bit */
2642     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2643 }
2644
2645 /*-----------------------------------------------------------------*/
2646 /* genUminus - unary minus code generation                         */
2647 /*-----------------------------------------------------------------*/
2648 static void genUminus (iCode *ic)
2649 {
2650   int size, i;
2651   sym_link *optype, *rtype;
2652
2653     FENTRY;     
2654     
2655     /* assign asmops */
2656     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2657     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2658
2659     /* if both in bit space then special case */
2660     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2661       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2662         
2663         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2664         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2665         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2666         goto release; 
2667     } 
2668
2669     optype = operandType(IC_LEFT(ic));
2670     rtype = operandType(IC_RESULT(ic));
2671
2672     /* if float then do float stuff */
2673     if (IS_FLOAT(optype)) {
2674       genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2675       goto release;
2676     }
2677
2678     /* otherwise subtract from zero by taking the 2's complement */
2679     size = AOP_SIZE(IC_LEFT(ic));
2680
2681     for(i=0; i<size; i++) {
2682       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2683         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2684       else {
2685         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2686         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2687       }
2688     }
2689
2690     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2691     for(i=1; i<size; i++) {
2692       emitSKPNZ;
2693       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2694     }
2695
2696 release:
2697     /* release the aops */
2698     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2699     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2700 }
2701
2702 #if 0
2703 /*-----------------------------------------------------------------*/
2704 /* saveRegisters - will look for a call and save the registers     */
2705 /*-----------------------------------------------------------------*/
2706 static void saveRegisters(iCode *lic) 
2707 {
2708     int i;
2709     iCode *ic;
2710     bitVect *rsave;
2711     sym_link *dtype;
2712
2713     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2714     /* look for call */
2715     for (ic = lic ; ic ; ic = ic->next) 
2716         if (ic->op == CALL || ic->op == PCALL)
2717             break;
2718
2719     if (!ic) {
2720         fprintf(stderr,"found parameter push with no function call\n");
2721         return ;
2722     }
2723
2724     /* if the registers have been saved already then
2725     do nothing */
2726     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2727         return ;
2728
2729     /* find the registers in use at this time 
2730     and push them away to safety */
2731     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2732                           ic->rUsed);
2733
2734     ic->regsSaved = 1;
2735     if (options.useXstack) {
2736         if (bitVectBitValue(rsave,R0_IDX))
2737             pic16_emitcode("mov","b,r0");
2738         pic16_emitcode("mov","r0,%s",spname);
2739         for (i = 0 ; i < pic16_nRegs ; i++) {
2740             if (bitVectBitValue(rsave,i)) {
2741                 if (i == R0_IDX)
2742                     pic16_emitcode("mov","a,b");
2743                 else
2744                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2745                 pic16_emitcode("movx","@r0,a");
2746                 pic16_emitcode("inc","r0");
2747             }
2748         }
2749         pic16_emitcode("mov","%s,r0",spname);
2750         if (bitVectBitValue(rsave,R0_IDX))
2751             pic16_emitcode("mov","r0,b");           
2752     }// else
2753     //for (i = 0 ; i < pic16_nRegs ; i++) {
2754     //    if (bitVectBitValue(rsave,i))
2755     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2756     //}
2757
2758     dtype = operandType(IC_LEFT(ic));
2759     if (currFunc && dtype && 
2760         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2761         IFFUNC_ISISR(currFunc->type) &&
2762         !ic->bankSaved) 
2763
2764         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2765
2766 }
2767 /*-----------------------------------------------------------------*/
2768 /* unsaveRegisters - pop the pushed registers                      */
2769 /*-----------------------------------------------------------------*/
2770 static void unsaveRegisters (iCode *ic)
2771 {
2772     int i;
2773     bitVect *rsave;
2774
2775     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2776     /* find the registers in use at this time 
2777     and push them away to safety */
2778     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2779                           ic->rUsed);
2780     
2781     if (options.useXstack) {
2782         pic16_emitcode("mov","r0,%s",spname);   
2783         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2784             if (bitVectBitValue(rsave,i)) {
2785                 pic16_emitcode("dec","r0");
2786                 pic16_emitcode("movx","a,@r0");
2787                 if (i == R0_IDX)
2788                     pic16_emitcode("mov","b,a");
2789                 else
2790                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2791             }       
2792
2793         }
2794         pic16_emitcode("mov","%s,r0",spname);
2795         if (bitVectBitValue(rsave,R0_IDX))
2796             pic16_emitcode("mov","r0,b");
2797     } //else
2798     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2799     //    if (bitVectBitValue(rsave,i))
2800     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2801     //}
2802
2803 }  
2804 #endif
2805
2806 #if 0  // patch 14
2807 /*-----------------------------------------------------------------*/
2808 /* pushSide -                                                      */
2809 /*-----------------------------------------------------------------*/
2810 static void pushSide(operand * oper, int size)
2811 {
2812         int offset = 0;
2813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2814         while (size--) {
2815                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2816                 if (AOP_TYPE(oper) != AOP_REG &&
2817                     AOP_TYPE(oper) != AOP_DIR &&
2818                     strcmp(l,"a") ) {
2819                         pic16_emitcode("mov","a,%s",l);
2820                         pic16_emitcode("push","acc");
2821                 } else
2822                         pic16_emitcode("push","%s",l);
2823         }
2824 }
2825 #endif // patch 14
2826
2827 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2828 {
2829   if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2830     pic16_emitpcode(POC_MOVFW, src);
2831     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2832   } else {
2833     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2834         src, pic16_popGet(AOP(op), offset)));
2835   }
2836 }
2837
2838
2839 /*-----------------------------------------------------------------*/
2840 /* assignResultValue - assign results to oper, rescall==1 is       */
2841 /*                     called from genCall() or genPcall()         */
2842 /*-----------------------------------------------------------------*/
2843 static void assignResultValue(operand * oper, int rescall)
2844 {
2845   int size = AOP_SIZE(oper);
2846   int offset=0;
2847   
2848     FENTRY2;
2849 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2850     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2851
2852     if(rescall) {
2853       /* assign result from a call/pcall function() */
2854                 
2855       /* function results are stored in a special order,
2856        * see top of file with Function return policy, or manual */
2857
2858       if(size <= 4) {
2859         /* 8-bits, result in WREG */
2860         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2861                         
2862         if(size>1) {
2863           /* 16-bits, result in PRODL:WREG */
2864           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2865         }
2866                         
2867         if(size>2) {
2868           /* 24-bits, result in PRODH:PRODL:WREG */
2869           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2870         }
2871                         
2872         if(size>3) {
2873           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2874           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2875         }
2876       
2877       } else {
2878         /* >32-bits, result on stack, and FSR0 points to beginning.
2879          * Fix stack when done */
2880         /* FIXME FIXME */
2881 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2882         while (size--) {
2883 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2884 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2885                 
2886           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2887           GpsuedoStkPtr++;
2888         }
2889                         
2890         /* fix stack */
2891         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2892         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2893         if(STACK_MODEL_LARGE) {
2894           emitSKPNC;
2895           pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2896         }
2897       }                 
2898     } else {
2899       int areg = 0;             /* matching argument register */
2900       
2901 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2902       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2903
2904
2905       /* its called from genReceive (probably) -- VR */
2906       if(!GpsuedoStkPtr && _G.useWreg) {
2907 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2908
2909         /* The last byte in the assignment is in W */
2910         if(areg <= GpsuedoStkPtr) {
2911           size--;
2912           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2913           offset++;
2914 //          debugf("receive from WREG\n", 0);
2915         }
2916       }
2917 //      GpsuedoStkPtr++;
2918       _G.stack_lat = AOP_SIZE(oper)-1;
2919
2920       while (size) {
2921         size--;
2922         GpsuedoStkPtr++;
2923         popaopidx(AOP(oper), offset, GpsuedoStkPtr);
2924 //        debugf("receive from STACK\n", 0);
2925         offset++;
2926       }
2927     }
2928 }
2929
2930
2931 /*-----------------------------------------------------------------*/
2932 /* genIpush - generate code for pushing this gets a little complex */
2933 /*-----------------------------------------------------------------*/
2934 static void genIpush (iCode *ic)
2935 {
2936 //  int size, offset=0;
2937
2938   FENTRY;
2939   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2940
2941   if(ic->parmPush) {
2942     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2943
2944     /* send to stack as normal */
2945     addSet(&_G.sendSet,ic);
2946 //    addSetHead(&_G.sendSet,ic);
2947     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2948   }
2949
2950         
2951 #if 0
2952     int size, offset = 0 ;
2953     char *l;
2954
2955
2956     /* if this is not a parm push : ie. it is spill push 
2957     and spill push is always done on the local stack */
2958     if (!ic->parmPush) {
2959
2960         /* and the item is spilt then do nothing */
2961         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2962             return ;
2963
2964         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2965         size = AOP_SIZE(IC_LEFT(ic));
2966         /* push it on the stack */
2967         while(size--) {
2968             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2969             if (*l == '#') {
2970                 MOVA(l);
2971                 l = "acc";
2972             }
2973             pic16_emitcode("push","%s",l);
2974         }
2975         return ;        
2976     }
2977
2978     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2979 #endif
2980 }
2981
2982 /*-----------------------------------------------------------------*/
2983 /* genIpop - recover the registers: can happen only for spilling   */
2984 /*-----------------------------------------------------------------*/
2985 static void genIpop (iCode *ic)
2986 {
2987   FENTRY;
2988   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2989 #if 0
2990     int size,offset ;
2991
2992
2993     /* if the temp was not pushed then */
2994     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2995         return ;
2996
2997     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2998     size = AOP_SIZE(IC_LEFT(ic));
2999     offset = (size-1);
3000     while (size--) 
3001         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3002                                    FALSE,TRUE));
3003
3004     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3005 #endif
3006 }
3007
3008 #if 0
3009 /*-----------------------------------------------------------------*/
3010 /* unsaverbank - restores the resgister bank from stack            */
3011 /*-----------------------------------------------------------------*/
3012 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3013 {
3014   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3015 #if 0
3016     int i;
3017     asmop *aop ;
3018     regs *r = NULL;
3019
3020     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3021     if (popPsw) {
3022         if (options.useXstack) {
3023             aop = newAsmop(0);
3024             r = getFreePtr(ic,&aop,FALSE);
3025             
3026             
3027             pic16_emitcode("mov","%s,_spx",r->name);
3028             pic16_emitcode("movx","a,@%s",r->name);
3029             pic16_emitcode("mov","psw,a");
3030             pic16_emitcode("dec","%s",r->name);
3031             
3032         }else
3033             pic16_emitcode ("pop","psw");
3034     }
3035
3036     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3037         if (options.useXstack) {       
3038             pic16_emitcode("movx","a,@%s",r->name);
3039             //pic16_emitcode("mov","(%s+%d),a",
3040             //       regspic16[i].base,8*bank+regspic16[i].offset);
3041             pic16_emitcode("dec","%s",r->name);
3042
3043         } else 
3044           pic16_emitcode("pop",""); //"(%s+%d)",
3045         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3046     }
3047
3048     if (options.useXstack) {
3049
3050         pic16_emitcode("mov","_spx,%s",r->name);
3051         pic16_freeAsmop(NULL,aop,ic,TRUE);
3052
3053     }
3054 #endif 
3055 }
3056
3057 /*-----------------------------------------------------------------*/
3058 /* saverbank - saves an entire register bank on the stack          */
3059 /*-----------------------------------------------------------------*/
3060 static void saverbank (int bank, iCode *ic, bool pushPsw)
3061 {
3062   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3063 #if 0
3064     int i;
3065     asmop *aop ;
3066     regs *r = NULL;
3067
3068     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3069     if (options.useXstack) {
3070
3071         aop = newAsmop(0);
3072         r = getFreePtr(ic,&aop,FALSE);  
3073         pic16_emitcode("mov","%s,_spx",r->name);
3074
3075     }
3076
3077     for (i = 0 ; i < pic16_nRegs ;i++) {
3078         if (options.useXstack) {
3079             pic16_emitcode("inc","%s",r->name);
3080             //pic16_emitcode("mov","a,(%s+%d)",
3081             //         regspic16[i].base,8*bank+regspic16[i].offset);
3082             pic16_emitcode("movx","@%s,a",r->name);           
3083         } else 
3084           pic16_emitcode("push","");// "(%s+%d)",
3085                      //regspic16[i].base,8*bank+regspic16[i].offset);
3086     }
3087     
3088     if (pushPsw) {
3089         if (options.useXstack) {
3090             pic16_emitcode("mov","a,psw");
3091             pic16_emitcode("movx","@%s,a",r->name);     
3092             pic16_emitcode("inc","%s",r->name);
3093             pic16_emitcode("mov","_spx,%s",r->name);       
3094             pic16_freeAsmop (NULL,aop,ic,TRUE);
3095             
3096         } else
3097             pic16_emitcode("push","psw");
3098         
3099         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3100     }
3101     ic->bankSaved = 1;
3102 #endif
3103 }
3104 #endif  /* 0 */
3105
3106
3107 static int wparamCmp(void *p1, void *p2)
3108 {
3109   return (!strcmp((char *)p1, (char *)p2));
3110 }
3111
3112 int inWparamList(char *s)
3113 {
3114   return isinSetWith(wparamList, s, wparamCmp);
3115
3116
3117
3118 /*-----------------------------------------------------------------*/
3119 /* genCall - generates a call statement                            */
3120 /*-----------------------------------------------------------------*/
3121 static void genCall (iCode *ic)
3122 {
3123   sym_link *ftype;   
3124   int stackParms=0;
3125   int use_wreg=0;
3126   int inwparam=0;
3127   char *fname;
3128   
3129     FENTRY;
3130
3131     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3132     /* if caller saves & we have not saved then */
3133 //    if (!ic->regsSaved)
3134 //      saveRegisters(ic);
3135
3136         /* initialise stackParms for IPUSH pushes */
3137 //      stackParms = psuedoStkPtr;
3138 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3139     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3140     inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3141
3142 #if 0
3143     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3144 #endif
3145
3146     /* if send set is not empty the assign */
3147     if (_G.sendSet) {
3148       iCode *sic;
3149       int psuedoStkPtr=-1; 
3150       int firstTimeThruLoop = 1;
3151
3152
3153         /* reverse sendSet if function is not reentrant */
3154         if(!IFFUNC_ISREENT(ftype))
3155           _G.sendSet = reverseSet(_G.sendSet);
3156
3157         /* First figure how many parameters are getting passed */
3158         stackParms = 0;
3159         use_wreg = 0;
3160         
3161         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3162           int size;
3163 //          int offset = 0;
3164
3165             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3166             size = AOP_SIZE(IC_LEFT(sic));
3167
3168             stackParms += size;
3169
3170             /* pass the last byte through WREG */
3171             if(inwparam) {
3172
3173               while (size--) {
3174                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3175                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3176                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3177
3178                 if(!firstTimeThruLoop) {
3179                   /* If this is not the first time we've been through the loop
3180                    * then we need to save the parameter in a temporary
3181                    * register. The last byte of the last parameter is
3182                    * passed in W. */
3183
3184                   pushw();
3185 //                  --psuedoStkPtr;             // sanity check
3186                   use_wreg = 1;
3187                 }
3188                 
3189                 firstTimeThruLoop=0;
3190
3191                 mov2w (AOP(IC_LEFT(sic)), size);
3192
3193 //                offset++;
3194               }
3195             } else {
3196               /* all arguments are passed via stack */
3197               use_wreg = 0;
3198
3199               while (size--) {
3200                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3201                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3202                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3203
3204 //                pushaop(AOP(IC_LEFT(sic)), size);
3205                 mov2w (AOP(IC_LEFT(sic)), size);
3206                 pushw();
3207               }
3208             }
3209
3210             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3211           }
3212
3213           if(inwparam) {
3214             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3215               pushw();  /* save last parameter to stack if functions has varargs */
3216               use_wreg = 0;
3217             } else
3218               use_wreg = 1;
3219           } else use_wreg = 0;
3220
3221           _G.stackRegSet = _G.sendSet;
3222           _G.sendSet = NULL;
3223     }
3224
3225     /* make the call */
3226     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3227
3228     GpsuedoStkPtr=0;
3229     
3230     /* if we need to assign a result value */
3231     if ((IS_ITEMP(IC_RESULT(ic))
3232           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3233               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3234         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3235
3236       _G.accInUse++;
3237       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3238       _G.accInUse--;
3239
3240       assignResultValue(IC_RESULT(ic), 1);
3241
3242       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3243                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3244                 
3245       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3246     }
3247
3248     if(!stackParms && ic->parmBytes) {
3249       stackParms = ic->parmBytes;
3250     }
3251       
3252     stackParms -= use_wreg;
3253     
3254     if(stackParms>0) {
3255       if(stackParms == 1) {
3256         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3257       } else {
3258         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3259         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3260       }
3261       if(STACK_MODEL_LARGE) {
3262         emitSKPNC;
3263         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3264       }
3265     }
3266
3267 #if 0
3268     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3269 #endif
3270
3271     /* adjust the stack for parameters if required */
3272 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3273
3274 #if 0
3275       /* if register bank was saved then pop them */
3276       if (ic->bankSaved)
3277         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3278
3279       /* if we hade saved some registers then unsave them */
3280       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3281         unsaveRegisters (ic);
3282 #endif
3283 }
3284
3285
3286
3287 /*-----------------------------------------------------------------*/
3288 /* genPcall - generates a call by pointer statement                */
3289 /*            new version, created from genCall - HJD              */
3290 /*-----------------------------------------------------------------*/
3291 static void genPcall (iCode *ic)
3292 {
3293   sym_link *ftype, *fntype;
3294   int stackParms=0;
3295   symbol *retlbl = newiTempLabel(NULL);
3296   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3297   
3298     FENTRY;
3299
3300     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3301     fntype = operandType( IC_LEFT(ic) )->next;
3302
3303     /* if send set is not empty the assign */
3304     if (_G.sendSet) {
3305       iCode *sic;
3306       int psuedoStkPtr=-1; 
3307
3308       /* reverse sendSet if function is not reentrant */
3309       if(!IFFUNC_ISREENT(fntype))
3310         _G.sendSet = reverseSet(_G.sendSet);
3311
3312       stackParms = 0;
3313       
3314       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3315         int size;
3316
3317           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3318           size = AOP_SIZE(IC_LEFT(sic));
3319           stackParms += size;
3320
3321           /* all parameters are passed via stack, since WREG is clobbered
3322            * by the calling sequence */
3323           while (size--) {
3324             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3325             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3326             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3327
3328             mov2w (AOP(IC_LEFT(sic)), size);
3329             pushw();
3330           }
3331
3332           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3333       }
3334
3335       _G.stackRegSet = _G.sendSet;
3336       _G.sendSet = NULL;
3337     }
3338
3339     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3340
3341     // push return address
3342     // push $ on return stack, then replace with retlbl
3343
3344     pic16_emitpcodeNULLop(POC_PUSH);
3345
3346     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3347     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3348     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3349     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3350     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3351     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3352
3353     /* make the call by writing the pointer into pc */
3354     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3355     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3356
3357     // note: MOVFF to PCL not allowed
3358     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3359     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3360
3361
3362     /* return address is here: (X) */
3363     pic16_emitpLabelFORCE(retlbl->key);
3364
3365     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3366
3367     GpsuedoStkPtr=0;
3368     /* if we need assign a result value */
3369     if ((IS_ITEMP(IC_RESULT(ic))
3370           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3371               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3372         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3373
3374       _G.accInUse++;
3375       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3376       _G.accInUse--;
3377
3378       assignResultValue(IC_RESULT(ic), 1);
3379
3380       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3381               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3382                 
3383       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3384     }
3385
3386 //    stackParms -= use_wreg;
3387     
3388     if(stackParms>0) {
3389       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3390       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3391       if(STACK_MODEL_LARGE) {
3392         /* this implies that stackParms < 256 !!! -- VR */
3393         emitSKPNC;
3394         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3395       }
3396     }
3397 }
3398
3399 /*-----------------------------------------------------------------*/
3400 /* resultRemat - result  is rematerializable                       */
3401 /*-----------------------------------------------------------------*/
3402 static int resultRemat (iCode *ic)
3403 {
3404   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3405   if (SKIP_IC(ic) || ic->op == IFX)
3406     return 0;
3407
3408   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3409     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3410     if (sym->remat && !POINTER_SET(ic)) 
3411       return 1;
3412   }
3413
3414   return 0;
3415 }
3416
3417 #if defined(__BORLANDC__) || defined(_MSC_VER)
3418 #define STRCASECMP stricmp
3419 #else
3420 #define STRCASECMP strcasecmp
3421 #endif
3422
3423 #if 0
3424 /*-----------------------------------------------------------------*/
3425 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3426 /*-----------------------------------------------------------------*/
3427 static bool inExcludeList(char *s)
3428 {
3429   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3430     int i =0;
3431     
3432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3433     if (options.excludeRegs[i] &&
3434     STRCASECMP(options.excludeRegs[i],"none") == 0)
3435         return FALSE ;
3436
3437     for ( i = 0 ; options.excludeRegs[i]; i++) {
3438         if (options.excludeRegs[i] &&
3439         STRCASECMP(s,options.excludeRegs[i]) == 0)
3440             return TRUE;
3441     }
3442     return FALSE ;
3443 }
3444 #endif
3445
3446 /*-----------------------------------------------------------------*/
3447 /* genFunction - generated code for function entry                 */
3448 /*-----------------------------------------------------------------*/
3449 static void genFunction (iCode *ic)
3450 {
3451   symbol *sym;
3452   sym_link *ftype;
3453   
3454     FENTRY;
3455     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3456
3457     pic16_labelOffset += (max_key+4);
3458     max_key=0;
3459     GpsuedoStkPtr=0;
3460     _G.nRegsSaved = 0;
3461         
3462     ftype = operandType(IC_LEFT(ic));
3463     sym = OP_SYMBOL(IC_LEFT(ic));
3464
3465     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3466       /* create an absolute section at the interrupt vector:
3467        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3468       symbol *asym;
3469       char asymname[128];
3470       pBlock *apb;
3471
3472         {
3473           int i, found=-1;
3474
3475             sym = OP_SYMBOL( IC_LEFT(ic));
3476             for(i=0;i<=2;i++) {
3477               if(interrupts[i]->name
3478                     && !STRCASECMP(interrupts[i]->name, sym->name)) {
3479                   found = i;
3480                   break;
3481               }
3482             }
3483                         
3484             if(found == -1) {
3485               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3486                             __FILE__, __LINE__, sym->name);
3487               assert( 0 );
3488             }
3489             _G.interruptvector = found;
3490         }
3491
3492         sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3493         asym = newSymbol(asymname, 0);
3494
3495         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3496         pic16_addpBlock( apb );
3497
3498         pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3499         pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3500         pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3501                 
3502         /* mark the end of this tiny function */
3503         pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3504
3505         {
3506           absSym *abSym;
3507
3508             abSym = Safe_calloc(1, sizeof(absSym));
3509             strcpy(abSym->name, asymname);
3510
3511             switch( _G.interruptvector ) {
3512               case 0: abSym->address = 0x000000; break;
3513               case 1: abSym->address = 0x000008; break;
3514               case 2: abSym->address = 0x000018; break;
3515             }
3516
3517             /* relocate interrupt vectors if needed */
3518             abSym->address += pic16_options.ivt_loc;
3519
3520             addSet(&absSymSet, abSym);
3521         }
3522     }
3523
3524     /* create the function header */
3525     pic16_emitcode(";","-----------------------------------------");
3526     pic16_emitcode(";"," function %s",sym->name);
3527     pic16_emitcode(";","-----------------------------------------");
3528
3529     pic16_emitcode("","%s:",sym->rname);
3530     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3531
3532
3533     {
3534       absSym *ab;
3535
3536         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3537           if(!strcmp(ab->name, sym->rname)) {
3538             pic16_pBlockConvert2Absolute(pb);
3539             break;
3540           }
3541         }
3542     }
3543
3544
3545     if(IFFUNC_ISNAKED(ftype)) {
3546       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3547       return;
3548     }
3549         
3550     /* if critical function then turn interrupts off */
3551     if (IFFUNC_ISCRITICAL(ftype)) {
3552       //pic16_emitcode("clr","ea");
3553     }
3554
3555     _G.fregsUsed = sym->regsUsed;
3556
3557     /* if this is an interrupt service routine then
3558      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3559     if (IFFUNC_ISISR(sym->type)) {
3560         _G.usefastretfie = 1;   /* use shadow registers by default */
3561         
3562         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3563         if(!(_G.interruptvector == 1)) {
3564           /* do not save WREG,STATUS,BSR for high priority interrupts
3565            * because they are stored in the hardware shadow registers already */
3566           _G.usefastretfie = 0;
3567           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3568           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3569           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3570         }
3571
3572         /* these should really be optimized somehow, because not all
3573          * interrupt handlers modify them */
3574         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3575         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3576         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3577         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3578         
3579 //        pic16_pBlockConvert2ISR(pb);
3580                 
3581     }
3582
3583     /* emit code to setup stack frame if user enabled,
3584      * and function is not main() */
3585          
3586     //fprintf(stderr, "function name: %s\n", sym->name);
3587     if(strcmp(sym->name, "main")) {
3588       if(1  /*!options.ommitFramePtr || sym->regsUsed*/) {
3589         /* setup the stack frame */
3590         if(STACK_MODEL_LARGE)
3591           pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3592         pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3593 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3594         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3595         if(STACK_MODEL_LARGE)
3596           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3597       }
3598     }
3599
3600     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3601           && sym->stack) {
3602
3603       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3604
3605       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3606       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3607       emitSKPNC;
3608       pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3609     }
3610           
3611     if(inWparamList(sym->name)) {
3612       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3613         _G.useWreg = 0;
3614       else
3615         _G.useWreg = 1;
3616     } else
3617       _G.useWreg = 0;
3618
3619     /* if callee-save to be used for this function
3620      * then save the registers being used in this function */
3621 //    if (IFFUNC_CALLEESAVES(sym->type))
3622     {
3623       int i;
3624
3625         /* if any registers used */
3626         if (sym->regsUsed) {
3627           /* save the registers used */
3628           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3629           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3630           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3631             if (bitVectBitValue(sym->regsUsed,i)) {
3632               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3633               _G.nRegsSaved++;
3634
3635               if(!pic16_regWithIdx(i)->wasUsed) {
3636                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3637                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3638                 pic16_regWithIdx(i)->wasUsed = 1;
3639               }
3640             }
3641           }
3642           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3643         }
3644     }
3645         
3646     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3647 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions               */
3652 /*-----------------------------------------------------------------*/
3653 static void genEndFunction (iCode *ic)
3654 {
3655   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3656
3657     FENTRY;
3658
3659     if(IFFUNC_ISNAKED(sym->type)) {
3660       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3661       return;
3662     }
3663
3664     _G.stack_lat = 0;
3665
3666     /* add code for ISCRITICAL */
3667     if(IFFUNC_ISCRITICAL(sym->type)) {
3668       /* if critical function, turn on interrupts */
3669       
3670       /* TODO: add code here -- VR */
3671     }
3672     
3673     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3674           && sym->stack) {
3675       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3676       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3677       emitSKPNC;
3678       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3679     }
3680
3681 //    sym->regsUsed = _G.fregsUsed;
3682     
3683     /* now we need to restore the registers */
3684     /* if any registers used */
3685     if (sym->regsUsed) {
3686       int i;
3687
3688         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3689         /* restore registers used */
3690         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3691         for ( i = sym->regsUsed->size; i >= 0; i--) {
3692           if (bitVectBitValue(sym->regsUsed,i)) {
3693             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3694             _G.nRegsSaved--;
3695           }
3696         }
3697         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3698
3699     }
3700
3701     if(strcmp(sym->name, "main")) {
3702       if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3703         /* restore stack frame */
3704         if(STACK_MODEL_LARGE)
3705           pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3706 //          pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3707         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3708 //        pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3709       }
3710     }
3711
3712     _G.useWreg = 0;
3713
3714     if (IFFUNC_ISISR(sym->type)) {
3715       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3716       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3717       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3718       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3719
3720       if(!(_G.interruptvector == 1)) {
3721         /* do not restore interrupt vector for WREG,STATUS,BSR
3722          * for high priority interrupt, see genFunction */
3723         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3724         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3725         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3726       }
3727       _G.interruptvector = 0;           /* sanity check */
3728
3729
3730       /* if debug then send end of function */
3731 /*      if (options.debug && currFunc)  */
3732       if (currFunc) {
3733         debugFile->writeEndFunction (currFunc, ic, 1);
3734       }
3735         
3736       if(_G.usefastretfie)
3737         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3738       else
3739         pic16_emitpcodeNULLop(POC_RETFIE);
3740
3741       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3742       
3743       _G.usefastretfie = 0;
3744       return;
3745     }
3746
3747     if (IFFUNC_ISCRITICAL(sym->type)) {
3748       pic16_emitcode("setb","ea");
3749     }
3750
3751     /* if debug then send end of function */
3752     if (currFunc) {
3753       debugFile->writeEndFunction (currFunc, ic, 1);
3754     }
3755
3756     /* insert code to restore stack frame, if user enabled it
3757      * and function is not main() */
3758          
3759
3760     pic16_emitpcodeNULLop(POC_RETURN);
3761
3762     /* Mark the end of a function */
3763     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3764 }
3765
3766
3767 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3768 {
3769   if(is_LitOp(op)) {
3770     unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3771       if(lit == 0) {
3772         pic16_emitpcode(POC_CLRF, dest);
3773       } else {
3774         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3775         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3776       }
3777   } else {
3778     if(dest->type == PO_WREG && (offset == 0)) {
3779       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3780       return;
3781     }
3782     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3783   }
3784 }
3785
3786 /*-----------------------------------------------------------------*/
3787 /* genRet - generate code for return statement                     */
3788 /*-----------------------------------------------------------------*/
3789 static void genRet (iCode *ic)
3790 {
3791   int size;
3792   operand *left;
3793
3794     FENTRY;
3795         /* if we have no return value then
3796          * just generate the "ret" */
3797         
3798         if (!IC_LEFT(ic)) 
3799                 goto jumpret;       
3800     
3801         /* we have something to return then
3802          * move the return value into place */
3803         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3804         size = AOP_SIZE(IC_LEFT(ic));
3805
3806         if(size <= 4) {
3807                 if(size>3) {
3808                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3809 //                      pic16_emitpcode(POC_MOVFF,
3810 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3811                 }
3812                 if(size>2) {
3813                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3814 //                      pic16_emitpcode(POC_MOVFF,
3815 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3816                 }
3817                 if(size>1) {
3818                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3819 //                      pic16_emitpcode(POC_MOVFF,
3820 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3821                 }
3822
3823 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3824
3825                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3826 //              pic16_emitpcode(POC_MOVFF,
3827 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3828
3829         } else {
3830                 /* >32-bits, setup stack and FSR0 */
3831                 while (size--) {
3832 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3833 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3834
3835                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3836
3837 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3838                         GpsuedoStkPtr++;
3839                 }
3840                         
3841                 /* setup FSR0 */
3842                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3843                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3844
3845                 if(STACK_MODEL_LARGE) {
3846                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3847                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3848                 } else {
3849                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3850                 }
3851         }
3852                                 
3853 #if 0
3854         /* old code, left here for reference -- VR */    
3855         while (size--) {
3856           char *l ;
3857
3858                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3859                         /* #NOCHANGE */
3860                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3861                         pic16_emitpcomment("push %s",l);
3862                         pushed++;
3863                 } else {
3864                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3865                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3866                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3867                         
3868                         if (strcmp(fReturn[offset],l)) {
3869                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3870                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3871                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3872                                 } else {
3873                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3874                                 }
3875                                 
3876                                 if(size) {
3877                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3878                                 }
3879                                 offset++;
3880                         }
3881                 }
3882         }    
3883
3884         if (pushed) {
3885                 while(pushed) {
3886                         pushed--;
3887                         if (strcmp(fReturn[pushed],"a"))
3888                                 pic16_emitcode("pop",fReturn[pushed]);
3889                         else
3890                                 pic16_emitcode("pop","acc");
3891                 }
3892         }
3893 #endif
3894
3895
3896         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3897     
3898 jumpret:
3899         /* generate a jump to the return label
3900          * if the next is not the return statement */
3901         if (!(ic->next && ic->next->op == LABEL
3902                 && IC_LABEL(ic->next) == returnLabel)) {
3903         
3904                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3905                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3906         }
3907 }
3908
3909 /*-----------------------------------------------------------------*/
3910 /* genLabel - generates a label                                    */
3911 /*-----------------------------------------------------------------*/
3912 static void genLabel (iCode *ic)
3913 {
3914   FENTRY;
3915
3916   /* special case never generate */
3917   if (IC_LABEL(ic) == entryLabel)
3918     return ;
3919
3920   pic16_emitpLabel(IC_LABEL(ic)->key);
3921 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3922 }
3923
3924 /*-----------------------------------------------------------------*/
3925 /* genGoto - generates a goto                                      */
3926 /*-----------------------------------------------------------------*/
3927 //tsd
3928 static void genGoto (iCode *ic)
3929 {
3930   FENTRY;
3931   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3932 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3933 }
3934
3935
3936 /*-----------------------------------------------------------------*/
3937 /* genMultbits :- multiplication of bits                           */
3938 /*-----------------------------------------------------------------*/
3939 static void genMultbits (operand *left, 
3940                          operand *right, 
3941                          operand *result)
3942 {
3943   FENTRY;
3944
3945   if(!pic16_sameRegs(AOP(result),AOP(right)))
3946     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3947
3948   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3949   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3950   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3951
3952 }
3953
3954
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8 bit multiplication & division                */
3957 /*-----------------------------------------------------------------*/
3958 static void genMultOneByte (operand *left,
3959                             operand *right,
3960                             operand *result)
3961 {
3962
3963   FENTRY;
3964   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3965   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3966
3967   /* (if two literals, the value is computed before) */
3968   /* if one literal, literal on the right */
3969   if (AOP_TYPE(left) == AOP_LIT){
3970     operand *t = right;
3971     right = left;
3972     left = t;
3973   }
3974
3975         /* size is already checked in genMult == 1 */
3976 //      size = AOP_SIZE(result);
3977
3978         if (AOP_TYPE(right) == AOP_LIT){
3979                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3980                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3981                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3982                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3983         } else {
3984                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3985                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3986                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3987                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3988         }
3989         
3990         pic16_genMult8X8_8 (left, right,result);
3991 }
3992
3993 /*-----------------------------------------------------------------*/
3994 /* genMultOneWord : 16 bit multiplication                          */
3995 /*-----------------------------------------------------------------*/
3996 static void genMultOneWord (operand *left,
3997                             operand *right,
3998                             operand *result)
3999 {
4000   FENTRY;
4001   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4002   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4003
4004   /* (if two literals, the value is computed before)
4005    * if one literal, literal on the right */
4006   if (AOP_TYPE(left) == AOP_LIT){
4007     operand *t = right;
4008     right = left;
4009     left = t;
4010   }
4011
4012   /* size is checked already == 2 */
4013 //  size = AOP_SIZE(result);
4014
4015   if (AOP_TYPE(right) == AOP_LIT) {
4016     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4017       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4018       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4019       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4020   } else {
4021     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4022       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4023       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4024       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4025   }
4026         
4027   pic16_genMult16X16_16(left, right,result);
4028 }
4029
4030 /*-----------------------------------------------------------------*/
4031 /* genMultOneLong : 32 bit multiplication                          */
4032 /*-----------------------------------------------------------------*/
4033 static void genMultOneLong (operand *left,
4034                             operand *right,
4035                             operand *result)
4036 {
4037   FENTRY;
4038   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4039   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4040
4041   /* (if two literals, the value is computed before)
4042    * if one literal, literal on the right */
4043   if (AOP_TYPE(left) == AOP_LIT){
4044     operand *t = right;
4045     right = left;
4046     left = t;
4047   }
4048
4049   /* size is checked already == 4 */
4050 //  size = AOP_SIZE(result);
4051
4052   if (AOP_TYPE(right) == AOP_LIT) {
4053     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4054         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4055         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4056         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4057   } else {
4058     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4059         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4060         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4061         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4062   }
4063         
4064   pic16_genMult32X32_32(left, right,result);
4065 }
4066
4067
4068
4069 /*-----------------------------------------------------------------*/
4070 /* genMult - generates code for multiplication                     */
4071 /*-----------------------------------------------------------------*/
4072 static void genMult (iCode *ic)
4073 {
4074   operand *left = IC_LEFT(ic);
4075   operand *right = IC_RIGHT(ic);
4076   operand *result= IC_RESULT(ic);   
4077
4078     FENTRY;
4079         /* assign the amsops */
4080         pic16_aopOp (left,ic,FALSE);
4081         pic16_aopOp (right,ic,FALSE);
4082         pic16_aopOp (result,ic,TRUE);
4083
4084         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4085
4086         /* special cases first *
4087         * both are bits */
4088         if (AOP_TYPE(left) == AOP_CRY
4089                 && AOP_TYPE(right)== AOP_CRY) {
4090                 genMultbits(left,right,result);
4091           goto release ;
4092         }
4093
4094         /* if both are of size == 1 */
4095         if(AOP_SIZE(left) == 1
4096                 && AOP_SIZE(right) == 1) {
4097                 genMultOneByte(left,right,result);
4098           goto release ;
4099         }
4100
4101         /* if both are of size == 2 */
4102         if(AOP_SIZE(left) == 2
4103                 && AOP_SIZE(right) == 2) {
4104                 genMultOneWord(left, right, result);
4105           goto release;
4106         }
4107         
4108         /* if both are of size == 4 */
4109         if(AOP_SIZE(left) == 4
4110                 && AOP_SIZE(right) == 4) {
4111                 genMultOneLong(left, right, result);
4112           goto release;
4113         }
4114         
4115         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4116
4117
4118         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4119         /* should have been converted to function call */
4120         assert(0) ;
4121
4122 release :
4123         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4124         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4125         pic16_freeAsmop(result,NULL,ic,TRUE); 
4126 }
4127
4128 /*-----------------------------------------------------------------*/
4129 /* genDivbits :- division of bits                                  */
4130 /*-----------------------------------------------------------------*/
4131 static void genDivbits (operand *left, 
4132                         operand *right, 
4133                         operand *result)
4134 {
4135   char *l;
4136
4137     FENTRY;
4138     /* the result must be bit */    
4139     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4140     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4141
4142     MOVA(l);    
4143
4144     pic16_emitcode("div","ab");
4145     pic16_emitcode("rrc","a");
4146     pic16_aopPut(AOP(result),"c",0);
4147 }
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genDivOneByte : 8 bit division                                  */
4151 /*-----------------------------------------------------------------*/
4152 static void genDivOneByte (operand *left,
4153                            operand *right,
4154                            operand *result)
4155 {
4156   sym_link *opetype = operandType(result);
4157   char *l ;
4158   symbol *lbl ;
4159   int size,offset;
4160
4161         /* result = divident / divisor
4162          * - divident may be a register or a literal,
4163          * - divisor may be a register or a literal,
4164          * so there are 3 cases (literal / literal is optimized
4165          * by the front-end) to handle.
4166          * In addition we must handle signed and unsigned, which
4167          * result in 6 final different cases -- VR */
4168
4169     FENTRY;
4170     
4171     size = AOP_SIZE(result) - 1;
4172     offset = 1;
4173     /* signed or unsigned */
4174     if (SPEC_USIGN(opetype)) {
4175       pCodeOp *pct1,    /* count */
4176                 *pct2,  /* reste */
4177                 *pct3;  /* temp */
4178       symbol *label1, *label2, *label3;;
4179
4180
4181         /* unsigned is easy */
4182
4183         pct1 = pic16_popGetTempReg(1);
4184         pct2 = pic16_popGetTempReg(1);
4185         pct3 = pic16_popGetTempReg(1);
4186         
4187         label1 = newiTempLabel(NULL);
4188         label2 = newiTempLabel(NULL);
4189         label3 = newiTempLabel(NULL);
4190
4191         /* the following algorithm is extracted from divuint.c */
4192
4193         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4194         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4195         
4196         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4197
4198         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4199         
4200         pic16_emitpLabel(label1->key);
4201         
4202         emitCLRC;
4203         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4204
4205
4206         emitCLRC;
4207         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4208         
4209
4210         emitSKPNC;
4211         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4212         
4213         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4215         
4216         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4217         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4218         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4219         
4220         pic16_emitpLabel( label3->key );
4221         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4222         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4223         
4224         
4225
4226         pic16_emitpLabel(label2->key);
4227         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4228         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4229         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4230         
4231         /* result is in wreg */
4232         if(AOP_TYPE(result) != AOP_ACC)
4233                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4234
4235         pic16_popReleaseTempReg( pct3, 1);
4236         pic16_popReleaseTempReg( pct2, 1);
4237         pic16_popReleaseTempReg( pct1, 1);
4238
4239         return ;
4240     }
4241
4242     /* signed is a little bit more difficult */
4243
4244     /* save the signs of the operands */
4245     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4246     MOVA(l);    
4247     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4248     pic16_emitcode("push","acc"); /* save it on the stack */
4249
4250     /* now sign adjust for both left & right */
4251     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4252     MOVA(l);       
4253     lbl = newiTempLabel(NULL);
4254     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4255     pic16_emitcode("cpl","a");   
4256     pic16_emitcode("inc","a");
4257     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4258     pic16_emitcode("mov","b,a");
4259
4260     /* sign adjust left side */
4261     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4262     MOVA(l);
4263
4264     lbl = newiTempLabel(NULL);
4265     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4266     pic16_emitcode("cpl","a");
4267     pic16_emitcode("inc","a");
4268     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4269
4270     /* now the division */
4271     pic16_emitcode("div","ab");
4272     /* we are interested in the lower order
4273     only */
4274     pic16_emitcode("mov","b,a");
4275     lbl = newiTempLabel(NULL);
4276     pic16_emitcode("pop","acc");   
4277     /* if there was an over flow we don't 
4278     adjust the sign of the result */
4279     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4280     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4281     CLRC;
4282     pic16_emitcode("clr","a");
4283     pic16_emitcode("subb","a,b");
4284     pic16_emitcode("mov","b,a");
4285     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4286
4287     /* now we are done */
4288     pic16_aopPut(AOP(result),"b",0);
4289     if(size > 0){
4290         pic16_emitcode("mov","c,b.7");
4291         pic16_emitcode("subb","a,acc");   
4292     }
4293     while (size--)
4294         pic16_aopPut(AOP(result),"a",offset++);
4295
4296 }
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genDiv - generates code for division                            */
4300 /*-----------------------------------------------------------------*/
4301 static void genDiv (iCode *ic)
4302 {
4303     operand *left = IC_LEFT(ic);
4304     operand *right = IC_RIGHT(ic);
4305     operand *result= IC_RESULT(ic);   
4306
4307
4308         /* Division is a very lengthy algorithm, so it is better
4309          * to call support routines than inlining algorithm.
4310          * Division functions written here just in case someone
4311          * wants to inline and not use the support libraries -- VR */
4312
4313     FENTRY;
4314     
4315     /* assign the amsops */
4316     pic16_aopOp (left,ic,FALSE);
4317     pic16_aopOp (right,ic,FALSE);
4318     pic16_aopOp (result,ic,TRUE);
4319
4320     /* special cases first */
4321     /* both are bits */
4322     if (AOP_TYPE(left) == AOP_CRY &&
4323         AOP_TYPE(right)== AOP_CRY) {
4324         genDivbits(left,right,result);
4325         goto release ;
4326     }
4327
4328     /* if both are of size == 1 */
4329     if (AOP_SIZE(left) == 1 &&
4330         AOP_SIZE(right) == 1 ) {
4331         genDivOneByte(left,right,result);
4332         goto release ;
4333     }
4334
4335     /* should have been converted to function call */
4336     assert(0);
4337 release :
4338     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4339     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340     pic16_freeAsmop(result,NULL,ic,TRUE); 
4341 }
4342
4343 /*-----------------------------------------------------------------*/
4344 /* genModbits :- modulus of bits                                   */
4345 /*-----------------------------------------------------------------*/
4346 static void genModbits (operand *left, 
4347                         operand *right, 
4348                         operand *result)
4349 {
4350   char *l;
4351
4352     FENTRY;  
4353     
4354     werror(W_POSSBUG2, __FILE__, __LINE__);
4355     /* the result must be bit */    
4356     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4357     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4358
4359     MOVA(l);       
4360
4361     pic16_emitcode("div","ab");
4362     pic16_emitcode("mov","a,b");
4363     pic16_emitcode("rrc","a");
4364     pic16_aopPut(AOP(result),"c",0);
4365 }
4366
4367 /*-----------------------------------------------------------------*/
4368 /* genModOneByte : 8 bit modulus                                   */
4369 /*-----------------------------------------------------------------*/
4370 static void genModOneByte (operand *left,
4371                            operand *right,
4372                            operand *result)
4373 {
4374   sym_link *opetype = operandType(result);
4375   char *l ;
4376   symbol *lbl ;
4377
4378     FENTRY;
4379     werror(W_POSSBUG2, __FILE__, __LINE__);
4380
4381     /* signed or unsigned */
4382     if (SPEC_USIGN(opetype)) {
4383         /* unsigned is easy */
4384         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4385         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4386         MOVA(l);    
4387         pic16_emitcode("div","ab");
4388         pic16_aopPut(AOP(result),"b",0);
4389         return ;
4390     }
4391
4392     /* signed is a little bit more difficult */
4393
4394     /* save the signs of the operands */
4395     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4396     MOVA(l);
4397
4398     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4399     pic16_emitcode("push","acc"); /* save it on the stack */
4400
4401     /* now sign adjust for both left & right */
4402     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4403     MOVA(l);
4404
4405     lbl = newiTempLabel(NULL);
4406     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4407     pic16_emitcode("cpl","a");   
4408     pic16_emitcode("inc","a");
4409     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4410     pic16_emitcode("mov","b,a"); 
4411
4412     /* sign adjust left side */
4413     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4414     MOVA(l);
4415
4416     lbl = newiTempLabel(NULL);
4417     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4418     pic16_emitcode("cpl","a");   
4419     pic16_emitcode("inc","a");
4420     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4421
4422     /* now the multiplication */
4423     pic16_emitcode("div","ab");
4424     /* we are interested in the lower order
4425     only */
4426     lbl = newiTempLabel(NULL);
4427     pic16_emitcode("pop","acc");   
4428     /* if there was an over flow we don't 
4429     adjust the sign of the result */
4430     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4431     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4432     CLRC ;
4433     pic16_emitcode("clr","a");
4434     pic16_emitcode("subb","a,b");
4435     pic16_emitcode("mov","b,a");
4436     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4437
4438     /* now we are done */
4439     pic16_aopPut(AOP(result),"b",0);
4440
4441 }
4442
4443 /*-----------------------------------------------------------------*/
4444 /* genMod - generates code for division                            */
4445 /*-----------------------------------------------------------------*/
4446 static void genMod (iCode *ic)
4447 {
4448   operand *left = IC_LEFT(ic);
4449   operand *right = IC_RIGHT(ic);
4450   operand *result= IC_RESULT(ic);  
4451
4452     FENTRY;
4453     
4454     /* assign the amsops */
4455     pic16_aopOp (left,ic,FALSE);
4456     pic16_aopOp (right,ic,FALSE);
4457     pic16_aopOp (result,ic,TRUE);
4458
4459     /* special cases first */
4460     /* both are bits */
4461     if (AOP_TYPE(left) == AOP_CRY &&
4462         AOP_TYPE(right)== AOP_CRY) {
4463         genModbits(left,right,result);
4464         goto release ;
4465     }
4466
4467     /* if both are of size == 1 */
4468     if (AOP_SIZE(left) == 1 &&
4469         AOP_SIZE(right) == 1 ) {
4470         genModOneByte(left,right,result);
4471         goto release ;
4472     }
4473
4474     /* should have been converted to function call */
4475     assert(0);
4476
4477 release :
4478     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4479     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4480     pic16_freeAsmop(result,NULL,ic,TRUE); 
4481 }
4482
4483 /*-----------------------------------------------------------------*/
4484 /* genIfxJump :- will create a jump depending on the ifx           */
4485 /*-----------------------------------------------------------------*/
4486 /*
4487   note: May need to add parameter to indicate when a variable is in bit space.
4488 */
4489 static void genIfxJump (iCode *ic, char *jval)
4490 {
4491   FENTRY;
4492   
4493     /* if true label then we jump if condition
4494     supplied is true */
4495     if ( IC_TRUE(ic) ) {
4496
4497         if(strcmp(jval,"a") == 0)
4498           emitSKPZ;
4499         else if (strcmp(jval,"c") == 0)
4500           emitSKPC;
4501         else {
4502           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4503           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4504         }
4505
4506         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4507         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4508
4509     }
4510     else {
4511         /* false label is present */
4512         if(strcmp(jval,"a") == 0)
4513           emitSKPNZ;
4514         else if (strcmp(jval,"c") == 0)
4515           emitSKPNC;
4516         else {
4517           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4518           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4519         }
4520
4521         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4522         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4523
4524     }
4525
4526
4527     /* mark the icode as generated */
4528     ic->generated = 1;
4529 }
4530
4531 #if 0
4532 // not needed ATM
4533
4534 /*-----------------------------------------------------------------*/
4535 /* genSkip                                                         */
4536 /*-----------------------------------------------------------------*/
4537 static void genSkip(iCode *ifx,int status_bit)
4538 {
4539   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4540   if(!ifx)
4541     return;
4542
4543   if ( IC_TRUE(ifx) ) {
4544     switch(status_bit) {
4545     case 'z':
4546       emitSKPNZ;
4547       break;
4548
4549     case 'c':
4550       emitSKPNC;
4551       break;
4552
4553     case 'd':
4554       emitSKPDC;
4555       break;
4556
4557     }
4558
4559     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4560     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4561
4562   } else {
4563
4564     switch(status_bit) {
4565
4566     case 'z':
4567       emitSKPZ;
4568       break;
4569
4570     case 'c':
4571       emitSKPC;
4572       break;
4573
4574     case 'd':
4575       emitSKPDC;
4576       break;
4577     }
4578     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4579     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4580
4581   }
4582
4583 }
4584 #endif
4585
4586 /*-----------------------------------------------------------------*/
4587 /* genSkipc                                                        */
4588 /*-----------------------------------------------------------------*/
4589 static void genSkipc(resolvedIfx *rifx)
4590 {
4591   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4592   
4593   if(!rifx)
4594     return;
4595
4596   if(rifx->condition)
4597     emitSKPC;
4598   else
4599     emitSKPNC;
4600
4601   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4602   rifx->generated = 1;
4603 }
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genSkipz2                                                       */
4607 /*-----------------------------------------------------------------*/
4608 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4609 {
4610   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4611   
4612   if(!rifx)
4613     return;
4614
4615   if( (rifx->condition ^ invert_condition) & 1)
4616     emitSKPZ;
4617   else
4618     emitSKPNZ;
4619
4620   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4621   rifx->generated = 1;
4622 }
4623
4624 #if 0
4625 /*-----------------------------------------------------------------*/
4626 /* genSkipz                                                        */
4627 /*-----------------------------------------------------------------*/
4628 static void genSkipz(iCode *ifx, int condition)
4629 {
4630   if(!ifx)
4631     return;
4632
4633   if(condition)
4634     emitSKPNZ;
4635   else
4636     emitSKPZ;
4637
4638   if ( IC_TRUE(ifx) )
4639     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4640   else
4641     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4642
4643   if ( IC_TRUE(ifx) )
4644     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4645   else
4646     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4647
4648 }
4649 #endif
4650
4651 /*-----------------------------------------------------------------*/
4652 /* genSkipCond                                                     */
4653 /*-----------------------------------------------------------------*/
4654 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4655 {
4656   if(!rifx)
4657     return;
4658
4659   if(rifx->condition)
4660     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4661   else
4662     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4663
4664
4665   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4666   rifx->generated = 1;
4667 }
4668
4669 #if 0
4670 /*-----------------------------------------------------------------*/
4671 /* genChkZeroes :- greater or less than comparison                 */
4672 /*     For each byte in a literal that is zero, inclusive or the   */
4673 /*     the corresponding byte in the operand with W                */
4674 /*     returns true if any of the bytes are zero                   */
4675 /*-----------------------------------------------------------------*/
4676 static int genChkZeroes(operand *op, int lit,  int size)
4677 {
4678
4679   int i;
4680   int flag =1;
4681
4682   while(size--) {
4683     i = (lit >> (size*8)) & 0xff;
4684
4685     if(i==0) {
4686       if(flag) 
4687         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4688       else
4689         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4690       flag = 0;
4691     }
4692   }
4693
4694   return (flag==0);
4695 }
4696 #endif
4697
4698 /*-----------------------------------------------------------------*/
4699 /* genCmp :- greater or less than comparison                       */
4700 /*-----------------------------------------------------------------*/
4701 #if 1
4702                 /* { */
4703       /* original code */
4704 static void genCmp (operand *left,operand *right,
4705                     operand *result, iCode *ifx, int sign)
4706 {
4707   int size; //, offset = 0 ;
4708   unsigned long lit = 0L,i = 0;
4709   resolvedIfx rFalseIfx;
4710   //  resolvedIfx rTrueIfx;
4711   symbol *truelbl;
4712   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4713 /*
4714   if(ifx) {
4715     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4716     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4717   }
4718 */
4719
4720   FENTRY;
4721   
4722   resolveIfx(&rFalseIfx,ifx);
4723   truelbl  = newiTempLabel(NULL);
4724   size = max(AOP_SIZE(left),AOP_SIZE(right));
4725
4726   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4727
4728 #define _swapp
4729
4730   /* if literal is on the right then swap with left */
4731   if ((AOP_TYPE(right) == AOP_LIT)) {
4732     operand *tmp = right ;
4733     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4734     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4735 #ifdef _swapp
4736
4737     lit = (lit - 1) & mask;
4738     right = left;
4739     left = tmp;
4740     rFalseIfx.condition ^= 1;
4741 #endif
4742
4743   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4744     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4745   }
4746
4747
4748   //if(IC_TRUE(ifx) == NULL)
4749   /* if left & right are bit variables */
4750   if (AOP_TYPE(left) == AOP_CRY &&
4751       AOP_TYPE(right) == AOP_CRY ) {
4752     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4753     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4754   } else {
4755     /* subtract right from left if at the
4756        end the carry flag is set then we know that
4757        left is greater than right */
4758
4759     symbol *lbl  = newiTempLabel(NULL);
4760
4761 #if 0
4762         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4763                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4764 #endif
4765
4766 #ifndef _swapp
4767     if(AOP_TYPE(right) == AOP_LIT) {
4768
4769       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4770
4771       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4772
4773       /* special cases */
4774
4775       if(lit == 0) {
4776
4777         if(sign != 0) 
4778           genSkipCond(&rFalseIfx,left,size-1,7);
4779         else 
4780           /* no need to compare to 0...*/
4781           /* NOTE: this is a de-generate compare that most certainly 
4782            *       creates some dead code. */
4783           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4784
4785         if(ifx) ifx->generated = 1;
4786         return;
4787
4788       }
4789       size--;
4790
4791       if(size == 0) {
4792         //i = (lit >> (size*8)) & 0xff;
4793         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4794         
4795         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4796
4797         i = ((0-lit) & 0xff);
4798         if(sign) {
4799           if( i == 0x81) { 
4800             /* lit is 0x7f, all signed chars are less than
4801              * this except for 0x7f itself */
4802             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4803             genSkipz2(&rFalseIfx,0);
4804           } else {
4805             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4806             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4807             genSkipc(&rFalseIfx);
4808           }
4809
4810         } else {
4811           if(lit == 1) {
4812             genSkipz2(&rFalseIfx,1);
4813           } else {
4814             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4815             genSkipc(&rFalseIfx);
4816           }
4817         }
4818
4819         if(ifx) ifx->generated = 1;
4820         return;
4821       }
4822
4823       /* chars are out of the way. now do ints and longs */
4824
4825
4826       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4827         
4828       /* special cases */
4829
4830       if(sign) {
4831
4832         if(lit == 0) {
4833           genSkipCond(&rFalseIfx,left,size,7);
4834           if(ifx) ifx->generated = 1;
4835           return;
4836         }
4837
4838         if(lit <0x100) {
4839           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4840
4841           //rFalseIfx.condition ^= 1;
4842           //genSkipCond(&rFalseIfx,left,size,7);
4843           //rFalseIfx.condition ^= 1;
4844
4845           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4846           if(rFalseIfx.condition)
4847             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4848           else
4849             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4850
4851           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4852           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4853           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4854
4855           while(size > 1)
4856             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4857
4858           if(rFalseIfx.condition) {
4859             emitSKPZ;
4860             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4861
4862           } else {
4863             emitSKPNZ;
4864           }
4865
4866           genSkipc(&rFalseIfx);
4867           pic16_emitpLabel(truelbl->key);
4868           if(ifx) ifx->generated = 1;
4869           return;
4870
4871         }
4872
4873         if(size == 1) {
4874
4875           if( (lit & 0xff) == 0) {
4876             /* lower byte is zero */
4877             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4878             i = ((lit >> 8) & 0xff) ^0x80;
4879             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4880             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4881             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4882             genSkipc(&rFalseIfx);
4883
4884
4885             if(ifx) ifx->generated = 1;
4886             return;
4887
4888           }
4889         } else {
4890           /* Special cases for signed longs */
4891           if( (lit & 0xffffff) == 0) {
4892             /* lower byte is zero */
4893             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4894             i = ((lit >> 8*3) & 0xff) ^0x80;
4895             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4896             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4897             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4898             genSkipc(&rFalseIfx);
4899
4900
4901             if(ifx) ifx->generated = 1;
4902             return;
4903
4904           }
4905
4906         }
4907
4908
4909         if(lit & (0x80 << (size*8))) {
4910           /* lit is negative */
4911           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4912
4913           //genSkipCond(&rFalseIfx,left,size,7);
4914
4915           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4916
4917           if(rFalseIfx.condition)
4918             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4919           else
4920             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4921
4922
4923         } else {
4924           /* lit is positive */
4925           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4926           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4927           if(rFalseIfx.condition)
4928             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4929           else
4930             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4931
4932         }
4933
4934         /*
4935           This works, but is only good for ints.
4936           It also requires a "known zero" register.
4937           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4938           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4939           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4940           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4941           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4942           genSkipc(&rFalseIfx);
4943
4944           pic16_emitpLabel(truelbl->key);
4945           if(ifx) ifx->generated = 1;
4946           return;
4947         **/
4948           
4949         /* There are no more special cases, so perform a general compare */
4950   
4951         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4952         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4953
4954         while(size--) {
4955
4956           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4957           emitSKPNZ;
4958           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4959         }
4960         //rFalseIfx.condition ^= 1;
4961         genSkipc(&rFalseIfx);
4962
4963         pic16_emitpLabel(truelbl->key);
4964
4965         if(ifx) ifx->generated = 1;
4966         return;
4967
4968
4969       }
4970
4971
4972       /* sign is out of the way. So now do an unsigned compare */
4973       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4974
4975
4976       /* General case - compare to an unsigned literal on the right.*/
4977
4978       i = (lit >> (size*8)) & 0xff;
4979       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4980       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4981       while(size--) {
4982         i = (lit >> (size*8)) & 0xff;
4983
4984         if(i) {
4985           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4986           emitSKPNZ;
4987           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4988         } else {
4989           /* this byte of the lit is zero, 
4990            *if it's not the last then OR in the variable */
4991           if(size)
4992             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4993         }
4994       }
4995
4996
4997       pic16_emitpLabel(lbl->key);
4998 //      pic16_emitpLabel(truelbl->key);
4999       //if(emitFinalCheck)
5000       genSkipc(&rFalseIfx);
5001       if(sign)
5002         pic16_emitpLabel(truelbl->key);
5003
5004       if(ifx) ifx->generated = 1;
5005       return;
5006
5007
5008     }
5009 #endif  // _swapp
5010
5011     if(AOP_TYPE(left) == AOP_LIT) {
5012       //symbol *lbl = newiTempLabel(NULL);
5013
5014       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5015
5016
5017       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5018
5019       /* Special cases */
5020       if((lit == 0) && (sign == 0)){
5021
5022         size--;
5023         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5024         while(size) 
5025           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5026
5027         genSkipz2(&rFalseIfx,0);
5028         if(ifx) ifx->generated = 1;
5029         return;
5030       }
5031
5032       if(size==1) {
5033         /* Special cases */
5034         lit &= 0xff;
5035         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5036           /* degenerate compare can never be true */
5037           if(rFalseIfx.condition == 0)
5038             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5039
5040           if(ifx) ifx->generated = 1;
5041           return;
5042         }
5043
5044         if(sign) {
5045           /* signed comparisons to a literal byte */
5046
5047           int lp1 = (lit+1) & 0xff;
5048
5049           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5050           switch (lp1) {
5051           case 0:
5052             rFalseIfx.condition ^= 1;
5053             genSkipCond(&rFalseIfx,right,0,7);
5054             break;
5055           case 0x7f:
5056             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5057             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5058             genSkipz2(&rFalseIfx,1);
5059             break;
5060           default:
5061             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5062             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5063             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5064             rFalseIfx.condition ^= 1;
5065             genSkipc(&rFalseIfx);
5066             break;
5067           }
5068         } else {
5069           /* unsigned comparisons to a literal byte */
5070
5071           switch(lit & 0xff ) {
5072           case 0:
5073             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5074             genSkipz2(&rFalseIfx,0);
5075             break;
5076           case 0x7f:
5077             rFalseIfx.condition ^= 1;
5078             genSkipCond(&rFalseIfx,right,0,7);
5079             break;
5080
5081           default:
5082             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5083             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5084             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5085             rFalseIfx.condition ^= 1;
5086             if (AOP_TYPE(result) == AOP_CRY)
5087               genSkipc(&rFalseIfx);
5088             else {
5089               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5090               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5091             }         
5092             break;
5093           }
5094         }
5095
5096         if(ifx) ifx->generated = 1;
5097         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5098                 goto check_carry;
5099         return;
5100
5101       } else {
5102
5103         /* Size is greater than 1 */
5104
5105         if(sign) {
5106           int lp1 = lit+1;
5107
5108           size--;
5109
5110           if(lp1 == 0) {
5111             /* this means lit = 0xffffffff, or -1 */
5112
5113
5114             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5115             rFalseIfx.condition ^= 1;
5116             genSkipCond(&rFalseIfx,right,size,7);
5117             if(ifx) ifx->generated = 1;
5118
5119             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5120               goto check_carry;
5121
5122             return;
5123           }
5124
5125           if(lit == 0) {
5126             int s = size;
5127
5128             if(rFalseIfx.condition) {
5129               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5130               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5131             }
5132
5133             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5134             while(size--)
5135               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5136
5137
5138             emitSKPZ;
5139             if(rFalseIfx.condition) {
5140               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5141               pic16_emitpLabel(truelbl->key);
5142             }else {
5143               rFalseIfx.condition ^= 1;
5144               genSkipCond(&rFalseIfx,right,s,7);
5145             }
5146
5147             if(ifx) ifx->generated = 1;
5148
5149             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5150               goto check_carry;
5151
5152             return;
5153           }
5154
5155           if((size == 1) &&  (0 == (lp1&0xff))) {
5156             /* lower byte of signed word is zero */
5157             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5158             i = ((lp1 >> 8) & 0xff) ^0x80;
5159             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5160             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5161             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5162             rFalseIfx.condition ^= 1;
5163             genSkipc(&rFalseIfx);
5164
5165
5166             if(ifx) ifx->generated = 1;
5167
5168             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5169               goto check_carry;
5170
5171             return;
5172           }
5173
5174           if(lit & (0x80 << (size*8))) {
5175             /* Lit is less than zero */
5176             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5177             //rFalseIfx.condition ^= 1;
5178             //genSkipCond(&rFalseIfx,left,size,7);
5179             //rFalseIfx.condition ^= 1;
5180             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5181             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5182
5183             if(rFalseIfx.condition)
5184               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5185             else
5186               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5187
5188
5189           } else {
5190             /* Lit is greater than or equal to zero */
5191             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5192             //rFalseIfx.condition ^= 1;
5193             //genSkipCond(&rFalseIfx,right,size,7);
5194             //rFalseIfx.condition ^= 1;
5195
5196             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5197             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5198
5199             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5200             if(rFalseIfx.condition)
5201               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5202             else
5203               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5204
5205           }
5206
5207           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5208           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5209
5210           while(size--) {
5211
5212             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5213             emitSKPNZ;
5214             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5215           }
5216           rFalseIfx.condition ^= 1;
5217           //rFalseIfx.condition = 1;
5218           genSkipc(&rFalseIfx);
5219
5220           pic16_emitpLabel(truelbl->key);
5221
5222           if(ifx) ifx->generated = 1;
5223
5224
5225           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5226             goto check_carry;
5227
5228           return;
5229           // end of if (sign)
5230         } else {
5231
5232           /* compare word or long to an unsigned literal on the right.*/
5233
5234
5235           size--;
5236           if(lit < 0xff) {
5237             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5238             switch (lit) {
5239             case 0:
5240               break; /* handled above */
5241 /*
5242             case 0xff:
5243               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5244               while(size--)
5245                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5246               genSkipz2(&rFalseIfx,0);
5247               break;
5248 */
5249             default:
5250               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5251               while(--size)
5252                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5253
5254               emitSKPZ;
5255               if(rFalseIfx.condition)
5256                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5257               else
5258                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5259
5260
5261               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5262               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5263
5264               rFalseIfx.condition ^= 1;
5265               genSkipc(&rFalseIfx);
5266             }
5267
5268             pic16_emitpLabel(truelbl->key);
5269
5270             if(ifx) ifx->generated = 1;
5271
5272             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5273               goto check_carry;
5274
5275             return;
5276           }
5277
5278
5279           lit++;
5280           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5281           i = (lit >> (size*8)) & 0xff;
5282
5283           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5284           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5285
5286           while(size--) {
5287             i = (lit >> (size*8)) & 0xff;
5288
5289             if(i) {
5290               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5291               emitSKPNZ;
5292               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5293             } else {
5294               /* this byte of the lit is zero, 
5295                * if it's not the last then OR in the variable */
5296               if(size)
5297                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5298             }
5299           }
5300
5301
5302           pic16_emitpLabel(lbl->key);
5303
5304           rFalseIfx.condition ^= 1;
5305
5306           genSkipc(&rFalseIfx);
5307         }
5308
5309         if(sign)
5310           pic16_emitpLabel(truelbl->key);
5311         if(ifx) ifx->generated = 1;
5312
5313             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5314               goto check_carry;
5315
5316         return;
5317       }
5318     }
5319     /* Compare two variables */
5320
5321     DEBUGpic16_emitcode(";sign","%d",sign);
5322
5323     size--;
5324     if(sign) {
5325       /* Sigh. thus sucks... */
5326       if(size) {
5327         pCodeOp *pctemp;
5328         
5329         pctemp = pic16_popGetTempReg(1);
5330         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5331         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5332         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5333         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5334         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5335         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5336         pic16_popReleaseTempReg(pctemp, 1);
5337       } else {
5338         /* Signed char comparison */
5339         /* Special thanks to Nikolai Golovchenko for this snippet */
5340         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5341         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5342         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5343         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5344         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5345         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5346
5347         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5348         genSkipc(&rFalseIfx);
5349           
5350         if(ifx) ifx->generated = 1;
5351
5352             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5353               goto check_carry;
5354
5355         return;
5356       }
5357
5358     } else {
5359
5360       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5361       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5362     }
5363
5364
5365     /* The rest of the bytes of a multi-byte compare */
5366     while (size) {
5367
5368       emitSKPZ;
5369       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5370       size--;
5371
5372       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5373       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374
5375
5376     }
5377
5378     pic16_emitpLabel(lbl->key);
5379
5380     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5381     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5382         (AOP_TYPE(result) == AOP_REG)) {
5383       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5384       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5385     } else {
5386       genSkipc(&rFalseIfx);
5387     }         
5388     //genSkipc(&rFalseIfx);
5389     if(ifx) ifx->generated = 1;
5390
5391
5392             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5393               goto check_carry;
5394
5395     return;
5396
5397   }
5398
5399 check_carry:
5400   if ((AOP_TYPE(result) != AOP_CRY) 
5401         && AOP_SIZE(result)) {
5402     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5403
5404     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5405
5406     pic16_outBitC(result);
5407   } else {
5408     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5409     /* if the result is used in the next
5410        ifx conditional branch then generate
5411        code a little differently */
5412     if (ifx )
5413       genIfxJump (ifx,"c");
5414     else
5415       pic16_outBitC(result);
5416     /* leave the result in acc */
5417   }
5418
5419 }
5420
5421 #else   /* old version of genCmp() */   /* } else { */
5422
5423 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5424 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5425         operand *result, int offset, int invert_op)
5426 {
5427   /* add code here */
5428   
5429   /* check condition, > or < ?? */
5430   if(rIfx->condition != 0)invert_op ^= 1;
5431   
5432   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5433
5434   if(!ifx)invert_op ^= 1;
5435
5436   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5437       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5438   
5439   /* do selection */
5440   if(!invert_op)return POC_CPFSGT;
5441   else return POC_CPFSLT;
5442 }
5443
5444 static int compareAopfirstpass=1;
5445
5446 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5447             operand *oper, int offset, operand *result,
5448             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5449             symbol *tlbl)
5450 {
5451   int op;
5452   symbol *truelbl;
5453
5454   /* invert if there is a result to be loaded, in order to fit,
5455    * SETC/CLRC sequence */
5456   if(AOP_SIZE(result))invert_op ^= 1;
5457
5458 //  if(sign && !offset)invert_op ^= 1;
5459   
5460 //  if(sign)invert_op ^= 1;
5461   
5462   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5463
5464   if(AOP_SIZE(result) && compareAopfirstpass) {
5465     if(!ifx) {
5466       if(pcop2)
5467         pic16_emitpcode(POC_SETF, pcop2);
5468       else
5469         emitSETC;
5470     } else {
5471       if(pcop2)
5472         pic16_emitpcode(POC_CLRF, pcop2);
5473       else
5474         emitCLRC;
5475     }
5476   }
5477
5478   compareAopfirstpass = 0;
5479
5480       /* there is a bug when comparing operands with size > 1,
5481        * because higher bytes can be equal and test should be performed
5482        * to the next lower byte, current algorithm, considers operands
5483        * inequal in these cases! -- VR 20041107 */
5484
5485     
5486   if(pcop)
5487     pic16_emitpcode(op, pcop);
5488   else
5489     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5490
5491
5492   if((!sign || !offset) && AOP_SIZE(result)) {
5493     if(!ifx) {
5494       if(pcop2)
5495         pic16_emitpcode(POC_CLRF, pcop2);
5496         else
5497         emitCLRC;
5498     } else {
5499       if(pcop2)
5500         pic16_emitpcode(POC_SETF, pcop2);
5501       else
5502         emitSETC;
5503     }
5504     
5505     /* don't emit final branch (offset == 0) */
5506     if(offset) {
5507
5508       if(pcop2)
5509         pic16_emitpcode(POC_RRCF, pcop2);
5510
5511       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5512     }
5513   } else {
5514     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5515       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5516             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5517
5518       truelbl = newiTempLabel( NULL );
5519       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5520       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5521         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5522       else
5523         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5524       pic16_emitpLabel(truelbl->key);
5525     } else {
5526       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5527     }
5528   }
5529 }
5530
5531
5532   
5533
5534 #if 1   /* { */
5535 static void genCmp (operand *left, operand *right,
5536                     operand *result, iCode *ifx, int sign)
5537 {
5538   int size, cmpop=1;
5539   long lit = 0L;
5540   resolvedIfx rFalseIfx;
5541   symbol *falselbl, *tlbl;
5542
5543     FENTRY;
5544     
5545     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5546
5547     resolveIfx(&rFalseIfx, ifx);
5548     size = max(AOP_SIZE(left), AOP_SIZE(right));
5549     
5550     /* if left & right are bit variables */
5551     if(AOP_TYPE(left) == AOP_CRY
5552       && AOP_TYPE(right) == AOP_CRY ) {
5553
5554         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5555         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5556         
5557         werror(W_POSSBUG2, __FILE__, __LINE__);
5558         exit(-1);
5559     }
5560     
5561     /* if literal is on the right then swap with left */
5562     if((AOP_TYPE(right) == AOP_LIT)) {
5563       operand *tmp = right ;
5564 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5565
5566         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5567
5568 //      lit = (lit - 1) & mask;
5569         right = left;
5570         left = tmp;
5571         rFalseIfx.condition ^= 1;               /* reverse compare */
5572     } else
5573     if ((AOP_TYPE(left) == AOP_LIT)) {
5574       /* float compares are handled by support functions */
5575       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5576     }
5577
5578     /* actual comparing algorithm */
5579 //    size = AOP_SIZE( right );
5580
5581     falselbl = newiTempLabel( NULL );
5582     if(AOP_TYPE(left) == AOP_LIT) {
5583       /* compare to literal */
5584       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5585       
5586       if(sign) {
5587         pCodeOp *pct, *pct2;
5588         symbol *tlbl1;
5589
5590         /* signed compare */
5591         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5592
5593         pct = pic16_popCopyReg(&pic16_pc_prodl);
5594         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5595         tlbl = newiTempLabel( NULL );
5596         
5597         /* first compare signs:
5598          *  a. if both are positive, compare just like unsigned
5599          *  b. if both are negative, invert cmpop, compare just like unsigned
5600          *  c. if different signs, determine the result directly */
5601
5602         size--;
5603
5604 #if 1
5605         /* { */
5606         tlbl1 = newiTempLabel( NULL );
5607 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
5608
5609         if(lit > 0) {
5610
5611           /* literal is zero or positive:
5612            *  a. if carry is zero, too, continue compare,
5613            *  b. if carry is set, then continue depending on cmpop ^ condition:
5614            *    1. '<' return false (literal < variable),
5615            *    2. '>' return true (literal > variable) */
5616 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5617           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5618           
5619           
5620           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5621           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5622         } else 
5623         if(lit < 0) {
5624           
5625           /* literal is negative:
5626            *  a. if carry is set, too, continue compare,
5627            *  b. if carry is zero, then continue depending on cmpop ^ condition:
5628            *    1. '<' return true (literal < variable),
5629            *    2. '>' return false (literal > variable) */
5630 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5631           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5632           
5633           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5634           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5635         }
5636 #if 1
5637         else {
5638           /* lit == 0 */
5639           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5640           
5641           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5642           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5643         }
5644 #endif
5645         
5646         
5647         pic16_emitpLabel( tlbl1->key );
5648 #endif  /* } */
5649
5650         compareAopfirstpass=1;
5651 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5652 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5653 //        pic16_emitpcode(POC_MOVWF, pct);
5654
5655 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5656         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5657 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5658         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5659
5660         /* generic case */        
5661           while( size-- ) {
5662 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5663 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5664 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5665 //            pic16_emitpcode(POC_MOVWF, pct);
5666
5667 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5668             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5669             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5670 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5671 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5672           }
5673 //        }
5674         
5675         if(ifx)ifx->generated = 1;
5676
5677         if(AOP_SIZE(result)) {
5678           pic16_emitpLabel(tlbl->key);
5679           pic16_emitpLabel(falselbl->key);
5680           pic16_outBitOp( result, pct2 );
5681         } else {
5682           pic16_emitpLabel(tlbl->key);
5683         }
5684       } else {
5685
5686
5687         /* unsigned compare */      
5688         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5689     
5690         compareAopfirstpass=1;
5691         while(size--) {
5692           
5693           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5694           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5695
5696         }
5697
5698         if(ifx)ifx->generated = 1;
5699
5700
5701         if(AOP_SIZE(result)) {
5702           pic16_emitpLabel(falselbl->key);
5703           pic16_outBitC( result );
5704         }
5705
5706       }
5707     } else {
5708       /* compare registers */
5709       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5710
5711
5712       if(sign) {
5713         pCodeOp *pct, *pct2;
5714         
5715         /* signed compare */
5716         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5717
5718         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
5719         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
5720         tlbl = newiTempLabel( NULL );
5721         
5722         compareAopfirstpass=1;
5723
5724         size--;
5725         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5726 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5727         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5728         pic16_emitpcode(POC_MOVWF, pct);
5729
5730         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5731 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5732         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5733
5734         /* WREG already holds left + 0x80 */
5735         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5736         
5737         while( size-- ) {
5738           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5739 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5740           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5741           pic16_emitpcode(POC_MOVWF, pct);
5742                 
5743           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5744 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5745           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5746
5747           /* WREG already holds left + 0x80 */
5748           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5749 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5750         }
5751         
5752         if(ifx)ifx->generated = 1;
5753
5754         if(AOP_SIZE(result)) {
5755           pic16_emitpLabel(tlbl->key);
5756           pic16_emitpLabel(falselbl->key);
5757           pic16_outBitOp( result, pct2 );
5758         } else {
5759           pic16_emitpLabel(tlbl->key);
5760         }
5761
5762       } else {
5763         /* unsigned compare */      
5764         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5765
5766         compareAopfirstpass=1;
5767         while(size--) {
5768           
5769           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5770           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5771
5772         }
5773
5774         if(ifx)ifx->generated = 1;
5775         if(AOP_SIZE(result)) {
5776
5777           pic16_emitpLabel(falselbl->key);
5778           pic16_outBitC( result );
5779         }
5780
5781       }
5782     }
5783 }
5784
5785 #else    /* } else { */
5786
5787 /* new version of genCmp -- VR 20041012 */
5788 static void genCmp (operand *left,operand *right,
5789                     operand *result, iCode *ifx, int sign)
5790 {
5791   int size; //, offset = 0 ;
5792   unsigned long lit = 0L,i = 0;
5793   resolvedIfx rFalseIfx;
5794   int willCheckCarry=0;
5795   //  resolvedIfx rTrueIfx;
5796   symbol *truelbl;
5797
5798     FENTRY;
5799   
5800   /* General concept:
5801    * subtract right from left if at the end the carry flag is set then we
5802    * know that left is greater than right */
5803             
5804   resolveIfx(&rFalseIfx,ifx);
5805   truelbl  = newiTempLabel(NULL);
5806   size = max(AOP_SIZE(left),AOP_SIZE(right));
5807
5808   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5809
5810   /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5811    * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5812   
5813
5814   /* if literal is on the right then swap with left */
5815   if ((AOP_TYPE(right) == AOP_LIT)) {
5816     operand *tmp = right ;
5817     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5818
5819       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5820
5821 //      lit = (lit - 1) & mask;
5822       right = left;
5823       left = tmp;
5824       rFalseIfx.condition ^= 1;         /* reverse compare */
5825   } else
5826   if ((AOP_TYPE(left) == AOP_LIT)) {
5827     /* float compares are handled by support functions */
5828     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5829   }
5830
5831
5832   //if(IC_TRUE(ifx) == NULL)
5833   /* if left & right are bit variables */
5834   if (AOP_TYPE(left) == AOP_CRY &&
5835       AOP_TYPE(right) == AOP_CRY ) {
5836
5837     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5838     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5839
5840   } else {
5841     symbol *lbl  = newiTempLabel(NULL);
5842
5843     if(AOP_TYPE(left) == AOP_LIT) {
5844       DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5845
5846       if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5847         willCheckCarry = 1;
5848       else willCheckCarry = 0;
5849
5850       /* Special cases */
5851       if((lit == 0) && (sign == 0)) {
5852         /* unsigned compare to 0 */
5853         DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5854         
5855         size--;
5856         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857         while(size) 
5858           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5859
5860         genSkipz2(&rFalseIfx,0);
5861         if(ifx)ifx->generated = 1;
5862         return;
5863       }
5864
5865       if(size==1) {
5866         /* Special cases */
5867         lit &= 0xff;
5868         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5869           /* degenerate compare can never be true */
5870           if(rFalseIfx.condition == 0)
5871             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5872
5873           if(ifx) ifx->generated = 1;
5874           return;
5875         }
5876
5877         if(sign) {
5878           /* signed comparisons to a literal byte */
5879           DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5880
5881           int lp1 = (lit+1) & 0xff;
5882
5883           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5884           switch (lp1) {
5885           case 0:
5886             rFalseIfx.condition ^= 1;
5887             genSkipCond(&rFalseIfx,right,0,7);
5888             break;
5889           case 0x7f:
5890             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5891             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5892             genSkipz2(&rFalseIfx,1);
5893             break;
5894           default:
5895             pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5896             
5897             if(rFalseIfx.condition)
5898               pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5899             else
5900               pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5901
5902             if(willCheckCarry) {
5903               if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5904               else { emitSETC; emitCLRC; }
5905               
5906             } else {
5907               pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5908             }              
5909                       
5910 /*          pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5911             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5912             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5913             rFalseIfx.condition ^= 1;
5914             genSkipc(&rFalseIfx);
5915 */
5916             break;
5917           }
5918         } else {
5919           /* unsigned comparisons to a literal byte */
5920           DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5921
5922           switch(lit & 0xff ) {
5923                           /* special cases */
5924           case 0:
5925             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5926             genSkipz2(&rFalseIfx,0);
5927             break;
5928           case 0x7f:
5929             rFalseIfx.condition ^= 1;
5930             genSkipCond(&rFalseIfx,right,0,7);
5931             break;
5932           default:
5933             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5934             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5935             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5936             rFalseIfx.condition ^= 1;
5937             if (AOP_TYPE(result) == AOP_CRY)
5938               genSkipc(&rFalseIfx);
5939             else {
5940               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5941               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5942             }         
5943             break;
5944           }
5945         }
5946
5947         if(ifx) ifx->generated = 1;
5948         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5949                 goto check_carry;
5950         return;
5951
5952       } else {
5953
5954         /* Size is greater than 1 */
5955
5956         if(sign) {
5957           int lp1 = lit+1;
5958
5959           size--;
5960
5961           if(lp1 == 0) {
5962             /* this means lit = 0xffffffff, or -1 */
5963
5964
5965             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5966             rFalseIfx.condition ^= 1;
5967             genSkipCond(&rFalseIfx,right,size,7);
5968             if(ifx) ifx->generated = 1;
5969             return;
5970           }
5971
5972           if(lit == 0) {
5973             int s = size;
5974
5975             if(rFalseIfx.condition) {
5976               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5977               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5978             }
5979
5980             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5981             while(size--)
5982               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5983
5984
5985             emitSKPZ;
5986             if(rFalseIfx.condition) {
5987               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5988               pic16_emitpLabel(truelbl->key);
5989             }else {
5990               rFalseIfx.condition ^= 1;
5991               genSkipCond(&rFalseIfx,right,s,7);
5992             }
5993
5994             if(ifx) ifx->generated = 1;
5995             return;
5996           }
5997
5998           if((size == 1) &&  (0 == (lp1&0xff))) {
5999             /* lower byte of signed word is zero */
6000             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
6001             i = ((lp1 >> 8) & 0xff) ^0x80;
6002             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6003             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6004             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6005             rFalseIfx.condition ^= 1;
6006             genSkipc(&rFalseIfx);
6007
6008
6009             if(ifx) ifx->generated = 1;
6010             return;
6011           }
6012
6013           if(lit & (0x80 << (size*8))) {
6014             /* Lit is less than zero */
6015             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
6016             //rFalseIfx.condition ^= 1;
6017             //genSkipCond(&rFalseIfx,left,size,7);
6018             //rFalseIfx.condition ^= 1;
6019             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6020             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6021
6022             if(rFalseIfx.condition)
6023               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6024             else
6025               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6026
6027
6028           } else {
6029             /* Lit is greater than or equal to zero */
6030             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
6031             //rFalseIfx.condition ^= 1;
6032             //genSkipCond(&rFalseIfx,right,size,7);
6033             //rFalseIfx.condition ^= 1;
6034
6035             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6036             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6037
6038             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6039             if(rFalseIfx.condition)
6040               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6041             else
6042               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6043
6044           }
6045
6046
6047           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6048           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6049
6050           while(size--) {
6051
6052             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6053             emitSKPNZ;
6054             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6055           }
6056           rFalseIfx.condition ^= 1;
6057           //rFalseIfx.condition = 1;
6058           genSkipc(&rFalseIfx);
6059
6060           pic16_emitpLabel(truelbl->key);
6061
6062           if(ifx) ifx->generated = 1;
6063           return;
6064           // end of if (sign)
6065         } else {
6066
6067           /* compare word or long to an unsigned literal on the right.*/
6068
6069
6070           size--;
6071           if(lit < 0xff) {
6072             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6073             switch (lit) {
6074             case 0:
6075               break; /* handled above */
6076 /*
6077             case 0xff:
6078               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6079               while(size--)
6080                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6081               genSkipz2(&rFalseIfx,0);
6082               break;
6083 */
6084             default:
6085               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6086               while(--size)
6087                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6088
6089               emitSKPZ;
6090               if(rFalseIfx.condition)
6091                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6092               else
6093                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6094
6095
6096               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6097               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6098
6099               rFalseIfx.condition ^= 1;
6100               genSkipc(&rFalseIfx);
6101             }
6102
6103             pic16_emitpLabel(truelbl->key);
6104
6105             if(ifx) ifx->generated = 1;
6106             return;
6107           }
6108
6109
6110           lit++;
6111           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6112           i = (lit >> (size*8)) & 0xff;
6113
6114           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6115           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6116
6117           while(size--) {
6118             i = (lit >> (size*8)) & 0xff;
6119
6120             if(i) {
6121               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6122               emitSKPNZ;
6123               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6124             } else {
6125               /* this byte of the lit is zero, 
6126                * if it's not the last then OR in the variable */
6127               if(size)
6128                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6129             }
6130           }
6131
6132
6133           pic16_emitpLabel(lbl->key);
6134
6135           rFalseIfx.condition ^= 1;
6136
6137           genSkipc(&rFalseIfx);
6138         }
6139
6140         if(sign)
6141           pic16_emitpLabel(truelbl->key);
6142         if(ifx) ifx->generated = 1;
6143         return;
6144       }
6145     }
6146     /* Compare two variables */
6147
6148     DEBUGpic16_emitcode(";sign","%d",sign);
6149
6150     size--;
6151     if(sign) {
6152       /* Sigh. thus sucks... */
6153       if(size) {
6154         pCodeOp *pctemp;
6155         
6156         pctemp = pic16_popGetTempReg(1);
6157         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6158         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6159         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6160         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6161         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6162         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6163         pic16_popReleaseTempReg(pctemp, 1);
6164       } else {
6165         /* Signed char comparison */
6166         /* Special thanks to Nikolai Golovchenko for this snippet */
6167         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6168         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6169         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6170         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6171         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6172         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6173
6174         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6175         genSkipc(&rFalseIfx);
6176           
6177         if(ifx) ifx->generated = 1;
6178         return;
6179       }
6180
6181     } else {
6182
6183       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6184       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6185     }
6186
6187
6188     /* The rest of the bytes of a multi-byte compare */
6189     while (size) {
6190
6191       emitSKPZ;
6192       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6193       size--;
6194
6195       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6196       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6197
6198
6199     }
6200
6201     pic16_emitpLabel(lbl->key);
6202
6203     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6204     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6205         (AOP_TYPE(result) == AOP_REG)) {
6206       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6207       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6208     } else {
6209       genSkipc(&rFalseIfx);
6210     }         
6211     //genSkipc(&rFalseIfx);
6212     if(ifx) ifx->generated = 1;
6213
6214     return;
6215
6216   }
6217
6218 check_carry:
6219   if ((AOP_TYPE(result) != AOP_CRY) 
6220         && AOP_SIZE(result)) {
6221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6222
6223     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6224
6225     pic16_outBitC(result);
6226   } else {
6227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6228     /* if the result is used in the next
6229        ifx conditional branch then generate
6230        code a little differently */
6231     if (ifx )
6232       genIfxJump (ifx,"c");
6233     else
6234       pic16_outBitC(result);
6235     /* leave the result in acc */
6236   }
6237
6238 }
6239 #endif  /* } */
6240
6241
6242 #endif  /* } */
6243
6244
6245
6246 /*-----------------------------------------------------------------*/
6247 /* genCmpGt :- greater than comparison                             */
6248 /*-----------------------------------------------------------------*/
6249 static void genCmpGt (iCode *ic, iCode *ifx)
6250 {
6251   operand *left, *right, *result;
6252   sym_link *letype , *retype;
6253   int sign ;
6254
6255     FENTRY;
6256     
6257     left = IC_LEFT(ic);
6258     right= IC_RIGHT(ic);
6259     result = IC_RESULT(ic);
6260
6261     letype = getSpec(operandType(left));
6262     retype =getSpec(operandType(right));
6263     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6264     /* assign the amsops */
6265     pic16_aopOp (left,ic,FALSE);
6266     pic16_aopOp (right,ic,FALSE);
6267     pic16_aopOp (result,ic,TRUE);
6268
6269     genCmp(right, left, result, ifx, sign);
6270
6271     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6272     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6273     pic16_freeAsmop(result,NULL,ic,TRUE); 
6274 }
6275
6276 /*-----------------------------------------------------------------*/
6277 /* genCmpLt - less than comparisons                                */
6278 /*-----------------------------------------------------------------*/
6279 static void genCmpLt (iCode *ic, iCode *ifx)
6280 {
6281   operand *left, *right, *result;
6282   sym_link *letype , *retype;
6283   int sign ;
6284
6285     FENTRY;
6286
6287     left = IC_LEFT(ic);
6288     right= IC_RIGHT(ic);
6289     result = IC_RESULT(ic);
6290
6291     letype = getSpec(operandType(left));
6292     retype =getSpec(operandType(right));
6293     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6294
6295     /* assign the amsops */
6296     pic16_aopOp (left,ic,FALSE);
6297     pic16_aopOp (right,ic,FALSE);
6298     pic16_aopOp (result,ic,TRUE);
6299
6300     genCmp(left, right, result, ifx, sign);
6301
6302     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6303     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304     pic16_freeAsmop(result,NULL,ic,TRUE); 
6305 }
6306
6307 #if 0
6308 // not needed ATM
6309 // FIXME reenable literal optimisation when the pic16 port is stable
6310
6311 /*-----------------------------------------------------------------*/
6312 /* genc16bit2lit - compare a 16 bit value to a literal             */
6313 /*-----------------------------------------------------------------*/
6314 static void genc16bit2lit(operand *op, int lit, int offset)
6315 {
6316   int i;
6317
6318   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6319   if( (lit&0xff) == 0) 
6320     i=1;
6321   else
6322     i=0;
6323
6324   switch( BYTEofLONG(lit,i)) { 
6325   case 0:
6326     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6327     break;
6328   case 1:
6329     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6330     break;
6331   case 0xff:
6332     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6333     break;
6334   default:
6335     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6336     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6337   }
6338
6339   i ^= 1;
6340
6341   switch( BYTEofLONG(lit,i)) { 
6342   case 0:
6343     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6344     break;
6345   case 1:
6346     emitSKPNZ;
6347     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6348     break;
6349   case 0xff:
6350     emitSKPNZ;
6351     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6352     break;
6353   default:
6354     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6355     emitSKPNZ;
6356     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6357
6358   }
6359
6360 }
6361 #endif
6362
6363 #if 0
6364 // not needed ATM
6365 /*-----------------------------------------------------------------*/
6366 /* gencjneshort - compare and jump if not equal                    */
6367 /*-----------------------------------------------------------------*/
6368 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6369 {
6370   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6371   int offset = 0;
6372   int res_offset = 0;  /* the result may be a different size then left or right */
6373   int res_size = AOP_SIZE(result);
6374   resolvedIfx rIfx;
6375   symbol *lbl, *lbl_done;
6376
6377   unsigned long lit = 0L;
6378   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6379
6380   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6381   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6382   if(result)
6383     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6384   resolveIfx(&rIfx,ifx);
6385   lbl =  newiTempLabel(NULL);
6386   lbl_done =  newiTempLabel(NULL);
6387
6388
6389   /* if the left side is a literal or 
6390      if the right is in a pointer register and left 
6391      is not */
6392   if ((AOP_TYPE(left) == AOP_LIT) || 
6393       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6394     operand *t = right;
6395     right = left;
6396     left = t;
6397   }
6398   if(AOP_TYPE(right) == AOP_LIT)
6399     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6400
6401   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6402     preserve_result = 1;
6403
6404   if(result && !preserve_result)
6405     {
6406       int i;
6407       for(i = 0; i < AOP_SIZE(result); i++)
6408         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6409     }
6410
6411
6412   /* if the right side is a literal then anything goes */
6413   if (AOP_TYPE(right) == AOP_LIT &&
6414       AOP_TYPE(left) != AOP_DIR ) {
6415     switch(size) {
6416     case 2:
6417       genc16bit2lit(left, lit, 0);
6418       emitSKPZ;
6419       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6420       break;
6421     default:
6422       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6423       while (size--) {
6424         if(lit & 0xff) {
6425           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6426           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6427         } else {
6428           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6429         }
6430
6431         emitSKPZ;
6432         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6433         offset++;
6434         if(res_offset < res_size-1)
6435           res_offset++;
6436         lit >>= 8;
6437       }
6438       break;
6439     }
6440   }
6441
6442   /* if the right side is in a register or in direct space or
6443      if the left is a pointer register & right is not */    
6444   else if (AOP_TYPE(right) == AOP_REG ||
6445            AOP_TYPE(right) == AOP_DIR || 
6446            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6447            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6448     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6449     int lbl_key = lbl->key;
6450
6451     if(result) {
6452       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6453       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6454     }else {
6455       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6456       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6457               __FUNCTION__,__LINE__);
6458       return;
6459     }
6460    
6461 /*     switch(size) { */
6462 /*     case 2: */
6463 /*       genc16bit2lit(left, lit, 0); */
6464 /*       emitSKPNZ; */
6465 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6466 /*       break; */
6467 /*     default: */
6468     while (size--) {
6469       int emit_skip=1;
6470       if((AOP_TYPE(left) == AOP_DIR) && 
6471          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6472
6473         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6474         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6475
6476       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6477             
6478         switch (lit & 0xff) {
6479         case 0:
6480           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6481           break;
6482         case 1:
6483           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6484           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6485           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6486           emit_skip=0;
6487           break;
6488         case 0xff:
6489           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6490           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6491           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6492           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6493           emit_skip=0;
6494           break;
6495         default:
6496           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6498         }
6499         lit >>= 8;
6500
6501       } else {
6502         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6503       }
6504       if(emit_skip) {
6505         if(AOP_TYPE(result) == AOP_CRY) {
6506           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6507           if(rIfx.condition)
6508             emitSKPNZ;
6509           else
6510             emitSKPZ;
6511           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6512         } else {
6513           /* fix me. probably need to check result size too */
6514           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6515           if(rIfx.condition)
6516             emitSKPZ;
6517           else
6518             emitSKPNZ;
6519           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6520           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6521         }
6522         if(ifx)
6523           ifx->generated=1;
6524       }
6525       emit_skip++;
6526       offset++;
6527       if(res_offset < res_size-1)
6528         res_offset++;
6529     }
6530 /*       break; */
6531 /*     } */
6532   } else if(AOP_TYPE(right) == AOP_REG &&
6533             AOP_TYPE(left) != AOP_DIR){
6534
6535     while(size--) {
6536       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6537       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6538       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6539       if(rIfx.condition)
6540         emitSKPNZ;
6541       else
6542         emitSKPZ;
6543       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6544       offset++;
6545       if(res_offset < res_size-1)
6546         res_offset++;
6547     }
6548       
6549   }else{
6550     /* right is a pointer reg need both a & b */
6551     while(size--) {
6552       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6553       if(strcmp(l,"b"))
6554         pic16_emitcode("mov","b,%s",l);
6555       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6556       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6557       offset++;
6558     }
6559   }
6560
6561   if(result && preserve_result)
6562     {
6563       int i;
6564       for(i = 0; i < AOP_SIZE(result); i++)
6565         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6566     }
6567
6568   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6569
6570   if(result && preserve_result)
6571     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6572
6573   if(!rIfx.condition)
6574     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6575
6576   pic16_emitpLabel(lbl->key);
6577
6578   if(result && preserve_result)
6579     {
6580       int i;
6581       for(i = 0; i < AOP_SIZE(result); i++)
6582         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6583
6584       pic16_emitpLabel(lbl_done->key);
6585    }
6586
6587   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6588
6589   if(ifx)
6590     ifx->generated = 1;
6591 }
6592 #endif
6593
6594 #if 0
6595 /*-----------------------------------------------------------------*/
6596 /* gencjne - compare and jump if not equal                         */
6597 /*-----------------------------------------------------------------*/
6598 static void gencjne(operand *left, operand *right, iCode *ifx)
6599 {
6600     symbol *tlbl  = newiTempLabel(NULL);
6601
6602     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6603     gencjneshort(left, right, lbl);
6604
6605     pic16_emitcode("mov","a,%s",one);
6606     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6607     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6608     pic16_emitcode("clr","a");
6609     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6610
6611     pic16_emitpLabel(lbl->key);
6612     pic16_emitpLabel(tlbl->key);
6613
6614 }
6615 #endif
6616
6617
6618 /*-----------------------------------------------------------------*/
6619 /* is_LitOp - check if operand has to be treated as literal        */
6620 /*-----------------------------------------------------------------*/
6621 static bool is_LitOp(operand *op)
6622 {
6623   return ((AOP_TYPE(op) == AOP_LIT)
6624       || ( (AOP_TYPE(op) == AOP_PCODE)
6625           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6626               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6627 }
6628
6629 /*-----------------------------------------------------------------*/
6630 /* is_LitAOp - check if operand has to be treated as literal        */
6631 /*-----------------------------------------------------------------*/
6632 static bool is_LitAOp(asmop *aop)
6633 {
6634   return ((aop->type == AOP_LIT)
6635       || ( (aop->type == AOP_PCODE)
6636           && ( (aop->aopu.pcop->type == PO_LITERAL)
6637               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6638 }
6639
6640
6641
6642 /*-----------------------------------------------------------------*/
6643 /* genCmpEq - generates code for equal to                          */
6644 /*-----------------------------------------------------------------*/
6645 static void genCmpEq (iCode *ic, iCode *ifx)
6646 {
6647   operand *left, *right, *result;
6648   symbol *falselbl = newiTempLabel(NULL);
6649   symbol *donelbl = newiTempLabel(NULL);
6650
6651   int preserve_result = 0;
6652   int generate_result = 0;
6653   int i=0;
6654
6655   FENTRY;
6656   
6657   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6658   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6659   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6660  
6661   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6662
6663   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6664     {
6665       werror(W_POSSBUG2, __FILE__, __LINE__);
6666       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6667       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6668       goto release;
6669     }
6670
6671   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6672     {
6673       operand *tmp = right ;
6674       right = left;
6675       left = tmp;
6676     }
6677
6678   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6679     preserve_result = 1;
6680
6681   if(result && AOP_SIZE(result))
6682     generate_result = 1;
6683
6684   if(generate_result && !preserve_result)
6685     {
6686       for(i = 0; i < AOP_SIZE(result); i++)
6687         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6688     }
6689
6690   for(i=0; i < AOP_SIZE(left); i++)
6691     {
6692       if(AOP_TYPE(left) != AOP_ACC)
6693         {
6694           if(is_LitOp(left))
6695             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6696           else
6697             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6698         }
6699       if(is_LitOp(right))
6700         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6701       else
6702         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6703
6704       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6705     }
6706
6707   // result == true
6708
6709   if(generate_result && preserve_result)
6710     {
6711       for(i = 0; i < AOP_SIZE(result); i++)
6712         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6713     }
6714
6715   if(generate_result)
6716     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6717
6718   if(generate_result && preserve_result)
6719     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6720
6721   if(ifx && IC_TRUE(ifx))
6722     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6723
6724   if(ifx && IC_FALSE(ifx))
6725     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6726
6727   pic16_emitpLabel(falselbl->key);
6728
6729   // result == false
6730
6731   if(ifx && IC_FALSE(ifx))
6732     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6733
6734   if(generate_result && preserve_result)
6735     {
6736       for(i = 0; i < AOP_SIZE(result); i++)
6737         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6738     }
6739
6740   pic16_emitpLabel(donelbl->key);
6741
6742   if(ifx)
6743     ifx->generated = 1;
6744
6745 release:
6746   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6747   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6748   pic16_freeAsmop(result,NULL,ic,TRUE);
6749
6750 }
6751
6752
6753 #if 0
6754 // old version kept for reference
6755
6756 /*-----------------------------------------------------------------*/
6757 /* genCmpEq - generates code for equal to                          */
6758 /*-----------------------------------------------------------------*/
6759 static void genCmpEq (iCode *ic, iCode *ifx)
6760 {
6761     operand *left, *right, *result;
6762     unsigned long lit = 0L;
6763     int size,offset=0;
6764     symbol *falselbl  = newiTempLabel(NULL);
6765
6766
6767     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6768
6769     if(ifx)
6770       DEBUGpic16_emitcode ("; ifx is non-null","");
6771     else
6772       DEBUGpic16_emitcode ("; ifx is null","");
6773
6774     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6775     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6776     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6777
6778     size = max(AOP_SIZE(left),AOP_SIZE(right));
6779
6780     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6781
6782     /* if literal, literal on the right or 
6783     if the right is in a pointer register and left 
6784     is not */
6785     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6786         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6787       operand *tmp = right ;
6788       right = left;
6789       left = tmp;
6790     }
6791
6792
6793     if(ifx && !AOP_SIZE(result)){
6794         symbol *tlbl;
6795         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6796         /* if they are both bit variables */
6797         if (AOP_TYPE(left) == AOP_CRY &&
6798             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6799                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6800             if(AOP_TYPE(right) == AOP_LIT){
6801                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6802                 if(lit == 0L){
6803                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6804                     pic16_emitcode("cpl","c");
6805                 } else if(lit == 1L) {
6806                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6807                 } else {
6808                     pic16_emitcode("clr","c");
6809                 }
6810                 /* AOP_TYPE(right) == AOP_CRY */
6811             } else {
6812                 symbol *lbl = newiTempLabel(NULL);
6813                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6814                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6815                 pic16_emitcode("cpl","c");
6816                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6817             }
6818             /* if true label then we jump if condition
6819             supplied is true */
6820             tlbl = newiTempLabel(NULL);
6821             if ( IC_TRUE(ifx) ) {
6822                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6823                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6824             } else {
6825                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6826                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6827             }
6828             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6829
6830                 {
6831                 /* left and right are both bit variables, result is carry */
6832                         resolvedIfx rIfx;
6833               
6834                         resolveIfx(&rIfx,ifx);
6835
6836                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6837                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6838                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6839                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6840                         genSkipz2(&rIfx,0);
6841                 }
6842         } else {
6843
6844                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6845
6846                         /* They're not both bit variables. Is the right a literal? */
6847                         if(AOP_TYPE(right) == AOP_LIT) {
6848                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6849             
6850                         switch(size) {
6851
6852                                 case 1:
6853                                         switch(lit & 0xff) {
6854                                                 case 1:
6855                                                                 if ( IC_TRUE(ifx) ) {
6856                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6857                                                                         emitSKPNZ;
6858                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6859                                                                 } else {
6860                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6861                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6862                                                                 }
6863                                                                 break;
6864                                                 case 0xff:
6865                                                                 if ( IC_TRUE(ifx) ) {
6866                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6867                                                                         emitSKPNZ;
6868                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6869                                                                 } else {
6870                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6871                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6872                                                                 }
6873                                                                 break;
6874                                                 default:
6875                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6876                                                                 if(lit)
6877                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6878                                                                 genSkip(ifx,'z');
6879                                         } // switch lit
6880
6881
6882                                         /* end of size == 1 */
6883                                         break;
6884               
6885                                 case 2:
6886                                         genc16bit2lit(left,lit,offset);
6887                                         genSkip(ifx,'z');
6888                                         break;
6889                                         /* end of size == 2 */
6890
6891                                 default:
6892                                         /* size is 4 */
6893                                         if(lit==0) {
6894                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6895                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6896                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6897                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6898                                                 genSkip(ifx,'z');
6899                                         } else {
6900                                                 /* search for patterns that can be optimized */
6901
6902                                                 genc16bit2lit(left,lit,0);
6903                                                 lit >>= 16;
6904                                                 if(lit) {
6905                                                                 if(IC_TRUE(ifx))
6906                                                                 emitSKPZ; // if hi word unequal
6907                                                                 else
6908                                                                 emitSKPNZ; // if hi word equal
6909                                                                 // fail early
6910                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6911                                                         genc16bit2lit(left,lit,2);
6912                                                         genSkip(ifx,'z');
6913                                                 } else {
6914                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6915                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6916                                                         genSkip(ifx,'z');
6917                                                 }
6918                                         }
6919                                                 pic16_emitpLabel(falselbl->key);
6920                                                 break;
6921
6922                         } // switch size
6923           
6924                         ifx->generated = 1;
6925                         goto release ;
6926             
6927
6928           } else if(AOP_TYPE(right) == AOP_CRY ) {
6929             /* we know the left is not a bit, but that the right is */
6930             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6931             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6932                       pic16_popGet(AOP(right),offset));
6933             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6934
6935             /* if the two are equal, then W will be 0 and the Z bit is set
6936              * we could test Z now, or go ahead and check the high order bytes if
6937              * the variable we're comparing is larger than a byte. */
6938
6939             while(--size)
6940               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6941
6942             if ( IC_TRUE(ifx) ) {
6943               emitSKPNZ;
6944               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6945               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6946             } else {
6947               emitSKPZ;
6948               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6949               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6950             }
6951
6952           } else {
6953             /* They're both variables that are larger than bits */
6954             int s = size;
6955
6956             tlbl = newiTempLabel(NULL);
6957
6958             while(size--) {
6959               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6960               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6961
6962               if ( IC_TRUE(ifx) ) {
6963                 if(size) {
6964                   emitSKPZ;
6965                 
6966                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6967
6968                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6969                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6970                 } else {
6971                   emitSKPNZ;
6972
6973                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6974
6975
6976                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6977                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6978                 }
6979               } else {
6980                 emitSKPZ;
6981
6982                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6983
6984                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6985                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6986               }
6987               offset++;
6988             }
6989             if(s>1 && IC_TRUE(ifx)) {
6990               pic16_emitpLabel(tlbl->key);
6991               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6992             }
6993           }
6994         }
6995         /* mark the icode as generated */
6996         ifx->generated = 1;
6997         goto release ;
6998     }
6999
7000     /* if they are both bit variables */
7001     if (AOP_TYPE(left) == AOP_CRY &&
7002         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7003         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7004         if(AOP_TYPE(right) == AOP_LIT){
7005             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7006             if(lit == 0L){
7007                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7008                 pic16_emitcode("cpl","c");
7009             } else if(lit == 1L) {
7010                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7011             } else {
7012                 pic16_emitcode("clr","c");
7013             }
7014             /* AOP_TYPE(right) == AOP_CRY */
7015         } else {
7016             symbol *lbl = newiTempLabel(NULL);
7017             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7018             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7019             pic16_emitcode("cpl","c");
7020             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7021         }
7022         /* c = 1 if egal */
7023         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7024             pic16_outBitC(result);
7025             goto release ;
7026         }
7027         if (ifx) {
7028             genIfxJump (ifx,"c");
7029             goto release ;
7030         }
7031         /* if the result is used in an arithmetic operation
7032         then put the result in place */
7033         pic16_outBitC(result);
7034     } else {
7035       
7036       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7037       gencjne(left,right,result,ifx);
7038 /*
7039       if(ifx) 
7040         gencjne(left,right,newiTempLabel(NULL));
7041       else {
7042         if(IC_TRUE(ifx)->key)
7043           gencjne(left,right,IC_TRUE(ifx)->key);
7044         else
7045           gencjne(left,right,IC_FALSE(ifx)->key);
7046         ifx->generated = 1;
7047         goto release ;
7048       }
7049       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7050         pic16_aopPut(AOP(result),"a",0);
7051         goto release ;
7052       }
7053
7054       if (ifx) {
7055         genIfxJump (ifx,"a");
7056         goto release ;
7057       }
7058 */
7059       /* if the result is used in an arithmetic operation
7060          then put the result in place */
7061 /*
7062       if (AOP_TYPE(result) != AOP_CRY) 
7063         pic16_outAcc(result);
7064 */
7065       /* leave the result in acc */
7066     }
7067
7068 release:
7069     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7070     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7071     pic16_freeAsmop(result,NULL,ic,TRUE);
7072 }
7073 #endif
7074
7075 /*-----------------------------------------------------------------*/
7076 /* ifxForOp - returns the icode containing the ifx for operand     */
7077 /*-----------------------------------------------------------------*/
7078 static iCode *ifxForOp ( operand *op, iCode *ic )
7079 {
7080   FENTRY2;
7081
7082     /* if true symbol then needs to be assigned */
7083     if (IS_TRUE_SYMOP(op))
7084         return NULL ;
7085
7086     /* if this has register type condition and
7087     the next instruction is ifx with the same operand
7088     and live to of the operand is upto the ifx only then */
7089     if (ic->next
7090         && ic->next->op == IFX
7091         && IC_COND(ic->next)->key == op->key
7092         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7093         ) {
7094                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7095           return ic->next;
7096     }
7097
7098     if (ic->next &&
7099         ic->next->op == IFX &&
7100         IC_COND(ic->next)->key == op->key) {
7101       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7102       return ic->next;
7103     }
7104
7105     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7106     if (ic->next &&
7107         ic->next->op == IFX)
7108       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7109
7110     if (ic->next &&
7111         ic->next->op == IFX &&
7112         IC_COND(ic->next)->key == op->key) {
7113       DEBUGpic16_emitcode ("; "," key is okay");
7114       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7115                            OP_SYMBOL(op)->liveTo,
7116                            ic->next->seq);
7117     }
7118
7119 #if 0
7120     /* the code below is completely untested
7121      * it just allows ulong2fs.c compile -- VR */
7122          
7123     ic = ic->next;
7124     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7125                                         __FILE__, __FUNCTION__, __LINE__);
7126         
7127     /* if this has register type condition and
7128     the next instruction is ifx with the same operand
7129     and live to of the operand is upto the ifx only then */
7130     if (ic->next &&
7131         ic->next->op == IFX &&
7132         IC_COND(ic->next)->key == op->key &&
7133         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7134         return ic->next;
7135
7136     if (ic->next &&
7137         ic->next->op == IFX &&
7138         IC_COND(ic->next)->key == op->key) {
7139       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7140       return ic->next;
7141     }
7142
7143     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7144                                         __FILE__, __FUNCTION__, __LINE__);
7145
7146 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7147 #endif
7148
7149     return NULL;
7150 }
7151 /*-----------------------------------------------------------------*/
7152 /* genAndOp - for && operation                                     */
7153 /*-----------------------------------------------------------------*/
7154 static void genAndOp (iCode *ic)
7155 {
7156   operand *left,*right, *result;
7157 /*     symbol *tlbl; */
7158
7159     FENTRY;
7160
7161     /* note here that && operations that are in an
7162     if statement are taken away by backPatchLabels
7163     only those used in arthmetic operations remain */
7164     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7165     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7166     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7167
7168     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7169
7170     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7171     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7172     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7173
7174     /* if both are bit variables */
7175 /*     if (AOP_TYPE(left) == AOP_CRY && */
7176 /*         AOP_TYPE(right) == AOP_CRY ) { */
7177 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7178 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7179 /*         pic16_outBitC(result); */
7180 /*     } else { */
7181 /*         tlbl = newiTempLabel(NULL); */
7182 /*         pic16_toBoolean(left);     */
7183 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7184 /*         pic16_toBoolean(right); */
7185 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7186 /*         pic16_outBitAcc(result); */
7187 /*     } */
7188
7189     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7190     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7191     pic16_freeAsmop(result,NULL,ic,TRUE);
7192 }
7193
7194
7195 /*-----------------------------------------------------------------*/
7196 /* genOrOp - for || operation                                      */
7197 /*-----------------------------------------------------------------*/
7198 /*
7199   tsd pic port -
7200   modified this code, but it doesn't appear to ever get called
7201 */
7202
7203 static void genOrOp (iCode *ic)
7204 {
7205   operand *left,*right, *result;
7206   symbol *tlbl;
7207
7208     FENTRY;  
7209
7210   /* note here that || operations that are in an
7211     if statement are taken away by backPatchLabels
7212     only those used in arthmetic operations remain */
7213     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7214     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7215     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7216
7217     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7218
7219     /* if both are bit variables */
7220     if (AOP_TYPE(left) == AOP_CRY &&
7221         AOP_TYPE(right) == AOP_CRY ) {
7222       pic16_emitcode("clrc","");
7223       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7224                AOP(left)->aopu.aop_dir,
7225                AOP(left)->aopu.aop_dir);
7226       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7227                AOP(right)->aopu.aop_dir,
7228                AOP(right)->aopu.aop_dir);
7229       pic16_emitcode("setc","");
7230
7231     } else {
7232         tlbl = newiTempLabel(NULL);
7233         pic16_toBoolean(left);
7234         emitSKPZ;
7235         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7236         pic16_toBoolean(right);
7237         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7238
7239         pic16_outBitAcc(result);
7240     }
7241
7242     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7243     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7244     pic16_freeAsmop(result,NULL,ic,TRUE);            
7245 }
7246
7247 /*-----------------------------------------------------------------*/
7248 /* isLiteralBit - test if lit == 2^n                               */
7249 /*-----------------------------------------------------------------*/
7250 static int isLiteralBit(unsigned long lit)
7251 {
7252     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7253     0x100L,0x200L,0x400L,0x800L,
7254     0x1000L,0x2000L,0x4000L,0x8000L,
7255     0x10000L,0x20000L,0x40000L,0x80000L,
7256     0x100000L,0x200000L,0x400000L,0x800000L,
7257     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7258     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7259     int idx;
7260     
7261     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7262     for(idx = 0; idx < 32; idx++)
7263         if(lit == pw[idx])
7264             return idx+1;
7265     return 0;
7266 }
7267
7268 /*-----------------------------------------------------------------*/
7269 /* continueIfTrue -                                                */
7270 /*-----------------------------------------------------------------*/
7271 static void continueIfTrue (iCode *ic)
7272 {
7273   FENTRY;
7274   if(IC_TRUE(ic))
7275     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7276   ic->generated = 1;
7277 }
7278
7279 /*-----------------------------------------------------------------*/
7280 /* jmpIfTrue -                                                     */
7281 /*-----------------------------------------------------------------*/
7282 static void jumpIfTrue (iCode *ic)
7283 {
7284   FENTRY;
7285   if(!IC_TRUE(ic))
7286     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7287   ic->generated = 1;
7288 }
7289
7290 /*-----------------------------------------------------------------*/
7291 /* jmpTrueOrFalse -                                                */
7292 /*-----------------------------------------------------------------*/
7293 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7294 {
7295   // ugly but optimized by peephole
7296   FENTRY;
7297   if(IC_TRUE(ic)){
7298     symbol *nlbl = newiTempLabel(NULL);
7299       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7300       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7301       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7302       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7303   } else {
7304     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7305     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7306   }
7307   ic->generated = 1;
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* genAnd  - code for and                                          */
7312 /*-----------------------------------------------------------------*/
7313 static void genAnd (iCode *ic, iCode *ifx)
7314 {
7315   operand *left, *right, *result;
7316   int size, offset=0;  
7317   unsigned long lit = 0L;
7318   int bytelit = 0;
7319   resolvedIfx rIfx;
7320
7321     FENTRY;
7322     
7323   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7324   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7325   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7326
7327   resolveIfx(&rIfx,ifx);
7328
7329   /* if left is a literal & right is not then exchange them */
7330   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7331       AOP_NEEDSACC(left)) {
7332     operand *tmp = right ;
7333     right = left;
7334     left = tmp;
7335   }
7336
7337   /* if result = right then exchange them */
7338   if(pic16_sameRegs(AOP(result),AOP(right))){
7339     operand *tmp = right ;
7340     right = left;
7341     left = tmp;
7342   }
7343
7344   /* if right is bit then exchange them */
7345   if (AOP_TYPE(right) == AOP_CRY &&
7346       AOP_TYPE(left) != AOP_CRY){
7347     operand *tmp = right ;
7348     right = left;
7349     left = tmp;
7350   }
7351   if(AOP_TYPE(right) == AOP_LIT)
7352     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7353
7354   size = AOP_SIZE(result);
7355
7356   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7357
7358   // if(bit & yy)
7359   // result = bit & yy;
7360   if (AOP_TYPE(left) == AOP_CRY){
7361     // c = bit & literal;
7362     if(AOP_TYPE(right) == AOP_LIT){
7363       if(lit & 1) {
7364         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7365           // no change
7366           goto release;
7367         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7368       } else {
7369         // bit(result) = 0;
7370         if(size && (AOP_TYPE(result) == AOP_CRY)){
7371           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7372           goto release;
7373         }
7374         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7375           jumpIfTrue(ifx);
7376           goto release;
7377         }
7378         pic16_emitcode("clr","c");
7379       }
7380     } else {
7381       if (AOP_TYPE(right) == AOP_CRY){
7382         // c = bit & bit;
7383         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7384         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7385       } else {
7386         // c = bit & val;
7387         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7388         // c = lsb
7389         pic16_emitcode("rrc","a");
7390         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7391       }
7392     }
7393     // bit = c
7394     // val = c
7395     if(size)
7396       pic16_outBitC(result);
7397     // if(bit & ...)
7398     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7399       genIfxJump(ifx, "c");           
7400     goto release ;
7401   }
7402
7403   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7404   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7405   if((AOP_TYPE(right) == AOP_LIT) &&
7406      (AOP_TYPE(result) == AOP_CRY) &&
7407      (AOP_TYPE(left) != AOP_CRY)){
7408     int posbit = isLiteralBit(lit);
7409     /* left &  2^n */
7410     if(posbit){
7411       posbit--;
7412       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7413       // bit = left & 2^n
7414       if(size)
7415         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7416       // if(left &  2^n)
7417       else{
7418         if(ifx){
7419 /*
7420           if(IC_TRUE(ifx)) {
7421             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7422             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7423           } else {
7424             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7425             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7426           }
7427 */
7428         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7429         size = AOP_SIZE(left);
7430
7431         {
7432           int bp = posbit, ofs=0;
7433           
7434             while(bp > 7) {
7435               bp -= 8;
7436               ofs++;
7437             }
7438         
7439           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7440                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7441
7442         }
7443 /*
7444           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7445                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7446 */
7447           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7448           
7449           ifx->generated = 1;
7450         }
7451         goto release;
7452       }
7453     } else {
7454       symbol *tlbl = newiTempLabel(NULL);
7455       int sizel = AOP_SIZE(left);
7456
7457       if(size)
7458         emitSETC;
7459
7460       while(sizel--) {
7461         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7462
7463           /* patch provided by Aaron Colwell */
7464           if((posbit = isLiteralBit(bytelit)) != 0) {
7465               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7466                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7467                                                 (posbit-1),0, PO_GPR_REGISTER));
7468
7469               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7470 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7471           } else {
7472               if (bytelit == 0xff) {
7473                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7474                    * a peephole could optimize it out -- VR */
7475                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7476               } else {
7477                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7478                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7479               }
7480
7481               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7482                             pic16_popGetLabel(tlbl->key));
7483           }
7484         
7485 #if 0
7486           /* old code, left here for reference -- VR 09/2004 */
7487           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7488           // byte ==  2^n ?
7489           if((posbit = isLiteralBit(bytelit)) != 0)
7490             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7491           else{
7492             if(bytelit != 0x0FFL)
7493               pic16_emitcode("anl","a,%s",
7494                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7495             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7496           }
7497 #endif
7498         }
7499         offset++;
7500       }
7501       // bit = left & literal
7502       if(size) {
7503         emitCLRC;
7504         pic16_emitpLabel(tlbl->key);
7505       }
7506       // if(left & literal)
7507       else {
7508         if(ifx) {
7509           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7510           pic16_emitpLabel(tlbl->key);
7511           ifx->generated = 1;
7512         }
7513         goto release;
7514       }
7515     }
7516
7517     pic16_outBitC(result);
7518     goto release ;
7519   }
7520
7521   /* if left is same as result */
7522   if(pic16_sameRegs(AOP(result),AOP(left))){
7523     int know_W = -1;
7524     for(;size--; offset++,lit>>=8) {
7525       if(AOP_TYPE(right) == AOP_LIT){
7526         switch(lit & 0xff) {
7527         case 0x00:
7528           /*  and'ing with 0 has clears the result */
7529 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7530           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7531           break;
7532         case 0xff:
7533           /* and'ing with 0xff is a nop when the result and left are the same */
7534           break;
7535
7536         default:
7537           {
7538             int p = pic16_my_powof2( (~lit) & 0xff );
7539             if(p>=0) {
7540               /* only one bit is set in the literal, so use a bcf instruction */
7541 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7542               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7543
7544             } else {
7545               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7546               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7547               if(know_W != (lit&0xff))
7548                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7549               know_W = lit &0xff;
7550               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7551             }
7552           }    
7553         }
7554       } else {
7555         if (AOP_TYPE(left) == AOP_ACC) {
7556           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7557         } else {                    
7558           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7559           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7560
7561         }
7562       }
7563     }
7564
7565   } else {
7566     // left & result in different registers
7567     if(AOP_TYPE(result) == AOP_CRY){
7568       // result = bit
7569       // if(size), result in bit
7570       // if(!size && ifx), conditional oper: if(left & right)
7571       symbol *tlbl = newiTempLabel(NULL);
7572       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7573       if(size)
7574         pic16_emitcode("setb","c");
7575       while(sizer--){
7576         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7577         pic16_emitcode("anl","a,%s",
7578                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7579         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7580         offset++;
7581       }
7582       if(size){
7583         CLRC;
7584         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7585         pic16_outBitC(result);
7586       } else if(ifx)
7587         jmpTrueOrFalse(ifx, tlbl);
7588     } else {
7589       for(;(size--);offset++) {
7590         // normal case
7591         // result = left & right
7592         if(AOP_TYPE(right) == AOP_LIT){
7593           int t = (lit >> (offset*8)) & 0x0FFL;
7594           switch(t) { 
7595           case 0x00:
7596             pic16_emitcode("clrf","%s",
7597                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7598             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7599             break;
7600           case 0xff:
7601             pic16_emitcode("movf","%s,w",
7602                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7603             pic16_emitcode("movwf","%s",
7604                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7605             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7606             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7607             break;
7608           default:
7609             pic16_emitcode("movlw","0x%x",t);
7610             pic16_emitcode("andwf","%s,w",
7611                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7612             pic16_emitcode("movwf","%s",
7613                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7614               
7615             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7616             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7617             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7618           }
7619           continue;
7620         }
7621
7622         if (AOP_TYPE(left) == AOP_ACC) {
7623           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7624           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7625         } else {
7626           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7627           pic16_emitcode("andwf","%s,w",
7628                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7629           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7630           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7631         }
7632         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7633         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7634       }
7635     }
7636   }
7637
7638   release :
7639     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7640   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7641   pic16_freeAsmop(result,NULL,ic,TRUE);     
7642 }
7643
7644 /*-----------------------------------------------------------------*/
7645 /* genOr  - code for or                                            */
7646 /*-----------------------------------------------------------------*/
7647 static void genOr (iCode *ic, iCode *ifx)
7648 {
7649     operand *left, *right, *result;
7650     int size, offset=0;
7651     unsigned long lit = 0L;
7652
7653     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7654
7655     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7656     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7657     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7658
7659     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7660
7661     /* if left is a literal & right is not then exchange them */
7662     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7663         AOP_NEEDSACC(left)) {
7664         operand *tmp = right ;
7665         right = left;
7666         left = tmp;
7667     }
7668
7669     /* if result = right then exchange them */
7670     if(pic16_sameRegs(AOP(result),AOP(right))){
7671         operand *tmp = right ;
7672         right = left;
7673         left = tmp;
7674     }
7675
7676     /* if right is bit then exchange them */
7677     if (AOP_TYPE(right) == AOP_CRY &&
7678         AOP_TYPE(left) != AOP_CRY){
7679         operand *tmp = right ;
7680         right = left;
7681         left = tmp;
7682     }
7683
7684     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7685
7686     if(AOP_TYPE(right) == AOP_LIT)
7687         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7688
7689     size = AOP_SIZE(result);
7690
7691     // if(bit | yy)
7692     // xx = bit | yy;
7693     if (AOP_TYPE(left) == AOP_CRY){
7694         if(AOP_TYPE(right) == AOP_LIT){
7695             // c = bit & literal;
7696             if(lit){
7697                 // lit != 0 => result = 1
7698                 if(AOP_TYPE(result) == AOP_CRY){
7699                   if(size)
7700                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7701                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7702                   //     AOP(result)->aopu.aop_dir,
7703                   //     AOP(result)->aopu.aop_dir);
7704                     else if(ifx)
7705                         continueIfTrue(ifx);
7706                     goto release;
7707                 }
7708             } else {
7709                 // lit == 0 => result = left
7710                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7711                     goto release;
7712                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7713             }
7714         } else {
7715             if (AOP_TYPE(right) == AOP_CRY){
7716               if(pic16_sameRegs(AOP(result),AOP(left))){
7717                 // c = bit | bit;
7718                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7719                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7720                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7721
7722                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7723                          AOP(result)->aopu.aop_dir,
7724                          AOP(result)->aopu.aop_dir);
7725                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7726                          AOP(right)->aopu.aop_dir,
7727                          AOP(right)->aopu.aop_dir);
7728                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7729                          AOP(result)->aopu.aop_dir,
7730                          AOP(result)->aopu.aop_dir);
7731               } else {
7732                 if( AOP_TYPE(result) == AOP_ACC) {
7733                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7734                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7735                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7736                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7737
7738                 } else {
7739
7740                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7741                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7742                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7743                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7744
7745                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7746                                  AOP(result)->aopu.aop_dir,
7747                                  AOP(result)->aopu.aop_dir);
7748                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7749                                  AOP(right)->aopu.aop_dir,
7750                                  AOP(right)->aopu.aop_dir);
7751                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7752                                  AOP(left)->aopu.aop_dir,
7753                                  AOP(left)->aopu.aop_dir);
7754                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7755                                  AOP(result)->aopu.aop_dir,
7756                                  AOP(result)->aopu.aop_dir);
7757                 }
7758               }
7759             } else {
7760                 // c = bit | val;
7761                 symbol *tlbl = newiTempLabel(NULL);
7762                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7763
7764
7765                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7766                 if( AOP_TYPE(right) == AOP_ACC) {
7767                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7768                   emitSKPNZ;
7769                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7770                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7771                 }
7772
7773
7774
7775                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7776                     pic16_emitcode(";XXX setb","c");
7777                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7778                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7779                 pic16_toBoolean(right);
7780                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7781                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7782                     jmpTrueOrFalse(ifx, tlbl);
7783                     goto release;
7784                 } else {
7785                     CLRC;
7786                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7787                 }
7788             }
7789         }
7790         // bit = c
7791         // val = c
7792         if(size)
7793             pic16_outBitC(result);
7794         // if(bit | ...)
7795         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7796             genIfxJump(ifx, "c");           
7797         goto release ;
7798     }
7799
7800     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7801     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7802     if((AOP_TYPE(right) == AOP_LIT) &&
7803        (AOP_TYPE(result) == AOP_CRY) &&
7804        (AOP_TYPE(left) != AOP_CRY)){
7805         if(lit){
7806           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7807             // result = 1
7808             if(size)
7809                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7810             else 
7811                 continueIfTrue(ifx);
7812             goto release;
7813         } else {
7814           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7815             // lit = 0, result = boolean(left)
7816             if(size)
7817                 pic16_emitcode(";XXX setb","c");
7818             pic16_toBoolean(right);
7819             if(size){
7820                 symbol *tlbl = newiTempLabel(NULL);
7821                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7822                 CLRC;
7823                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7824             } else {
7825                 genIfxJump (ifx,"a");
7826                 goto release;
7827             }
7828         }
7829         pic16_outBitC(result);
7830         goto release ;
7831     }
7832
7833     /* if left is same as result */
7834     if(pic16_sameRegs(AOP(result),AOP(left))){
7835       int know_W = -1;
7836       for(;size--; offset++,lit>>=8) {
7837         if(AOP_TYPE(right) == AOP_LIT){
7838           if((lit & 0xff) == 0)
7839             /*  or'ing with 0 has no effect */
7840             continue;
7841           else {
7842             int p = pic16_my_powof2(lit & 0xff);
7843             if(p>=0) {
7844               /* only one bit is set in the literal, so use a bsf instruction */
7845               pic16_emitpcode(POC_BSF,
7846                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7847             } else {
7848               if(know_W != (lit & 0xff))
7849                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7850               know_W = lit & 0xff;
7851               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7852             }
7853                     
7854           }
7855         } else {
7856           if (AOP_TYPE(left) == AOP_ACC) {
7857             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7858             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7859           } else {                  
7860             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7861             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7862
7863             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7864             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7865
7866           }
7867         }
7868       }
7869     } else {
7870         // left & result in different registers
7871         if(AOP_TYPE(result) == AOP_CRY){
7872             // result = bit
7873             // if(size), result in bit
7874             // if(!size && ifx), conditional oper: if(left | right)
7875             symbol *tlbl = newiTempLabel(NULL);
7876             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7877             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7878
7879
7880             if(size)
7881                 pic16_emitcode(";XXX setb","c");
7882             while(sizer--){
7883                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7884                 pic16_emitcode(";XXX orl","a,%s",
7885                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7886                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7887                 offset++;
7888             }
7889             if(size){
7890                 CLRC;
7891                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7892                 pic16_outBitC(result);
7893             } else if(ifx)
7894                 jmpTrueOrFalse(ifx, tlbl);
7895         } else for(;(size--);offset++){
7896           // normal case
7897           // result = left & right
7898           if(AOP_TYPE(right) == AOP_LIT){
7899             int t = (lit >> (offset*8)) & 0x0FFL;
7900             switch(t) { 
7901             case 0x00:
7902               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7903               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7904
7905               pic16_emitcode("movf","%s,w",
7906                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907               pic16_emitcode("movwf","%s",
7908                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7909               break;
7910             default:
7911               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7912               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7913               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7914
7915               pic16_emitcode("movlw","0x%x",t);
7916               pic16_emitcode("iorwf","%s,w",
7917                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7918               pic16_emitcode("movwf","%s",
7919                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7920               
7921             }
7922             continue;
7923           }
7924
7925           // faster than result <- left, anl result,right
7926           // and better if result is SFR
7927           if (AOP_TYPE(left) == AOP_ACC) {
7928             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7929             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7930           } else {
7931             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7932             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7933
7934             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7935             pic16_emitcode("iorwf","%s,w",
7936                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7937           }
7938           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7939           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7940         }
7941     }
7942
7943 release :
7944     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7945     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7946     pic16_freeAsmop(result,NULL,ic,TRUE);     
7947 }
7948
7949 /*-----------------------------------------------------------------*/
7950 /* genXor - code for xclusive or                                   */
7951 /*-----------------------------------------------------------------*/
7952 static void genXor (iCode *ic, iCode *ifx)
7953 {
7954   operand *left, *right, *result;
7955   int size, offset=0;
7956   unsigned long lit = 0L;
7957
7958   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7959
7960   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7961   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7962   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7963
7964   /* if left is a literal & right is not ||
7965      if left needs acc & right does not */
7966   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7967       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7968     operand *tmp = right ;
7969     right = left;
7970     left = tmp;
7971   }
7972
7973   /* if result = right then exchange them */
7974   if(pic16_sameRegs(AOP(result),AOP(right))){
7975     operand *tmp = right ;
7976     right = left;
7977     left = tmp;
7978   }
7979
7980   /* if right is bit then exchange them */
7981   if (AOP_TYPE(right) == AOP_CRY &&
7982       AOP_TYPE(left) != AOP_CRY){
7983     operand *tmp = right ;
7984     right = left;
7985     left = tmp;
7986   }
7987   if(AOP_TYPE(right) == AOP_LIT)
7988     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7989
7990   size = AOP_SIZE(result);
7991
7992   // if(bit ^ yy)
7993   // xx = bit ^ yy;
7994   if (AOP_TYPE(left) == AOP_CRY){
7995     if(AOP_TYPE(right) == AOP_LIT){
7996       // c = bit & literal;
7997       if(lit>>1){
7998         // lit>>1  != 0 => result = 1
7999         if(AOP_TYPE(result) == AOP_CRY){
8000           if(size)
8001             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8002             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8003           else if(ifx)
8004             continueIfTrue(ifx);
8005           goto release;
8006         }
8007         pic16_emitcode("setb","c");
8008       } else{
8009         // lit == (0 or 1)
8010         if(lit == 0){
8011           // lit == 0, result = left
8012           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8013             goto release;
8014           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8015         } else{
8016           // lit == 1, result = not(left)
8017           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8018             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8019             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8020             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8021             goto release;
8022           } else {
8023             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8024             pic16_emitcode("cpl","c");
8025           }
8026         }
8027       }
8028
8029     } else {
8030       // right != literal
8031       symbol *tlbl = newiTempLabel(NULL);
8032       if (AOP_TYPE(right) == AOP_CRY){
8033         // c = bit ^ bit;
8034         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8035       }
8036       else{
8037         int sizer = AOP_SIZE(right);
8038         // c = bit ^ val
8039         // if val>>1 != 0, result = 1
8040         pic16_emitcode("setb","c");
8041         while(sizer){
8042           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8043           if(sizer == 1)
8044             // test the msb of the lsb
8045             pic16_emitcode("anl","a,#0xfe");
8046           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8047           sizer--;
8048         }
8049         // val = (0,1)
8050         pic16_emitcode("rrc","a");
8051       }
8052       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8053       pic16_emitcode("cpl","c");
8054       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8055     }
8056     // bit = c
8057     // val = c
8058     if(size)
8059       pic16_outBitC(result);
8060     // if(bit | ...)
8061     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8062       genIfxJump(ifx, "c");           
8063     goto release ;
8064   }
8065
8066   if(pic16_sameRegs(AOP(result),AOP(left))){
8067     /* if left is same as result */
8068     for(;size--; offset++) {
8069       if(AOP_TYPE(right) == AOP_LIT){
8070         int t  = (lit >> (offset*8)) & 0x0FFL;
8071         if(t == 0x00L)
8072           continue;
8073         else
8074           if (IS_AOP_PREG(left)) {
8075             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8076             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8077             pic16_aopPut(AOP(result),"a",offset);
8078           } else {
8079             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8080             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8081             pic16_emitcode("xrl","%s,%s",
8082                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8083                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8084           }
8085       } else {
8086         if (AOP_TYPE(left) == AOP_ACC)
8087           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8088         else {
8089           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8090           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8091 /*
8092           if (IS_AOP_PREG(left)) {
8093             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8094             pic16_aopPut(AOP(result),"a",offset);
8095           } else
8096             pic16_emitcode("xrl","%s,a",
8097                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8098 */
8099         }
8100       }
8101     }
8102   } else {
8103     // left & result in different registers
8104     if(AOP_TYPE(result) == AOP_CRY){
8105       // result = bit
8106       // if(size), result in bit
8107       // if(!size && ifx), conditional oper: if(left ^ right)
8108       symbol *tlbl = newiTempLabel(NULL);
8109       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8110       if(size)
8111         pic16_emitcode("setb","c");
8112       while(sizer--){
8113         if((AOP_TYPE(right) == AOP_LIT) &&
8114            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8115           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8116         } else {
8117           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118           pic16_emitcode("xrl","a,%s",
8119                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8120         }
8121         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8122         offset++;
8123       }
8124       if(size){
8125         CLRC;
8126         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8127         pic16_outBitC(result);
8128       } else if(ifx)
8129         jmpTrueOrFalse(ifx, tlbl);
8130     } else for(;(size--);offset++){
8131       // normal case
8132       // result = left & right
8133       if(AOP_TYPE(right) == AOP_LIT){
8134         int t = (lit >> (offset*8)) & 0x0FFL;
8135         switch(t) { 
8136         case 0x00:
8137           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8138           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8139           pic16_emitcode("movf","%s,w",
8140                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8141           pic16_emitcode("movwf","%s",
8142                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8143           break;
8144         case 0xff:
8145           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8146           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8147           pic16_emitcode("comf","%s,w",
8148                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8149           pic16_emitcode("movwf","%s",
8150                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8151           break;
8152         default:
8153           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8154           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8155           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8156           pic16_emitcode("movlw","0x%x",t);
8157           pic16_emitcode("xorwf","%s,w",
8158                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8159           pic16_emitcode("movwf","%s",
8160                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8161
8162         }
8163         continue;
8164       }
8165
8166       // faster than result <- left, anl result,right
8167       // and better if result is SFR
8168       if (AOP_TYPE(left) == AOP_ACC) {
8169         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8170         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8171       } else {
8172         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8173         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8174         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8175         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8176       }
8177       if ( AOP_TYPE(result) != AOP_ACC){
8178         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8180       }
8181     }
8182   }
8183
8184   release :
8185     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8186   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8187   pic16_freeAsmop(result,NULL,ic,TRUE);     
8188 }
8189
8190 /*-----------------------------------------------------------------*/
8191 /* genInline - write the inline code out                           */
8192 /*-----------------------------------------------------------------*/
8193 static void genInline (iCode *ic)
8194 {
8195   char *buffer, *bp, *bp1;
8196     
8197         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8198
8199         _G.inLine += (!options.asmpeep);
8200
8201         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8202         strcpy(buffer,IC_INLINE(ic));
8203
8204 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8205
8206         /* emit each line as a code */
8207         while (*bp) {
8208                 if (*bp == '\n') {
8209                         *bp++ = '\0';
8210
8211                         if(*bp1)
8212                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8213                         bp1 = bp;
8214                 } else {
8215                         if (*bp == ':') {
8216                                 bp++;
8217                                 *bp = '\0';
8218                                 bp++;
8219
8220                                 /* print label, use this special format with NULL directive
8221                                  * to denote that the argument should not be indented with tab */
8222                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8223                                 bp1 = bp;
8224                         } else
8225                                 bp++;
8226                 }
8227         }
8228
8229         if ((bp1 != bp) && *bp1)
8230                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8231
8232
8233     Safe_free(buffer);
8234
8235     _G.inLine -= (!options.asmpeep);
8236 }
8237
8238 /*-----------------------------------------------------------------*/
8239 /* genRRC - rotate right with carry                                */
8240 /*-----------------------------------------------------------------*/
8241 static void genRRC (iCode *ic)
8242 {
8243   operand *left , *result ;
8244   int size, offset = 0, same;
8245
8246   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8247
8248   /* rotate right with carry */
8249   left = IC_LEFT(ic);
8250   result=IC_RESULT(ic);
8251   pic16_aopOp (left,ic,FALSE);
8252   pic16_aopOp (result,ic,FALSE);
8253
8254   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8255
8256   same = pic16_sameRegs(AOP(result),AOP(left));
8257
8258   size = AOP_SIZE(result);    
8259
8260   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8261
8262   /* get the lsb and put it into the carry */
8263   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8264
8265   offset = 0 ;
8266
8267   while(size--) {
8268
8269     if(same) {
8270       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8271     } else {
8272       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8273       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8274     }
8275
8276     offset++;
8277   }
8278
8279   pic16_freeAsmop(left,NULL,ic,TRUE);
8280   pic16_freeAsmop(result,NULL,ic,TRUE);
8281 }
8282
8283 /*-----------------------------------------------------------------*/
8284 /* genRLC - generate code for rotate left with carry               */
8285 /*-----------------------------------------------------------------*/
8286 static void genRLC (iCode *ic)
8287 {    
8288   operand *left , *result ;
8289   int size, offset = 0;
8290   int same;
8291
8292   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8293   /* rotate right with carry */
8294   left = IC_LEFT(ic);
8295   result=IC_RESULT(ic);
8296   pic16_aopOp (left,ic,FALSE);
8297   pic16_aopOp (result,ic,FALSE);
8298
8299   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8300
8301   same = pic16_sameRegs(AOP(result),AOP(left));
8302
8303   /* move it to the result */
8304   size = AOP_SIZE(result);    
8305
8306   /* get the msb and put it into the carry */
8307   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8308
8309   offset = 0 ;
8310
8311   while(size--) {
8312
8313     if(same) {
8314       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8315     } else {
8316       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8317       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8318     }
8319
8320     offset++;
8321   }
8322
8323
8324   pic16_freeAsmop(left,NULL,ic,TRUE);
8325   pic16_freeAsmop(result,NULL,ic,TRUE);
8326 }
8327
8328
8329 /* gpasm can get the highest order bit with HIGH/UPPER
8330  * so the following probably is not needed -- VR */
8331  
8332 /*-----------------------------------------------------------------*/
8333 /* genGetHbit - generates code get highest order bit               */
8334 /*-----------------------------------------------------------------*/
8335 static void genGetHbit (iCode *ic)
8336 {
8337     operand *left, *result;
8338     left = IC_LEFT(ic);
8339     result=IC_RESULT(ic);
8340     pic16_aopOp (left,ic,FALSE);
8341     pic16_aopOp (result,ic,FALSE);
8342
8343     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8344     /* get the highest order byte into a */
8345     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8346     if(AOP_TYPE(result) == AOP_CRY){
8347         pic16_emitcode("rlc","a");
8348         pic16_outBitC(result);
8349     }
8350     else{
8351         pic16_emitcode("rl","a");
8352         pic16_emitcode("anl","a,#0x01");
8353         pic16_outAcc(result);
8354     }
8355
8356
8357     pic16_freeAsmop(left,NULL,ic,TRUE);
8358     pic16_freeAsmop(result,NULL,ic,TRUE);
8359 }
8360
8361 #if 0
8362 /*-----------------------------------------------------------------*/
8363 /* AccRol - rotate left accumulator by known count                 */
8364 /*-----------------------------------------------------------------*/
8365 static void AccRol (int shCount)
8366 {
8367     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8368     shCount &= 0x0007;              // shCount : 0..7
8369     switch(shCount){
8370         case 0 :
8371             break;
8372         case 1 :
8373             pic16_emitcode("rl","a");
8374             break;
8375         case 2 :
8376             pic16_emitcode("rl","a");
8377             pic16_emitcode("rl","a");
8378             break;
8379         case 3 :
8380             pic16_emitcode("swap","a");
8381             pic16_emitcode("rr","a");
8382             break;
8383         case 4 :
8384             pic16_emitcode("swap","a");
8385             break;
8386         case 5 :
8387             pic16_emitcode("swap","a");
8388             pic16_emitcode("rl","a");
8389             break;
8390         case 6 :
8391             pic16_emitcode("rr","a");
8392             pic16_emitcode("rr","a");
8393             break;
8394         case 7 :
8395             pic16_emitcode("rr","a");
8396             break;
8397     }
8398 }
8399 #endif
8400
8401 /*-----------------------------------------------------------------*/
8402 /* AccLsh - left shift accumulator by known count                  */
8403 /*-----------------------------------------------------------------*/
8404 static void AccLsh (int shCount)
8405 {
8406         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8407         switch(shCount){
8408                 case 0 :
8409                         return;
8410                         break;
8411                 case 1 :
8412                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8413                         break;
8414                 case 2 :
8415                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8416                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8417                         break;
8418                 case 3 :
8419                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8420                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8421                         break;
8422                 case 4 :
8423                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8424                         break;
8425                 case 5 :
8426                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8427                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8428                         break;
8429                 case 6 :
8430                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8431                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8432                         break;
8433                 case 7 :
8434                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8435                         break;
8436         }
8437
8438         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8439 }
8440
8441 /*-----------------------------------------------------------------*/
8442 /* AccRsh - right shift accumulator by known count                 */
8443 /*-----------------------------------------------------------------*/
8444 static void AccRsh (int shCount, int andmask)
8445 {
8446         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8447         switch(shCount){
8448                 case 0 :
8449                         return; break;
8450                 case 1 :
8451                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8452                         break;
8453                 case 2 :
8454                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8455                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8456                         break;
8457                 case 3 :
8458                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8459                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460                         break;
8461                 case 4 :
8462                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8463                         break;
8464                 case 5 :
8465                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8466                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467                         break;
8468                 case 6 :
8469                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8470                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8471                         break;
8472                 case 7 :
8473                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8474                         break;
8475         }
8476         
8477         if(andmask)
8478                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8479         else
8480                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8481 }
8482
8483 #if 0
8484 /*-----------------------------------------------------------------*/
8485 /* AccSRsh - signed right shift accumulator by known count                 */
8486 /*-----------------------------------------------------------------*/
8487 static void AccSRsh (int shCount)
8488 {
8489     symbol *tlbl ;
8490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8491     if(shCount != 0){
8492         if(shCount == 1){
8493             pic16_emitcode("mov","c,acc.7");
8494             pic16_emitcode("rrc","a");
8495         } else if(shCount == 2){
8496             pic16_emitcode("mov","c,acc.7");
8497             pic16_emitcode("rrc","a");
8498             pic16_emitcode("mov","c,acc.7");
8499             pic16_emitcode("rrc","a");
8500         } else {
8501             tlbl = newiTempLabel(NULL);
8502             /* rotate right accumulator */
8503             AccRol(8 - shCount);
8504             /* and kill the higher order bits */
8505             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8506             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8507             pic16_emitcode("orl","a,#0x%02x",
8508                      (unsigned char)~SRMask[shCount]);
8509             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8510         }
8511     }
8512 }
8513 #endif
8514
8515 /*-----------------------------------------------------------------*/
8516 /* shiftR1Left2Result - shift right one byte from left to result   */
8517 /*-----------------------------------------------------------------*/
8518 static void shiftR1Left2ResultSigned (operand *left, int offl,
8519                                 operand *result, int offr,
8520                                 int shCount)
8521 {
8522   int same;
8523
8524   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8525
8526   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8527
8528   switch(shCount) {
8529   case 1:
8530     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8531     if(same) 
8532       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8533     else {
8534       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8535       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8536     }
8537
8538     break;
8539   case 2:
8540
8541     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8542     if(same) 
8543       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8544     else {
8545       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8546       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8547     }
8548     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8549     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8550
8551     break;
8552
8553   case 3:
8554     if(same)
8555       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8556     else {
8557       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8558       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8559     }
8560
8561     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8562     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8563     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8564
8565     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8566     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8567
8568     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8569     break;
8570
8571   case 4:
8572     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8573     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8574     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8575     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8576     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8577     break;
8578   case 5:
8579     if(same) {
8580       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8581     } else {
8582       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8583       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8584     }
8585     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8586     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8587     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8588     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8589     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8590     break;
8591
8592   case 6:
8593     if(same) {
8594       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8595       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8596       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8597       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8598       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8599       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8600     } else {
8601       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8602       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8603       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8604       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8605       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8606     }
8607     break;
8608
8609   case 7:
8610     if(same) {
8611       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8612       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8613       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8614       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8615     } else {
8616       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8617       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8618       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
8619     }
8620
8621   default:
8622     break;
8623   }
8624 }
8625
8626 /*-----------------------------------------------------------------*/
8627 /* shiftR1Left2Result - shift right one byte from left to result   */
8628 /*-----------------------------------------------------------------*/
8629 static void shiftR1Left2Result (operand *left, int offl,
8630                                 operand *result, int offr,
8631                                 int shCount, int sign)
8632 {
8633   int same;
8634
8635   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8636
8637   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8638
8639   /* Copy the msb into the carry if signed. */
8640   if(sign) {
8641     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8642     return;
8643   }
8644
8645
8646
8647   switch(shCount) {
8648   case 1:
8649     emitCLRC;
8650     if(same) 
8651       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8652     else {
8653       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8654       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8655     }
8656     break;
8657   case 2:
8658     emitCLRC;
8659     if(same) {
8660       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8661     } else {
8662       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8663       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8664     }
8665     emitCLRC;
8666     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8667
8668     break;
8669   case 3:
8670     if(same)
8671       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8672     else {
8673       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8675     }
8676
8677     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8678     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8679     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8680     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8681     break;
8682       
8683   case 4:
8684     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8685     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8686     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8687     break;
8688
8689   case 5:
8690     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8691     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8692     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8693     //emitCLRC;
8694     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8695
8696     break;
8697   case 6:
8698
8699     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8700     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8701     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8703     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8704     break;
8705
8706   case 7:
8707
8708     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8709     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8710     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8711
8712     break;
8713
8714   default:
8715     break;
8716   }
8717 }
8718
8719 /*-----------------------------------------------------------------*/
8720 /* shiftL1Left2Result - shift left one byte from left to result    */
8721 /*-----------------------------------------------------------------*/
8722 static void shiftL1Left2Result (operand *left, int offl,
8723                                 operand *result, int offr, int shCount)
8724 {
8725   int same;
8726
8727   //    char *l;
8728   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8729
8730   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8731   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8732     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8733     //    MOVA(l);
8734     /* shift left accumulator */
8735     //AccLsh(shCount); // don't comment out just yet...
8736   //    pic16_aopPut(AOP(result),"a",offr);
8737
8738   switch(shCount) {
8739   case 1:
8740     /* Shift left 1 bit position */
8741     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8742     if(same) {
8743       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8744     } else {
8745       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8746       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8747     }
8748     break;
8749   case 2:
8750     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8751     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8752     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8753     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8754     break;
8755   case 3:
8756     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8757     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8758     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8759     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8760     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8761     break;
8762   case 4:
8763     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8764     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8765     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8766     break;
8767   case 5:
8768     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8769     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8770     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8771     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8772     break;
8773   case 6:
8774     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8775     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8776     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8777     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8778     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8779     break;
8780   case 7:
8781     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8783     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8784     break;
8785
8786   default:
8787     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8788   }
8789
8790 }
8791
8792 /*-----------------------------------------------------------------*/
8793 /* movLeft2Result - move byte from left to result                  */
8794 /*-----------------------------------------------------------------*/
8795 static void movLeft2Result (operand *left, int offl,
8796                             operand *result, int offr)
8797 {
8798   char *l;
8799   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8800   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8801     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8802
8803     if (*l == '@' && (IS_AOP_PREG(result))) {
8804       pic16_emitcode("mov","a,%s",l);
8805       pic16_aopPut(AOP(result),"a",offr);
8806     } else {
8807       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8808       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8809     }
8810   }
8811 }
8812
8813 /*-----------------------------------------------------------------*/
8814 /* shiftL2Left2Result - shift left two bytes from left to result   */
8815 /*-----------------------------------------------------------------*/
8816 static void shiftL2Left2Result (operand *left, int offl,
8817                                 operand *result, int offr, int shCount)
8818 {
8819   int same = pic16_sameRegs(AOP(result), AOP(left));
8820   int i;
8821
8822   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8823
8824   if (same && (offl != offr)) { // shift bytes
8825     if (offr > offl) {
8826        for(i=1;i>-1;i--) {
8827          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8828          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8829        }
8830     } else { // just treat as different later on
8831                 same = 0;
8832     }
8833   }
8834
8835   if(same) {
8836     switch(shCount) {
8837     case 0:
8838       break;
8839     case 1:
8840     case 2:
8841     case 3:
8842
8843       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8844       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8845       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8846
8847       while(--shCount) {
8848                 emitCLRC;
8849                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8850                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8851       }
8852
8853       break;
8854     case 4:
8855     case 5:
8856       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8857       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8858       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8859       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8860       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8861       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8862       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8863       if(shCount >=5) {
8864                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8865                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8866       }
8867       break;
8868     case 6:
8869       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8870       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8871       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8872       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8873       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8874       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8875       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8876       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8877       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8878       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8879       break;
8880     case 7:
8881       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8882       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8883       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8884       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8885       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8886     }
8887
8888   } else {
8889     switch(shCount) {
8890     case 0:
8891       break;
8892     case 1:
8893     case 2:
8894     case 3:
8895       /* note, use a mov/add for the shift since the mov has a
8896          chance of getting optimized out */
8897       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8898       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8899       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8900       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8901       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8902
8903       while(--shCount) {
8904                 emitCLRC;
8905                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8906                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8907       }
8908       break;
8909
8910     case 4:
8911     case 5:
8912       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8913       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8914       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8915       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8916       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8917       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8918       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8919       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8920
8921
8922       if(shCount == 5) {
8923                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8924                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8925       }
8926       break;
8927     case 6:
8928       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8929       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8930       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8931       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8932
8933       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8934       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8935       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8936       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8937       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8938       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8939       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8940       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8941       break;
8942     case 7:
8943       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8944       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8945       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8946       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8947       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8948     }
8949   }
8950
8951 }
8952 /*-----------------------------------------------------------------*/
8953 /* shiftR2Left2Result - shift right two bytes from left to result  */
8954 /*-----------------------------------------------------------------*/
8955 static void shiftR2Left2Result (operand *left, int offl,
8956                                 operand *result, int offr,
8957                                 int shCount, int sign)
8958 {
8959   int same = pic16_sameRegs(AOP(result), AOP(left));
8960   int i;
8961   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8962
8963   if (same && (offl != offr)) { // shift right bytes
8964     if (offr < offl) {
8965        for(i=0;i<2;i++) {
8966          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8967          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8968        }
8969     } else { // just treat as different later on
8970                 same = 0;
8971     }
8972   }
8973
8974   switch(shCount) {
8975   case 0:
8976     break;
8977   case 1:
8978   case 2:
8979   case 3:
8980     if(sign)
8981       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8982     else
8983       emitCLRC;
8984
8985     if(same) {
8986       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8987       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8988     } else {
8989       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8990       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8991       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8992       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8993     }
8994
8995     while(--shCount) {
8996       if(sign)
8997                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8998       else
8999                 emitCLRC;
9000       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9001       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9002     }
9003     break;
9004   case 4:
9005   case 5:
9006     if(same) {
9007
9008       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9009       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9010       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9011
9012       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9013       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9014       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9015       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9016     } else {
9017       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9018       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9019       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9020
9021       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9023       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9024       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9026     }
9027
9028     if(shCount >=5) {
9029       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9030       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9031     }
9032
9033     if(sign) {
9034       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9035       pic16_emitpcode(POC_BTFSC, 
9036                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9037       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9038     }
9039
9040     break;
9041
9042   case 6:
9043     if(same) {
9044
9045       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9046       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9047
9048       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9049       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9050       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9051       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9052       if(sign) {
9053         pic16_emitpcode(POC_BTFSC, 
9054                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9055         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9056       }
9057       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9058       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9059       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9060       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9061     } else {
9062       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9063       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9064       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9065       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9066       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9067       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9068       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9069       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9070       if(sign) {
9071         pic16_emitpcode(POC_BTFSC, 
9072                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9073         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9074       }
9075       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9076       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9077
9078         
9079     }
9080
9081     break;
9082   case 7:
9083     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9084     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9085     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9086     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9087     if(sign) {
9088       emitSKPNC;
9089       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9090     } else 
9091       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9092   }
9093 }
9094
9095
9096 /*-----------------------------------------------------------------*/
9097 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9098 /*-----------------------------------------------------------------*/
9099 static void shiftLLeftOrResult (operand *left, int offl,
9100                                 operand *result, int offr, int shCount)
9101 {
9102     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9103
9104     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9105     /* shift left accumulator */
9106     AccLsh(shCount);
9107     /* or with result */
9108     /* back to result */
9109     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9110 }
9111
9112 /*-----------------------------------------------------------------*/
9113 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9114 /*-----------------------------------------------------------------*/
9115 static void shiftRLeftOrResult (operand *left, int offl,
9116                                 operand *result, int offr, int shCount)
9117 {
9118     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9119     
9120     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9121     /* shift right accumulator */
9122     AccRsh(shCount, 1);
9123     /* or with result */
9124     /* back to result */
9125     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9126 }
9127
9128 /*-----------------------------------------------------------------*/
9129 /* genlshOne - left shift a one byte quantity by known count       */
9130 /*-----------------------------------------------------------------*/
9131 static void genlshOne (operand *result, operand *left, int shCount)
9132 {       
9133     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9134     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9135 }
9136
9137 /*-----------------------------------------------------------------*/
9138 /* genlshTwo - left shift two bytes by known amount != 0           */
9139 /*-----------------------------------------------------------------*/
9140 static void genlshTwo (operand *result,operand *left, int shCount)
9141 {
9142     int size;
9143     
9144     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9145     size = pic16_getDataSize(result);
9146
9147     /* if shCount >= 8 */
9148     if (shCount >= 8) {
9149         shCount -= 8 ;
9150
9151         if (size > 1){
9152             if (shCount)
9153                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9154             else 
9155                 movLeft2Result(left, LSB, result, MSB16);
9156         }
9157         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9158     }
9159
9160     /*  1 <= shCount <= 7 */
9161     else {  
9162         if(size == 1)
9163             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9164         else 
9165             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9166     }
9167 }
9168
9169 /*-----------------------------------------------------------------*/
9170 /* shiftLLong - shift left one long from left to result            */
9171 /* offr = LSB or MSB16                                             */
9172 /*-----------------------------------------------------------------*/
9173 static void shiftLLong (operand *left, operand *result, int offr )
9174 {
9175     int size = AOP_SIZE(result);
9176     int same = pic16_sameRegs(AOP(left),AOP(result));
9177         int i;
9178
9179     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9180
9181         if (same && (offr == MSB16)) { //shift one byte
9182                 for(i=size-1;i>=MSB16;i--) {
9183                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9184                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9185                 }
9186         } else {
9187                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9188         }
9189         
9190     if (size > LSB+offr ){
9191                 if (same) {
9192                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9193                 } else {
9194                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9195                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9196                 }
9197          }
9198
9199     if(size > MSB16+offr){
9200                 if (same) {
9201                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9202                 } else {
9203                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9204                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9205                 }
9206     }
9207
9208     if(size > MSB24+offr){
9209                 if (same) {
9210                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9211                 } else {
9212                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9213                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9214                 }
9215     }
9216
9217     if(size > MSB32+offr){
9218                 if (same) {
9219                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9220                 } else {
9221                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9222                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9223                 }
9224     }
9225     if(offr != LSB)
9226                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9227
9228 }
9229
9230 /*-----------------------------------------------------------------*/
9231 /* genlshFour - shift four byte by a known amount != 0             */
9232 /*-----------------------------------------------------------------*/
9233 static void genlshFour (operand *result, operand *left, int shCount)
9234 {
9235     int size;
9236
9237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9238     size = AOP_SIZE(result);
9239
9240     /* if shifting more that 3 bytes */
9241     if (shCount >= 24 ) {
9242         shCount -= 24;
9243         if (shCount)
9244             /* lowest order of left goes to the highest
9245             order of the destination */
9246             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9247         else
9248             movLeft2Result(left, LSB, result, MSB32);
9249
9250                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9251                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9252                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9253
9254         return;
9255     }
9256
9257     /* more than two bytes */
9258     else if ( shCount >= 16 ) {
9259         /* lower order two bytes goes to higher order two bytes */
9260         shCount -= 16;
9261         /* if some more remaining */
9262         if (shCount)
9263             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9264         else {
9265             movLeft2Result(left, MSB16, result, MSB32);
9266             movLeft2Result(left, LSB, result, MSB24);
9267         }
9268                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9269                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9270         return;
9271     }    
9272
9273     /* if more than 1 byte */
9274     else if ( shCount >= 8 ) {
9275         /* lower order three bytes goes to higher order  three bytes */
9276         shCount -= 8;
9277         if(size == 2){
9278             if(shCount)
9279                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9280             else
9281                 movLeft2Result(left, LSB, result, MSB16);
9282         }
9283         else{   /* size = 4 */
9284             if(shCount == 0){
9285                 movLeft2Result(left, MSB24, result, MSB32);
9286                 movLeft2Result(left, MSB16, result, MSB24);
9287                 movLeft2Result(left, LSB, result, MSB16);
9288                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9289             }
9290             else if(shCount == 1)
9291                 shiftLLong(left, result, MSB16);
9292             else{
9293                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9294                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9295                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9296                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9297             }
9298         }
9299     }
9300
9301     /* 1 <= shCount <= 7 */
9302     else if(shCount <= 3)
9303     { 
9304         shiftLLong(left, result, LSB);
9305         while(--shCount >= 1)
9306             shiftLLong(result, result, LSB);
9307     }
9308     /* 3 <= shCount <= 7, optimize */
9309     else{
9310         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9311         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9312         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9313     }
9314 }
9315
9316 /*-----------------------------------------------------------------*/
9317 /* genLeftShiftLiteral - left shifting by known count              */
9318 /*-----------------------------------------------------------------*/
9319 void pic16_genLeftShiftLiteral (operand *left,
9320                                  operand *right,
9321                                  operand *result,
9322                                  iCode *ic)
9323 {    
9324     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9325     int size;
9326
9327     FENTRY;
9328     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9329     pic16_freeAsmop(right,NULL,ic,TRUE);
9330
9331     pic16_aopOp(left,ic,FALSE);
9332     pic16_aopOp(result,ic,FALSE);
9333
9334     size = getSize(operandType(result));
9335
9336 #if VIEW_SIZE
9337     pic16_emitcode("; shift left ","result %d, left %d",size,
9338              AOP_SIZE(left));
9339 #endif
9340
9341     /* I suppose that the left size >= result size */
9342     if(shCount == 0){
9343         while(size--){
9344             movLeft2Result(left, size, result, size);
9345         }
9346     }
9347
9348     else if(shCount >= (size * 8))
9349         while(size--)
9350             pic16_aopPut(AOP(result),zero,size);
9351     else{
9352         switch (size) {
9353             case 1:
9354                 genlshOne (result,left,shCount);
9355                 break;
9356
9357             case 2:
9358             case 3:
9359                 genlshTwo (result,left,shCount);
9360                 break;
9361
9362             case 4:
9363                 genlshFour (result,left,shCount);
9364                 break;
9365         }
9366     }
9367     pic16_freeAsmop(left,NULL,ic,TRUE);
9368     pic16_freeAsmop(result,NULL,ic,TRUE);
9369 }
9370
9371 /*-----------------------------------------------------------------*
9372  * genMultiAsm - repeat assembly instruction for size of register.
9373  * if endian == 1, then the high byte (i.e base address + size of 
9374  * register) is used first else the low byte is used first;
9375  *-----------------------------------------------------------------*/
9376 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9377 {
9378
9379   int offset = 0;
9380
9381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9382
9383   if(!reg)
9384     return;
9385
9386   if(!endian) {
9387     endian = 1;
9388   } else {
9389     endian = -1;
9390     offset = size-1;
9391   }
9392
9393   while(size--) {
9394     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9395     offset += endian;
9396   }
9397
9398 }
9399 /*-----------------------------------------------------------------*/
9400 /* genLeftShift - generates code for left shifting                 */
9401 /*-----------------------------------------------------------------*/
9402 static void genLeftShift (iCode *ic)
9403 {
9404   operand *left,*right, *result;
9405   int size, offset;
9406 //  char *l;
9407   symbol *tlbl , *tlbl1;
9408   pCodeOp *pctemp;
9409
9410   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9411
9412   right = IC_RIGHT(ic);
9413   left  = IC_LEFT(ic);
9414   result = IC_RESULT(ic);
9415
9416   pic16_aopOp(right,ic,FALSE);
9417
9418   /* if the shift count is known then do it 
9419      as efficiently as possible */
9420   if (AOP_TYPE(right) == AOP_LIT) {
9421     pic16_genLeftShiftLiteral (left,right,result,ic);
9422     return ;
9423   }
9424
9425   /* shift count is unknown then we have to form
9426    * a loop. Get the loop count in WREG : Note: we take
9427    * only the lower order byte since shifting
9428    * more than 32 bits make no sense anyway, ( the
9429    * largest size of an object can be only 32 bits ) */
9430   
9431   pic16_aopOp(left,ic,FALSE);
9432   pic16_aopOp(result,ic,FALSE);
9433
9434   /* now move the left to the result if they are not the
9435    * same, and if size > 1,
9436    * and if right is not same to result (!!!) -- VR */
9437   if (!pic16_sameRegs(AOP(left),AOP(result))
9438       && (AOP_SIZE(result) > 1)) {
9439
9440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9441
9442     size = AOP_SIZE(result);
9443     offset=0;
9444     while (size--) {
9445
9446 #if 0
9447       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9448       if (*l == '@' && (IS_AOP_PREG(result))) {
9449
9450           pic16_emitcode("mov","a,%s",l);
9451           pic16_aopPut(AOP(result),"a",offset);
9452       } else
9453 #endif
9454       {
9455         /* we don't know if left is a literal or a register, take care -- VR */
9456         mov2f(AOP(result), AOP(left), offset);
9457       }
9458       offset++;
9459     }
9460   }
9461
9462   size = AOP_SIZE(result);
9463
9464   /* if it is only one byte then */
9465   if (size == 1) {
9466     if(optimized_for_speed) {
9467       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9468       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9469       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9470       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9471       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9472       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9473       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9474       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9475       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9476       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9477       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9478       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9479     } else {
9480
9481       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9482
9483       tlbl = newiTempLabel(NULL);
9484
9485 #if 1
9486       /* this is already done, why change it? */
9487       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9488                 mov2f(AOP(result), AOP(left), 0);
9489       }
9490 #endif
9491
9492       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9493       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9494       pic16_emitpLabel(tlbl->key);
9495       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9496       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9497       emitSKPC;
9498       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9499     }
9500     goto release ;
9501   }
9502     
9503   if (pic16_sameRegs(AOP(left),AOP(result))) {
9504
9505     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9506     
9507     tlbl = newiTempLabel(NULL);
9508     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9509     genMultiAsm(POC_RRCF, result, size,1);
9510     pic16_emitpLabel(tlbl->key);
9511     genMultiAsm(POC_RLCF, result, size,0);
9512     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9513     emitSKPC;
9514     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9515     goto release;
9516   }
9517
9518   //tlbl = newiTempLabel(NULL);
9519   //offset = 0 ;   
9520   //tlbl1 = newiTempLabel(NULL);
9521
9522   //reAdjustPreg(AOP(result));    
9523     
9524   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9525   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9526   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9527   //MOVA(l);
9528   //pic16_emitcode("add","a,acc");         
9529   //pic16_aopPut(AOP(result),"a",offset++);
9530   //while (--size) {
9531   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9532   //  MOVA(l);
9533   //  pic16_emitcode("rlc","a");         
9534   //  pic16_aopPut(AOP(result),"a",offset++);
9535   //}
9536   //reAdjustPreg(AOP(result));
9537
9538   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9539   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9540
9541
9542   tlbl = newiTempLabel(NULL);
9543   tlbl1= newiTempLabel(NULL);
9544
9545   size = AOP_SIZE(result);
9546   offset = 1;
9547
9548   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9549
9550   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9551
9552   /* offset should be 0, 1 or 3 */
9553   
9554   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9555   emitSKPNZ;
9556   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9557
9558   pic16_emitpcode(POC_MOVWF, pctemp);
9559
9560
9561   pic16_emitpLabel(tlbl->key);
9562
9563   emitCLRC;
9564   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9565   while(--size)
9566     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9567
9568   pic16_emitpcode(POC_DECFSZ,  pctemp);
9569   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9570   pic16_emitpLabel(tlbl1->key);
9571
9572   pic16_popReleaseTempReg(pctemp,1);
9573
9574
9575  release:
9576   pic16_freeAsmop (right,NULL,ic,TRUE);
9577   pic16_freeAsmop(left,NULL,ic,TRUE);
9578   pic16_freeAsmop(result,NULL,ic,TRUE);
9579 }
9580
9581
9582
9583 #if 0
9584 #error old code (left here for reference)
9585 /*-----------------------------------------------------------------*/
9586 /* genLeftShift - generates code for left shifting                 */
9587 /*-----------------------------------------------------------------*/
9588 static void genLeftShift (iCode *ic)
9589 {
9590   operand *left,*right, *result;
9591   int size, offset;
9592   char *l;
9593   symbol *tlbl , *tlbl1;
9594   pCodeOp *pctemp;
9595
9596   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9597
9598   right = IC_RIGHT(ic);
9599   left  = IC_LEFT(ic);
9600   result = IC_RESULT(ic);
9601
9602   pic16_aopOp(right,ic,FALSE);
9603
9604   /* if the shift count is known then do it 
9605      as efficiently as possible */
9606   if (AOP_TYPE(right) == AOP_LIT) {
9607     pic16_genLeftShiftLiteral (left,right,result,ic);
9608     return ;
9609   }
9610
9611   /* shift count is unknown then we have to form 
9612      a loop get the loop count in B : Note: we take
9613      only the lower order byte since shifting
9614      more that 32 bits make no sense anyway, ( the
9615      largest size of an object can be only 32 bits ) */  
9616
9617     
9618   pic16_aopOp(left,ic,FALSE);
9619   pic16_aopOp(result,ic,FALSE);
9620
9621   /* now move the left to the result if they are not the
9622      same */
9623   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9624       AOP_SIZE(result) > 1) {
9625
9626     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9627
9628     size = AOP_SIZE(result);
9629     offset=0;
9630     while (size--) {
9631       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9632       if (*l == '@' && (IS_AOP_PREG(result))) {
9633
9634         pic16_emitcode("mov","a,%s",l);
9635         pic16_aopPut(AOP(result),"a",offset);
9636       } else {
9637
9638         /* we don't know if left is a literal or a register, take care -- VR */
9639         mov2f(AOP(result), AOP(left), offset);
9640       }
9641       offset++;
9642     }
9643   }
9644
9645   size = AOP_SIZE(result);
9646
9647   /* if it is only one byte then */
9648   if (size == 1) {
9649     if(optimized_for_speed) {
9650       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9651       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9652       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9653       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9654       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9655       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9656       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9657       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9658       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9659       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9660       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9661       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9662     } else {
9663
9664       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9665
9666       tlbl = newiTempLabel(NULL);
9667       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9668                 mov2f(AOP(result), AOP(left), 0);
9669                 
9670 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9671 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9672       }
9673
9674       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9675       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9676       pic16_emitpLabel(tlbl->key);
9677       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9678       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9679       emitSKPC;
9680       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9681     }
9682     goto release ;
9683   }
9684     
9685   if (pic16_sameRegs(AOP(left),AOP(result))) {
9686
9687     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9688     
9689     tlbl = newiTempLabel(NULL);
9690     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9691     genMultiAsm(POC_RRCF, result, size,1);
9692     pic16_emitpLabel(tlbl->key);
9693     genMultiAsm(POC_RLCF, result, size,0);
9694     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9695     emitSKPC;
9696     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9697     goto release;
9698   }
9699
9700   //tlbl = newiTempLabel(NULL);
9701   //offset = 0 ;   
9702   //tlbl1 = newiTempLabel(NULL);
9703
9704   //reAdjustPreg(AOP(result));    
9705     
9706   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9707   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9708   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9709   //MOVA(l);
9710   //pic16_emitcode("add","a,acc");         
9711   //pic16_aopPut(AOP(result),"a",offset++);
9712   //while (--size) {
9713   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9714   //  MOVA(l);
9715   //  pic16_emitcode("rlc","a");         
9716   //  pic16_aopPut(AOP(result),"a",offset++);
9717   //}
9718   //reAdjustPreg(AOP(result));
9719
9720   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9721   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9722
9723
9724   tlbl = newiTempLabel(NULL);
9725   tlbl1= newiTempLabel(NULL);
9726
9727   size = AOP_SIZE(result);
9728   offset = 1;
9729
9730   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9731
9732   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9733
9734   /* offset should be 0, 1 or 3 */
9735   
9736   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9737   emitSKPNZ;
9738   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9739
9740   pic16_emitpcode(POC_MOVWF, pctemp);
9741
9742
9743   pic16_emitpLabel(tlbl->key);
9744
9745   emitCLRC;
9746   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9747   while(--size)
9748     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9749
9750   pic16_emitpcode(POC_DECFSZ,  pctemp);
9751   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9752   pic16_emitpLabel(tlbl1->key);
9753
9754   pic16_popReleaseTempReg(pctemp,1);
9755
9756
9757  release:
9758   pic16_freeAsmop (right,NULL,ic,TRUE);
9759   pic16_freeAsmop(left,NULL,ic,TRUE);
9760   pic16_freeAsmop(result,NULL,ic,TRUE);
9761 }
9762 #endif
9763
9764 /*-----------------------------------------------------------------*/
9765 /* genrshOne - right shift a one byte quantity by known count      */
9766 /*-----------------------------------------------------------------*/
9767 static void genrshOne (operand *result, operand *left,
9768                        int shCount, int sign)
9769 {
9770     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9771     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9772 }
9773
9774 /*-----------------------------------------------------------------*/
9775 /* genrshTwo - right shift two bytes by known amount != 0          */
9776 /*-----------------------------------------------------------------*/
9777 static void genrshTwo (operand *result,operand *left,
9778                        int shCount, int sign)
9779 {
9780   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9781   /* if shCount >= 8 */
9782   if (shCount >= 8) {
9783     shCount -= 8 ;
9784     if (shCount)
9785       shiftR1Left2Result(left, MSB16, result, LSB,
9786                          shCount, sign);
9787     else
9788       movLeft2Result(left, MSB16, result, LSB);
9789
9790     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9791
9792     if(sign) {
9793       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9794       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9795     }
9796   }
9797
9798   /*  1 <= shCount <= 7 */
9799   else
9800     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9801 }
9802
9803 /*-----------------------------------------------------------------*/
9804 /* shiftRLong - shift right one long from left to result           */
9805 /* offl = LSB or MSB16                                             */
9806 /*-----------------------------------------------------------------*/
9807 static void shiftRLong (operand *left, int offl,
9808                         operand *result, int sign)
9809 {
9810     int size = AOP_SIZE(result);
9811     int same = pic16_sameRegs(AOP(left),AOP(result));
9812     int i;
9813     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9814
9815         if (same && (offl == MSB16)) { //shift one byte right
9816                 for(i=MSB16;i<size;i++) {
9817                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9818                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9819                 }
9820         }
9821
9822     if(sign)
9823                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9824         else
9825                 emitCLRC;
9826
9827         if (same) {
9828                 if (offl == LSB)
9829                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9830         } else {
9831         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9832         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9833         }
9834
9835     if(offl == MSB16) {
9836         /* add sign of "a" */
9837         pic16_addSign(result, MSB32, sign);
9838         }
9839
9840         if (same) {
9841         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9842         } else {
9843         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9844         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9845         }
9846         
9847         if (same) {
9848         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9849         } else {
9850         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9851         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9852         }
9853
9854         if (same) {
9855         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9856         } else {
9857         if(offl == LSB){
9858                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9859                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9860         }
9861         }
9862 }
9863
9864 /*-----------------------------------------------------------------*/
9865 /* genrshFour - shift four byte by a known amount != 0             */
9866 /*-----------------------------------------------------------------*/
9867 static void genrshFour (operand *result, operand *left,
9868                         int shCount, int sign)
9869 {
9870   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9871   /* if shifting more that 3 bytes */
9872   if(shCount >= 24 ) {
9873     shCount -= 24;
9874     if(shCount)
9875       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9876     else
9877       movLeft2Result(left, MSB32, result, LSB);
9878
9879     pic16_addSign(result, MSB16, sign);
9880   }
9881   else if(shCount >= 16){
9882     shCount -= 16;
9883     if(shCount)
9884       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9885     else{
9886       movLeft2Result(left, MSB24, result, LSB);
9887       movLeft2Result(left, MSB32, result, MSB16);
9888     }
9889     pic16_addSign(result, MSB24, sign);
9890   }
9891   else if(shCount >= 8){
9892     shCount -= 8;
9893     if(shCount == 1)
9894       shiftRLong(left, MSB16, result, sign);
9895     else if(shCount == 0){
9896       movLeft2Result(left, MSB16, result, LSB);
9897       movLeft2Result(left, MSB24, result, MSB16);
9898       movLeft2Result(left, MSB32, result, MSB24);
9899       pic16_addSign(result, MSB32, sign);
9900     }
9901     else{ //shcount >= 2
9902       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9903       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9904       /* the last shift is signed */
9905       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9906       pic16_addSign(result, MSB32, sign);
9907     }
9908   }
9909   else{   /* 1 <= shCount <= 7 */
9910     if(shCount <= 2){
9911       shiftRLong(left, LSB, result, sign);
9912       if(shCount == 2)
9913         shiftRLong(result, LSB, result, sign);
9914     }
9915     else{
9916       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9917       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9918       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9919     }
9920   }
9921 }
9922
9923 /*-----------------------------------------------------------------*/
9924 /* genRightShiftLiteral - right shifting by known count            */
9925 /*-----------------------------------------------------------------*/
9926 static void genRightShiftLiteral (operand *left,
9927                                   operand *right,
9928                                   operand *result,
9929                                   iCode *ic,
9930                                   int sign)
9931 {    
9932   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9933   int lsize,res_size;
9934
9935   pic16_freeAsmop(right,NULL,ic,TRUE);
9936
9937   pic16_aopOp(left,ic,FALSE);
9938   pic16_aopOp(result,ic,FALSE);
9939
9940   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9941
9942 #if VIEW_SIZE
9943   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9944                  AOP_SIZE(left));
9945 #endif
9946
9947   lsize = pic16_getDataSize(left);
9948   res_size = pic16_getDataSize(result);
9949   /* test the LEFT size !!! */
9950
9951   /* I suppose that the left size >= result size */
9952   if(shCount == 0){
9953     while(res_size--)
9954       movLeft2Result(left, lsize, result, res_size);
9955   }
9956
9957   else if(shCount >= (lsize * 8)){
9958
9959     if(res_size == 1) {
9960       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9961       if(sign) {
9962         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9963         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9964       }
9965     } else {
9966
9967       if(sign) {
9968         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9969         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9970         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9971         while(res_size--)
9972           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9973
9974       } else {
9975
9976         while(res_size--)
9977           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9978       }
9979     }
9980   } else {
9981
9982     switch (res_size) {
9983     case 1:
9984       genrshOne (result,left,shCount,sign);
9985       break;
9986
9987     case 2:
9988       genrshTwo (result,left,shCount,sign);
9989       break;
9990
9991     case 4:
9992       genrshFour (result,left,shCount,sign);
9993       break;
9994     default :
9995       break;
9996     }
9997
9998   }
9999
10000   pic16_freeAsmop(left,NULL,ic,TRUE);
10001   pic16_freeAsmop(result,NULL,ic,TRUE);
10002 }
10003
10004 /*-----------------------------------------------------------------*/
10005 /* genSignedRightShift - right shift of signed number              */
10006 /*-----------------------------------------------------------------*/
10007 static void genSignedRightShift (iCode *ic)
10008 {
10009   operand *right, *left, *result;
10010   int size, offset;
10011   //  char *l;
10012   symbol *tlbl, *tlbl1 ;
10013   pCodeOp *pctemp;
10014
10015   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10016
10017   /* we do it the hard way put the shift count in b
10018      and loop thru preserving the sign */
10019   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10020
10021   right = IC_RIGHT(ic);
10022   left  = IC_LEFT(ic);
10023   result = IC_RESULT(ic);
10024
10025   pic16_aopOp(right,ic,FALSE);  
10026   pic16_aopOp(left,ic,FALSE);
10027   pic16_aopOp(result,ic,FALSE);
10028
10029
10030   if ( AOP_TYPE(right) == AOP_LIT) {
10031     genRightShiftLiteral (left,right,result,ic,1);
10032     return ;
10033   }
10034   /* shift count is unknown then we have to form 
10035      a loop get the loop count in B : Note: we take
10036      only the lower order byte since shifting
10037      more that 32 bits make no sense anyway, ( the
10038      largest size of an object can be only 32 bits ) */  
10039
10040   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10041   //pic16_emitcode("inc","b");
10042   //pic16_freeAsmop (right,NULL,ic,TRUE);
10043   //pic16_aopOp(left,ic,FALSE);
10044   //pic16_aopOp(result,ic,FALSE);
10045
10046   /* now move the left to the result if they are not the
10047      same */
10048   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10049       AOP_SIZE(result) > 1) {
10050
10051     size = AOP_SIZE(result);
10052     offset=0;
10053     while (size--) { 
10054       /*
10055         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10056         if (*l == '@' && IS_AOP_PREG(result)) {
10057
10058         pic16_emitcode("mov","a,%s",l);
10059         pic16_aopPut(AOP(result),"a",offset);
10060         } else
10061         pic16_aopPut(AOP(result),l,offset);
10062       */
10063       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10064       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10065
10066       offset++;
10067     }
10068   }
10069
10070   /* mov the highest order bit to OVR */    
10071   tlbl = newiTempLabel(NULL);
10072   tlbl1= newiTempLabel(NULL);
10073
10074   size = AOP_SIZE(result);
10075   offset = size - 1;
10076
10077   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10078
10079   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10080
10081   /* offset should be 0, 1 or 3 */
10082   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10083   emitSKPNZ;
10084   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10085
10086   pic16_emitpcode(POC_MOVWF, pctemp);
10087
10088
10089   pic16_emitpLabel(tlbl->key);
10090
10091   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10092   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10093
10094   while(--size) {
10095     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10096   }
10097
10098   pic16_emitpcode(POC_DECFSZ,  pctemp);
10099   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10100   pic16_emitpLabel(tlbl1->key);
10101
10102   pic16_popReleaseTempReg(pctemp,1);
10103 #if 0
10104   size = AOP_SIZE(result);
10105   offset = size - 1;
10106   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10107   pic16_emitcode("rlc","a");
10108   pic16_emitcode("mov","ov,c");
10109   /* if it is only one byte then */
10110   if (size == 1) {
10111     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10112     MOVA(l);
10113     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10114     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10115     pic16_emitcode("mov","c,ov");
10116     pic16_emitcode("rrc","a");
10117     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10118     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10119     pic16_aopPut(AOP(result),"a",0);
10120     goto release ;
10121   }
10122
10123   reAdjustPreg(AOP(result));
10124   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10125   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10126   pic16_emitcode("mov","c,ov");
10127   while (size--) {
10128     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10129     MOVA(l);
10130     pic16_emitcode("rrc","a");         
10131     pic16_aopPut(AOP(result),"a",offset--);
10132   }
10133   reAdjustPreg(AOP(result));
10134   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10135   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10136
10137  release:
10138 #endif
10139
10140   pic16_freeAsmop(left,NULL,ic,TRUE);
10141   pic16_freeAsmop(result,NULL,ic,TRUE);
10142   pic16_freeAsmop(right,NULL,ic,TRUE);
10143 }
10144
10145 /*-----------------------------------------------------------------*/
10146 /* genRightShift - generate code for right shifting                */
10147 /*-----------------------------------------------------------------*/
10148 static void genRightShift (iCode *ic)
10149 {
10150     operand *right, *left, *result;
10151     sym_link *letype ;
10152     int size, offset;
10153     char *l;
10154     symbol *tlbl, *tlbl1 ;
10155
10156     /* if signed then we do it the hard way preserve the
10157     sign bit moving it inwards */
10158     letype = getSpec(operandType(IC_LEFT(ic)));
10159     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10160
10161     if (!SPEC_USIGN(letype)) {
10162         genSignedRightShift (ic);
10163         return ;
10164     }
10165
10166     /* signed & unsigned types are treated the same : i.e. the
10167     signed is NOT propagated inwards : quoting from the
10168     ANSI - standard : "for E1 >> E2, is equivalent to division
10169     by 2**E2 if unsigned or if it has a non-negative value,
10170     otherwise the result is implementation defined ", MY definition
10171     is that the sign does not get propagated */
10172
10173     right = IC_RIGHT(ic);
10174     left  = IC_LEFT(ic);
10175     result = IC_RESULT(ic);
10176
10177     pic16_aopOp(right,ic,FALSE);
10178
10179     /* if the shift count is known then do it 
10180     as efficiently as possible */
10181     if (AOP_TYPE(right) == AOP_LIT) {
10182         genRightShiftLiteral (left,right,result,ic, 0);
10183         return ;
10184     }
10185
10186     /* shift count is unknown then we have to form 
10187     a loop get the loop count in B : Note: we take
10188     only the lower order byte since shifting
10189     more that 32 bits make no sense anyway, ( the
10190     largest size of an object can be only 32 bits ) */  
10191
10192     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10193     pic16_emitcode("inc","b");
10194     pic16_aopOp(left,ic,FALSE);
10195     pic16_aopOp(result,ic,FALSE);
10196
10197     /* now move the left to the result if they are not the
10198     same */
10199     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10200         AOP_SIZE(result) > 1) {
10201
10202         size = AOP_SIZE(result);
10203         offset=0;
10204         while (size--) {
10205             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10206             if (*l == '@' && IS_AOP_PREG(result)) {
10207
10208                 pic16_emitcode("mov","a,%s",l);
10209                 pic16_aopPut(AOP(result),"a",offset);
10210             } else
10211                 pic16_aopPut(AOP(result),l,offset);
10212             offset++;
10213         }
10214     }
10215
10216     tlbl = newiTempLabel(NULL);
10217     tlbl1= newiTempLabel(NULL);
10218     size = AOP_SIZE(result);
10219     offset = size - 1;
10220
10221     /* if it is only one byte then */
10222     if (size == 1) {
10223
10224       tlbl = newiTempLabel(NULL);
10225       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10226         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10227         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10228       }
10229
10230       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10231       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10232       pic16_emitpLabel(tlbl->key);
10233       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10234       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10235       emitSKPC;
10236       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10237
10238       goto release ;
10239     }
10240
10241     reAdjustPreg(AOP(result));
10242     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10243     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10244     CLRC;
10245     while (size--) {
10246         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10247         MOVA(l);
10248         pic16_emitcode("rrc","a");         
10249         pic16_aopPut(AOP(result),"a",offset--);
10250     }
10251     reAdjustPreg(AOP(result));
10252
10253     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10254     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10255
10256 release:
10257     pic16_freeAsmop(left,NULL,ic,TRUE);
10258     pic16_freeAsmop (right,NULL,ic,TRUE);
10259     pic16_freeAsmop(result,NULL,ic,TRUE);
10260 }
10261
10262
10263 void pic16_loadFSR0(operand *op)
10264 {
10265         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10266 }
10267
10268 /*-----------------------------------------------------------------*/
10269 /* genUnpackBits - generates code for unpacking bits               */
10270 /*-----------------------------------------------------------------*/
10271 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10272 {    
10273   int shCnt ;
10274   int rlen = 0 ;
10275   sym_link *etype, *letype;
10276   int blen=0, bstr=0;
10277   int lbstr;
10278   int offset = 0 ;
10279
10280     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10281     etype = getSpec(operandType(result));
10282     letype = getSpec(operandType(left));
10283     
10284 //    if(IS_BITFIELD(etype)) {
10285       blen = SPEC_BLEN(etype);
10286       bstr = SPEC_BSTR(etype);
10287 //    }
10288
10289     lbstr = SPEC_BSTR( letype );
10290
10291 #if 1
10292     if((blen == 1) && (bstr < 8)) {
10293       /* it is a single bit, so use the appropriate bit instructions */
10294       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10295
10296       if(IS_BITFIELD(etype)/* && !IS_ITEMP(left)*/) {
10297         pic16_emitpcode(POC_MOVFW, pic16_popGet( AOP(result), 0 ));
10298         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
10299       } else {
10300         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10301       }
10302       
10303       if((ptype == POINTER) && (result)) {
10304         /* workaround to reduce the extra lfsr instruction */
10305         pic16_emitpcode(POC_BTFSC,
10306               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10307       } else {
10308         pic16_emitpcode(POC_BTFSC,
10309               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10310       }
10311         
10312
10313       if(IS_BITFIELD(etype)) {
10314         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
10315       } else {
10316         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10317       }      
10318
10319       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10320       return;
10321     }
10322
10323 #endif
10324
10325         /* the following call to pic16_loadFSR0 is temporary until
10326          * optimization to handle single bit assignments is added
10327          * to the function. Until then use the old safe way! -- VR */
10328         pic16_loadFSR0( left );
10329  
10330         /* read the first byte  */
10331         switch (ptype) {
10332                 case POINTER:
10333                 case IPOINTER:
10334                 case PPOINTER:
10335                 case FPOINTER:
10336                 case GPOINTER:
10337                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10338                         break;
10339                 case CPOINTER:
10340                         pic16_emitcode("clr","a");
10341                         pic16_emitcode("movc","a","@a+dptr");
10342                         break;
10343         }
10344         
10345
10346         /* if we have bitdisplacement then it fits   */
10347         /* into this byte completely or if length is */
10348         /* less than a byte                          */
10349         if ((shCnt = SPEC_BSTR(etype)) || 
10350                 (SPEC_BLEN(etype) <= 8))  {
10351
10352                 /* shift right acc */
10353                 AccRsh(shCnt, 0);
10354
10355                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10356                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10357
10358 /* VR -- normally I would use the following, but since we use the hack,
10359  * to avoid the masking from AccRsh, why not mask it right now? */
10360
10361 /*
10362                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10363 */
10364
10365                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10366           return ;
10367         }
10368
10369
10370
10371         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10372         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10373         exit(-1);
10374
10375     /* bit field did not fit in a byte  */
10376     rlen = SPEC_BLEN(etype) - 8;
10377     pic16_aopPut(AOP(result),"a",offset++);
10378
10379     while (1)  {
10380
10381         switch (ptype) {
10382         case POINTER:
10383         case IPOINTER:
10384             pic16_emitcode("inc","%s",rname);
10385             pic16_emitcode("mov","a,@%s",rname);
10386             break;
10387             
10388         case PPOINTER:
10389             pic16_emitcode("inc","%s",rname);
10390             pic16_emitcode("movx","a,@%s",rname);
10391             break;
10392
10393         case FPOINTER:
10394             pic16_emitcode("inc","dptr");
10395             pic16_emitcode("movx","a,@dptr");
10396             break;
10397             
10398         case CPOINTER:
10399             pic16_emitcode("clr","a");
10400             pic16_emitcode("inc","dptr");
10401             pic16_emitcode("movc","a","@a+dptr");
10402             break;
10403             
10404         case GPOINTER:
10405             pic16_emitcode("inc","dptr");
10406             pic16_emitcode("lcall","__gptrget");
10407             break;
10408         }
10409
10410         rlen -= 8;            
10411         /* if we are done */
10412         if ( rlen <= 0 )
10413             break ;
10414         
10415         pic16_aopPut(AOP(result),"a",offset++);
10416                               
10417     }
10418     
10419     if (rlen) {
10420         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10421         pic16_aopPut(AOP(result),"a",offset);          
10422     }
10423     
10424     return ;
10425 }
10426
10427
10428 static void genDataPointerGet(operand *left,
10429                               operand *result,
10430                               iCode *ic)
10431 {
10432   int size, offset = 0, leoffset=0 ;
10433
10434         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10435         pic16_aopOp(result, ic, FALSE);
10436
10437         size = AOP_SIZE(result);
10438 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10439
10440
10441 #if 0
10442         /* The following tests may save a redudant movff instruction when
10443          * accessing unions */
10444          
10445         /* if they are the same */
10446         if (operandsEqu (left, result)) {
10447                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10448                 goto release;
10449         }
10450 #endif
10451
10452 #if 0
10453         /* if they are the same registers */
10454         if (pic16_sameRegs(AOP(left),AOP(result))) {
10455                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10456                 goto release;
10457         }
10458 #endif
10459
10460 #if 1
10461         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10462                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10463                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10464                 goto release;
10465         }
10466 #endif
10467
10468
10469 #if 0
10470         if ( AOP_TYPE(left) == AOP_PCODE) {
10471                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10472                                 AOP(left)->aopu.pcop->name,
10473                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10474                                 PCOR(AOP(left)->aopu.pcop)->instance:
10475                                 PCOI(AOP(left)->aopu.pcop)->offset);
10476         }
10477 #endif
10478
10479         if(AOP(left)->aopu.pcop->type == PO_DIR)
10480                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10481
10482         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10483
10484         while (size--) {
10485                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10486                 
10487                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10488                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10489                         mov2w(AOP(left), offset); // patch 8
10490                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10491                 } else {
10492                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10493                                 pic16_popGet(AOP(left), offset), //patch 8
10494                                 pic16_popGet(AOP(result), offset)));
10495                 }
10496
10497                 offset++;
10498                 leoffset++;
10499         }
10500
10501 release:
10502     pic16_freeAsmop(result,NULL,ic,TRUE);
10503 }
10504
10505
10506
10507 /*-----------------------------------------------------------------*/
10508 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10509 /*-----------------------------------------------------------------*/
10510 static void genNearPointerGet (operand *left, 
10511                                operand *result, 
10512                                iCode *ic)
10513 {
10514   asmop *aop = NULL;
10515   //regs *preg = NULL ;
10516   sym_link *rtype, *retype;
10517   sym_link *ltype = operandType(left);    
10518
10519     FENTRY;
10520     
10521     rtype = operandType(result);
10522     retype= getSpec(rtype);
10523     
10524     pic16_aopOp(left,ic,FALSE);
10525
10526 //    pic16_DumpOp("(left)",left);
10527 //    pic16_DumpOp("(result)",result);
10528
10529     /* if left is rematerialisable and
10530      * result is not bit variable type and
10531      * the left is pointer to data space i.e
10532      * lower 128 bytes of space */
10533     
10534     if (AOP_TYPE(left) == AOP_PCODE
10535       && !IS_BITFIELD(retype)
10536       && DCL_TYPE(ltype) == POINTER) {
10537
10538         genDataPointerGet (left,result,ic);
10539         pic16_freeAsmop(left, NULL, ic, TRUE);
10540         return ;
10541     }
10542     
10543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10544
10545     /* if the value is already in a pointer register
10546      * then don't need anything more */
10547     if (!AOP_INPREG(AOP(left))) {
10548       /* otherwise get a free pointer register */
10549       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10550                 
10551       /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10552       /* bitfields will be handled by genUnpackBits */
10553       if(!IS_BITFIELD(retype)) {
10554
10555         if(is_LitAOp( AOP(left) )) {
10556           pic16_loadFSR0( left );
10557         } else {
10558             // set up FSR0 with address from left
10559             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10560             pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10561         }
10562       }
10563     }
10564 //    else
10565 //    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10566     
10567     pic16_aopOp (result,ic,FALSE);
10568     
10569     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10570
10571     /* if bitfield then unpack the bits */
10572     if (IS_BITFIELD(retype)) 
10573       genUnpackBits (result, left, NULL, POINTER);
10574     else {
10575       /* we have can just get the values */
10576       int size = AOP_SIZE(result);
10577       int offset = 0;   
10578         
10579       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10580
10581       /* fsr0 is loaded already -- VR */
10582 //      pic16_loadFSR0( left );
10583
10584 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10585 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10586       while(size--) {
10587         if(size) {
10588           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10589                 pic16_popGet(AOP(result), offset++)));
10590         } else {
10591           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10592                 pic16_popGet(AOP(result), offset++)));
10593         }
10594       }
10595 #if 0
10596 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10597 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10598       if(size)
10599         pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10600 #endif
10601 /*
10602         while (size--) {
10603             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10604
10605                 pic16_emitcode("mov","a,@%s",rname);
10606                 pic16_aopPut(AOP(result),"a",offset);
10607             } else {
10608                 sprintf(buffer,"@%s",rname);
10609                 pic16_aopPut(AOP(result),buffer,offset);
10610             }
10611             offset++ ;
10612             if (size)
10613                 pic16_emitcode("inc","%s",rname);
10614         }
10615 */
10616     }
10617
10618     /* now some housekeeping stuff */
10619     if (aop) {
10620       /* we had to allocate for this iCode */
10621       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10622       pic16_freeAsmop(NULL,aop,ic,TRUE);
10623     } else { 
10624       /* we did not allocate which means left
10625        * already in a pointer register, then
10626        * if size > 0 && this could be used again
10627        * we have to point it back to where it 
10628        * belongs */
10629       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10630       if (AOP_SIZE(result) > 1
10631         && !OP_SYMBOL(left)->remat
10632         && ( OP_SYMBOL(left)->liveTo > ic->seq
10633             || ic->depth )) {
10634 //        int size = AOP_SIZE(result) - 1;
10635 //        while (size--)
10636 //          pic16_emitcode("dec","%s",rname);
10637         }
10638     }
10639
10640     /* done */
10641     pic16_freeAsmop(left,NULL,ic,TRUE);
10642     pic16_freeAsmop(result,NULL,ic,TRUE);
10643 }
10644
10645 /*-----------------------------------------------------------------*/
10646 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10647 /*-----------------------------------------------------------------*/
10648 static void genPagedPointerGet (operand *left, 
10649                                operand *result, 
10650                                iCode *ic)
10651 {
10652     asmop *aop = NULL;
10653     regs *preg = NULL ;
10654     char *rname ;
10655     sym_link *rtype, *retype;    
10656
10657     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10658
10659     rtype = operandType(result);
10660     retype= getSpec(rtype);
10661     
10662     pic16_aopOp(left,ic,FALSE);
10663
10664   /* if the value is already in a pointer register
10665        then don't need anything more */
10666     if (!AOP_INPREG(AOP(left))) {
10667         /* otherwise get a free pointer register */
10668         aop = newAsmop(0);
10669         preg = getFreePtr(ic,&aop,FALSE);
10670         pic16_emitcode("mov","%s,%s",
10671                 preg->name,
10672                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10673         rname = preg->name ;
10674     } else
10675         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10676     
10677     pic16_freeAsmop(left,NULL,ic,TRUE);
10678     pic16_aopOp (result,ic,FALSE);
10679
10680     /* if bitfield then unpack the bits */
10681     if (IS_BITFIELD(retype)) 
10682         genUnpackBits (result,left,rname,PPOINTER);
10683     else {
10684         /* we have can just get the values */
10685         int size = AOP_SIZE(result);
10686         int offset = 0 ;        
10687         
10688         while (size--) {
10689             
10690             pic16_emitcode("movx","a,@%s",rname);
10691             pic16_aopPut(AOP(result),"a",offset);
10692             
10693             offset++ ;
10694             
10695             if (size)
10696                 pic16_emitcode("inc","%s",rname);
10697         }
10698     }
10699
10700     /* now some housekeeping stuff */
10701     if (aop) {
10702         /* we had to allocate for this iCode */
10703         pic16_freeAsmop(NULL,aop,ic,TRUE);
10704     } else { 
10705         /* we did not allocate which means left
10706            already in a pointer register, then
10707            if size > 0 && this could be used again
10708            we have to point it back to where it 
10709            belongs */
10710         if (AOP_SIZE(result) > 1 &&
10711             !OP_SYMBOL(left)->remat &&
10712             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10713               ic->depth )) {
10714             int size = AOP_SIZE(result) - 1;
10715             while (size--)
10716                 pic16_emitcode("dec","%s",rname);
10717         }
10718     }
10719
10720     /* done */
10721     pic16_freeAsmop(result,NULL,ic,TRUE);
10722     
10723         
10724 }
10725
10726 /*-----------------------------------------------------------------*/
10727 /* genFarPointerGet - gget value from far space                    */
10728 /*-----------------------------------------------------------------*/
10729 static void genFarPointerGet (operand *left,
10730                               operand *result, iCode *ic)
10731 {
10732     int size, offset ;
10733     sym_link *retype = getSpec(operandType(result));
10734
10735     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10736
10737     pic16_aopOp(left,ic,FALSE);
10738
10739     /* if the operand is already in dptr 
10740     then we do nothing else we move the value to dptr */
10741     if (AOP_TYPE(left) != AOP_STR) {
10742         /* if this is remateriazable */
10743         if (AOP_TYPE(left) == AOP_IMMD)
10744             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10745         else { /* we need to get it byte by byte */
10746             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10747             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10748             if (options.model == MODEL_FLAT24)
10749             {
10750                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10751             }
10752         }
10753     }
10754     /* so dptr know contains the address */
10755     pic16_freeAsmop(left,NULL,ic,TRUE);
10756     pic16_aopOp(result,ic,FALSE);
10757
10758     /* if bit then unpack */
10759     if (IS_BITFIELD(retype)) 
10760         genUnpackBits(result,left,"dptr",FPOINTER);
10761     else {
10762         size = AOP_SIZE(result);
10763         offset = 0 ;
10764
10765         while (size--) {
10766             pic16_emitcode("movx","a,@dptr");
10767             pic16_aopPut(AOP(result),"a",offset++);
10768             if (size)
10769                 pic16_emitcode("inc","dptr");
10770         }
10771     }
10772
10773     pic16_freeAsmop(result,NULL,ic,TRUE);
10774 }
10775 #if 0
10776 /*-----------------------------------------------------------------*/
10777 /* genCodePointerGet - get value from code space                  */
10778 /*-----------------------------------------------------------------*/
10779 static void genCodePointerGet (operand *left,
10780                                 operand *result, iCode *ic)
10781 {
10782     int size, offset ;
10783     sym_link *retype = getSpec(operandType(result));
10784
10785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10786
10787     pic16_aopOp(left,ic,FALSE);
10788
10789     /* if the operand is already in dptr 
10790     then we do nothing else we move the value to dptr */
10791     if (AOP_TYPE(left) != AOP_STR) {
10792         /* if this is remateriazable */
10793         if (AOP_TYPE(left) == AOP_IMMD)
10794             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10795         else { /* we need to get it byte by byte */
10796             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10797             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10798             if (options.model == MODEL_FLAT24)
10799             {
10800                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10801             }
10802         }
10803     }
10804     /* so dptr know contains the address */
10805     pic16_freeAsmop(left,NULL,ic,TRUE);
10806     pic16_aopOp(result,ic,FALSE);
10807
10808     /* if bit then unpack */
10809     if (IS_BITFIELD(retype)) 
10810         genUnpackBits(result,left,"dptr",CPOINTER);
10811     else {
10812         size = AOP_SIZE(result);
10813         offset = 0 ;
10814
10815         while (size--) {
10816             pic16_emitcode("clr","a");
10817             pic16_emitcode("movc","a,@a+dptr");
10818             pic16_aopPut(AOP(result),"a",offset++);
10819             if (size)
10820                 pic16_emitcode("inc","dptr");
10821         }
10822     }
10823
10824     pic16_freeAsmop(result,NULL,ic,TRUE);
10825 }
10826 #endif
10827 #if 0
10828 /*-----------------------------------------------------------------*/
10829 /* genGenPointerGet - gget value from generic pointer space        */
10830 /*-----------------------------------------------------------------*/
10831 static void genGenPointerGet (operand *left,
10832                               operand *result, iCode *ic)
10833 {
10834   int size, offset, lit;
10835   sym_link *retype = getSpec(operandType(result));
10836
10837         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10838         pic16_aopOp(left,ic,FALSE);
10839         pic16_aopOp(result,ic,FALSE);
10840         size = AOP_SIZE(result);
10841
10842         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10843
10844         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10845
10846                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10847                 // load FSR0 from immediate
10848                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10849
10850 //              pic16_loadFSR0( left );
10851
10852                 offset = 0;
10853                 while(size--) {
10854                         if(size) {
10855                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10856                         } else {
10857                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10858                         }
10859                         offset++;
10860                 }
10861                 goto release;
10862
10863         }
10864         else { /* we need to get it byte by byte */
10865                 // set up FSR0 with address from left
10866                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10867                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10868
10869                 offset = 0 ;
10870
10871                 while(size--) {
10872                         if(size) {
10873                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10874                         } else {
10875                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10876                         }
10877                         offset++;
10878                 }
10879                 goto release;
10880         }
10881
10882   /* if bit then unpack */
10883         if (IS_BITFIELD(retype)) 
10884                 genUnpackBits(result,left,"BAD",GPOINTER);
10885
10886         release:
10887         pic16_freeAsmop(left,NULL,ic,TRUE);
10888         pic16_freeAsmop(result,NULL,ic,TRUE);
10889
10890 }
10891 #endif
10892
10893
10894 /*-----------------------------------------------------------------*/
10895 /* genGenPointerGet - gget value from generic pointer space        */
10896 /*-----------------------------------------------------------------*/
10897 static void genGenPointerGet (operand *left,
10898                               operand *result, iCode *ic)
10899 {
10900   int size, offset, lit;
10901   sym_link *retype = getSpec(operandType(result));
10902   char fgptrget[32];
10903
10904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10905     pic16_aopOp(left,ic,FALSE);
10906     pic16_aopOp(result,ic,FALSE);
10907     size = AOP_SIZE(result);
10908
10909     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10910
10911     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10912
10913       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10914       // load FSR0 from immediate
10915       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10916
10917       werror(W_POSSBUG2, __FILE__, __LINE__);
10918
10919       offset = 0;
10920       while(size--) {
10921         if(size) {
10922           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10923         } else {
10924           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10925         }
10926         offset++;
10927       }
10928
10929       goto release;
10930
10931     } else { /* we need to get it byte by byte */
10932
10933       /* set up WREG:PRODL:FSR0L with address from left */
10934       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10935       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10936       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10937       
10938       switch( size ) {
10939         case 1: strcpy(fgptrget, "__gptrget1"); break;
10940         case 2: strcpy(fgptrget, "__gptrget2"); break;
10941         case 3: strcpy(fgptrget, "__gptrget3"); break;
10942         case 4: strcpy(fgptrget, "__gptrget4"); break;
10943         default:
10944           werror(W_POSSBUG2, __FILE__, __LINE__);
10945           abort();
10946       }
10947       
10948       pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10949       
10950       assignResultValue(result, 1);
10951       
10952       {
10953         symbol *sym;
10954
10955           sym = newSymbol( fgptrget, 0 );
10956           strcpy(sym->rname, fgptrget);
10957           checkAddSym(&externs, sym);
10958
10959 //          fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10960       }
10961               
10962       goto release;
10963     }
10964
10965   /* if bit then unpack */
10966     if (IS_BITFIELD(retype)) 
10967       genUnpackBits(result,left,"BAD",GPOINTER);
10968
10969 release:
10970   pic16_freeAsmop(left,NULL,ic,TRUE);
10971   pic16_freeAsmop(result,NULL,ic,TRUE);
10972 }
10973
10974 /*-----------------------------------------------------------------*/
10975 /* genConstPointerGet - get value from const generic pointer space */
10976 /*-----------------------------------------------------------------*/
10977 static void genConstPointerGet (operand *left,
10978                                 operand *result, iCode *ic)
10979 {
10980   //sym_link *retype = getSpec(operandType(result));
10981   // symbol *albl = newiTempLabel(NULL);        // patch 15
10982   // symbol *blbl = newiTempLabel(NULL);        //
10983   // PIC_OPCODE poc;                            // patch 15
10984   int size;
10985   int offset = 0;
10986
10987   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10988   pic16_aopOp(left,ic,FALSE);
10989   pic16_aopOp(result,ic,TRUE);
10990   size = AOP_SIZE(result);
10991
10992   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10993
10994   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
10995 #if 0                                                                   // patch 15
10996   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
10997   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
10998   pic16_emitpLabel(albl->key);
10999
11000   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11001   
11002   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11003   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11004   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11005   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11006   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11007
11008   pic16_emitpLabel(blbl->key);
11009
11010   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11011 #endif                                                                  // patch 15
11012
11013
11014   // set up table pointer
11015   if( (AOP_TYPE(left) == AOP_PCODE) 
11016       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11017           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
11018     {
11019       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11020       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11021       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11022       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11023       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11024       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11025     }
11026   else
11027     {
11028       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11029       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11030       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11031     }
11032
11033
11034   while(size--)
11035     {
11036       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11037       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11038       offset++;
11039     }
11040     
11041   pic16_freeAsmop(left,NULL,ic,TRUE);
11042   pic16_freeAsmop(result,NULL,ic,TRUE);
11043
11044 }
11045
11046
11047 /*-----------------------------------------------------------------*/
11048 /* genPointerGet - generate code for pointer get                   */
11049 /*-----------------------------------------------------------------*/
11050 static void genPointerGet (iCode *ic)
11051 {
11052     operand *left, *result ;
11053     sym_link *type, *etype;
11054     int p_type;
11055
11056     FENTRY;
11057     
11058     left = IC_LEFT(ic);
11059     result = IC_RESULT(ic) ;
11060
11061     /* depending on the type of pointer we need to
11062     move it to the correct pointer register */
11063     type = operandType(left);
11064     etype = getSpec(type);
11065
11066 #if 0
11067     if (IS_PTR_CONST(type))
11068 #else
11069     if (IS_CODEPTR(type))
11070 #endif
11071       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11072
11073     /* if left is of type of pointer then it is simple */
11074     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11075         p_type = DCL_TYPE(type);
11076     else {
11077         /* we have to go by the storage class */
11078         p_type = PTR_TYPE(SPEC_OCLS(etype));
11079
11080         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11081
11082         if (SPEC_OCLS(etype)->codesp ) {
11083           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11084           //p_type = CPOINTER ; 
11085         }
11086         else
11087             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11088               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11089                /*p_type = FPOINTER ;*/ 
11090             else
11091                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11092                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11093 /*                  p_type = PPOINTER; */
11094                 else
11095                     if (SPEC_OCLS(etype) == idata )
11096                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11097 /*                      p_type = IPOINTER; */
11098                     else
11099                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11100 /*                      p_type = POINTER ; */
11101     }
11102
11103     /* now that we have the pointer type we assign
11104     the pointer values */
11105     switch (p_type) {
11106
11107     case POINTER:       
11108     case IPOINTER:
11109         genNearPointerGet (left,result,ic);
11110         break;
11111
11112     case PPOINTER:
11113         genPagedPointerGet(left,result,ic);
11114         break;
11115
11116     case FPOINTER:
11117         genFarPointerGet (left,result,ic);
11118         break;
11119
11120     case CPOINTER:
11121         genConstPointerGet (left,result,ic);
11122         //pic16_emitcodePointerGet (left,result,ic);
11123         break;
11124
11125     case GPOINTER:
11126 #if 0
11127       if (IS_PTR_CONST(type))
11128         genConstPointerGet (left,result,ic);
11129       else
11130 #endif
11131         genGenPointerGet (left,result,ic);
11132       break;
11133
11134     default:
11135       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11136               "genPointerGet: illegal pointer type");
11137     
11138     }
11139
11140 }
11141
11142 /*-----------------------------------------------------------------*/
11143 /* genPackBits - generates code for packed bit storage             */
11144 /*-----------------------------------------------------------------*/
11145 static void genPackBits (sym_link    *etype , operand *result,
11146                          operand *right ,
11147                          char *rname, int p_type)
11148 {
11149   int shCnt = 0 ;
11150   int offset = 0  ;
11151   int rLen = 0 ;
11152   int blen, bstr ;   
11153   sym_link *retype;
11154   char *l ;
11155
11156         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11157         blen = SPEC_BLEN(etype);
11158         bstr = SPEC_BSTR(etype);
11159
11160         retype = getSpec(operandType(right));
11161
11162         if(AOP_TYPE(right) == AOP_LIT) {
11163                 if((blen == 1) && (bstr < 8)) {
11164                   unsigned long lit;
11165                         /* it is a single bit, so use the appropriate bit instructions */
11166
11167                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11168
11169                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11170 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11171                         if((p_type == POINTER) && (result)) {
11172                                 /* workaround to reduce the extra lfsr instruction */
11173                                 if(lit) {
11174                                         pic16_emitpcode(POC_BSF,
11175                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11176                                 } else {
11177                                         pic16_emitpcode(POC_BCF,
11178                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11179                                 }
11180                         } else {
11181                                 pic16_loadFSR0( result );
11182                                 if(lit) {
11183                                         pic16_emitpcode(POC_BSF,
11184                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11185                                 } else {
11186                                         pic16_emitpcode(POC_BCF,
11187                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11188                                 }
11189                         }
11190         
11191                   return;
11192                 }
11193
11194                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11195                 offset++;
11196         } else
11197         if(IS_BITFIELD(retype) 
11198           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11199           && (blen == 1)) {
11200           int rblen, rbstr;
11201
11202             rblen = SPEC_BLEN( retype );
11203             rbstr = SPEC_BSTR( retype );
11204             
11205
11206             if(IS_BITFIELD(etype)) {
11207               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11208               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11209             } else {
11210               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11211             }
11212             
11213             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11214             
11215             if(IS_BITFIELD(etype)) {
11216               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11217             } else {
11218               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11219             }
11220
11221             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11222             
11223             return;
11224         } else
11225           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11226
11227         /* if the bit lenth is less than or    */
11228         /* it exactly fits a byte then         */
11229         if((shCnt=SPEC_BSTR(etype))
11230                 || SPEC_BLEN(etype) <= 8 )  {
11231
11232                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11233
11234                 /* shift left acc */
11235                 AccLsh(shCnt);
11236
11237                 /* using PRODL as a temporary register here */
11238                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11239
11240                 switch (p_type) {
11241                         case FPOINTER:
11242                         case POINTER:
11243                                 pic16_loadFSR0( result );
11244                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11245 //                              pic16_emitcode ("mov","b,a");
11246 //                              pic16_emitcode("mov","a,@%s",rname);
11247                                 break;
11248
11249                         case GPOINTER:
11250                                 werror(W_POSSBUG2, __FILE__, __LINE__);
11251                                 break;
11252
11253                 }
11254 #if 1
11255                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11256                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11257                                         (unsigned char)(0xff >> (8-bstr))) ));
11258                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11259                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11260 #endif
11261
11262           return;
11263         }
11264
11265
11266         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11267         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11268         exit(-1);
11269
11270
11271     /* if we r done */
11272     if ( SPEC_BLEN(etype) <= 8 )
11273         return ;
11274
11275     pic16_emitcode("inc","%s",rname);
11276     rLen = SPEC_BLEN(etype) ;     
11277
11278
11279
11280     /* now generate for lengths greater than one byte */
11281     while (1) {
11282
11283         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11284
11285         rLen -= 8 ;
11286         if (rLen <= 0 )
11287             break ;
11288
11289         switch (p_type) {
11290             case POINTER:
11291                 if (*l == '@') {
11292                     MOVA(l);
11293                     pic16_emitcode("mov","@%s,a",rname);
11294                 } else
11295                     pic16_emitcode("mov","@%s,%s",rname,l);
11296                 break;
11297
11298             case FPOINTER:
11299                 MOVA(l);
11300                 pic16_emitcode("movx","@dptr,a");
11301                 break;
11302
11303             case GPOINTER:
11304                 MOVA(l);
11305                 DEBUGpic16_emitcode(";lcall","__gptrput");
11306                 break;  
11307         }   
11308         pic16_emitcode ("inc","%s",rname);
11309     }
11310
11311     MOVA(l);
11312
11313     /* last last was not complete */
11314     if (rLen)   {
11315         /* save the byte & read byte */
11316         switch (p_type) {
11317             case POINTER:
11318                 pic16_emitcode ("mov","b,a");
11319                 pic16_emitcode("mov","a,@%s",rname);
11320                 break;
11321
11322             case FPOINTER:
11323                 pic16_emitcode ("mov","b,a");
11324                 pic16_emitcode("movx","a,@dptr");
11325                 break;
11326
11327             case GPOINTER:
11328                 pic16_emitcode ("push","b");
11329                 pic16_emitcode ("push","acc");
11330                 pic16_emitcode ("lcall","__gptrget");
11331                 pic16_emitcode ("pop","b");
11332                 break;
11333         }
11334
11335         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11336         pic16_emitcode ("orl","a,b");
11337     }
11338
11339     if (p_type == GPOINTER)
11340         pic16_emitcode("pop","b");
11341
11342     switch (p_type) {
11343
11344     case POINTER:
11345         pic16_emitcode("mov","@%s,a",rname);
11346         break;
11347         
11348     case FPOINTER:
11349         pic16_emitcode("movx","@dptr,a");
11350         break;
11351         
11352     case GPOINTER:
11353         DEBUGpic16_emitcode(";lcall","__gptrput");
11354         break;                  
11355     }
11356 }
11357 /*-----------------------------------------------------------------*/
11358 /* genDataPointerSet - remat pointer to data space                 */
11359 /*-----------------------------------------------------------------*/
11360 static void genDataPointerSet(operand *right,
11361                               operand *result,
11362                               iCode *ic)
11363 {
11364     int size, offset = 0, resoffset=0 ;
11365
11366     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11367     pic16_aopOp(right,ic,FALSE);
11368
11369     size = AOP_SIZE(right);
11370
11371 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11372
11373 #if 0
11374     if ( AOP_TYPE(result) == AOP_PCODE) {
11375       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11376               AOP(result)->aopu.pcop->name,
11377                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11378               PCOR(AOP(result)->aopu.pcop)->instance:
11379               PCOI(AOP(result)->aopu.pcop)->offset);
11380     }
11381 #endif
11382
11383         if(AOP(result)->aopu.pcop->type == PO_DIR)
11384                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11385
11386         while (size--) {
11387                 if (AOP_TYPE(right) == AOP_LIT) {
11388                   unsigned int lit;
11389
11390                     if(!IS_FLOAT(operandType( right )))
11391                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11392                     else {
11393                       union {
11394                         unsigned long lit_int;
11395                         float lit_float;
11396                       } info;
11397         
11398                         /* take care if literal is a float */
11399                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11400                         lit = info.lit_int;
11401                     }
11402
11403                     lit = lit >> (8*offset);
11404                     if(lit&0xff) {
11405                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11406                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11407                     } else {
11408                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11409                     }
11410                 } else {
11411                   mov2w(AOP(right), offset);
11412                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11413                 }
11414                 offset++;
11415                 resoffset++;
11416         }
11417
11418     pic16_freeAsmop(right,NULL,ic,TRUE);
11419 }
11420
11421
11422
11423 /*-----------------------------------------------------------------*/
11424 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11425 /*-----------------------------------------------------------------*/
11426 static void genNearPointerSet (operand *right,
11427                                operand *result, 
11428                                iCode *ic)
11429 {
11430   asmop *aop = NULL;
11431   char *l;
11432   sym_link *retype;
11433   sym_link *ptype = operandType(result);
11434   sym_link *resetype;
11435     
11436         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11437         retype= getSpec(operandType(right));
11438         resetype = getSpec(operandType(result));
11439   
11440         pic16_aopOp(result,ic,FALSE);
11441     
11442         /* if the result is rematerializable &
11443          * in data space & not a bit variable */
11444         
11445         /* and result is not a bit variable */
11446         if (AOP_TYPE(result) == AOP_PCODE
11447 //              && AOP_TYPE(result) == AOP_IMMD
11448                 && DCL_TYPE(ptype) == POINTER
11449                 && !IS_BITFIELD(retype)
11450                 && !IS_BITFIELD(resetype)) {
11451
11452                 genDataPointerSet (right,result,ic);
11453                 pic16_freeAsmop(result,NULL,ic,TRUE);
11454           return;
11455         }
11456
11457         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11458         pic16_aopOp(right,ic,FALSE);
11459         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11460
11461         /* if the value is already in a pointer register
11462          * then don't need anything more */
11463         if (!AOP_INPREG(AOP(result))) {
11464                 /* otherwise get a free pointer register */
11465                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11466
11467 //              if( (AOP_TYPE(result) == AOP_PCODE) 
11468 //                      && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11469 //                              || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11470                 if(is_LitAOp( AOP(result) ))
11471                 {
11472                   if(!IS_BITFIELD(resetype))
11473                         pic16_loadFSR0( result );  // patch 10
11474                 } else {
11475                   if(!IS_BITFIELD(resetype)) {
11476                         // set up FSR0 with address of result
11477                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11478                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11479                   }
11480                 }
11481
11482         }
11483 //      else
11484 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11485
11486         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11487
11488 //      pic16_loadFSR0( result );
11489
11490         /* if bitfield then unpack the bits */
11491         if (IS_BITFIELD(resetype)) {
11492                 genPackBits (resetype, result, right, NULL, POINTER);
11493         } else {
11494                 /* we have can just get the values */
11495           int size = AOP_SIZE(right);
11496           int offset = 0 ;    
11497
11498                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11499                 while (size--) {
11500                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11501                         if (*l == '@' ) {
11502                                 //MOVA(l);
11503                                 //pic16_emitcode("mov","@%s,a",rname);
11504                                 pic16_emitcode("movf","indf0,w ;1");
11505                         } else {
11506
11507                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
11508                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
11509                                         if (size) {                                                                     // 
11510                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
11511                                         } else {                                                                        // 
11512                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
11513                                         }                                                                               // 
11514                                 } else { // no literal                                                                  // 
11515                                         if(size) {                                                                      // 
11516                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11517                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11518                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
11519                                         } else {                                                                        // 
11520                                                 pic16_emitpcode(POC_MOVFF,                                              // 
11521                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
11522                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
11523                                         }                                                                               //
11524                                 }                                                                                       // patch 10
11525                         }
11526                         offset++;
11527                 }
11528         }
11529
11530         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11531         /* now some housekeeping stuff */
11532         if (aop) {
11533                 /* we had to allocate for this iCode */
11534                 pic16_freeAsmop(NULL,aop,ic,TRUE);
11535         } else { 
11536                 /* we did not allocate which means left
11537                  * already in a pointer register, then
11538                  * if size > 0 && this could be used again
11539                  * we have to point it back to where it 
11540                  * belongs */
11541                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11542                 if (AOP_SIZE(right) > 1
11543                         && !OP_SYMBOL(result)->remat
11544                         && ( OP_SYMBOL(result)->liveTo > ic->seq
11545                                 || ic->depth )) {
11546
11547                   int size = AOP_SIZE(right) - 1;
11548
11549                         while (size--)
11550                                 pic16_emitcode("decf","fsr0,f");
11551                         //pic16_emitcode("dec","%s",rname);
11552                 }
11553         }
11554
11555         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11556         /* done */
11557 //release:
11558         pic16_freeAsmop(right,NULL,ic,TRUE);
11559         pic16_freeAsmop(result,NULL,ic,TRUE);
11560 }
11561
11562 /*-----------------------------------------------------------------*/
11563 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11564 /*-----------------------------------------------------------------*/
11565 static void genPagedPointerSet (operand *right,
11566                                operand *result, 
11567                                iCode *ic)
11568 {
11569     asmop *aop = NULL;
11570     regs *preg = NULL ;
11571     char *rname , *l;
11572     sym_link *retype;
11573        
11574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11575
11576     retype= getSpec(operandType(right));
11577     
11578     pic16_aopOp(result,ic,FALSE);
11579     
11580     /* if the value is already in a pointer register
11581        then don't need anything more */
11582     if (!AOP_INPREG(AOP(result))) {
11583         /* otherwise get a free pointer register */
11584         aop = newAsmop(0);
11585         preg = getFreePtr(ic,&aop,FALSE);
11586         pic16_emitcode("mov","%s,%s",
11587                 preg->name,
11588                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11589         rname = preg->name ;
11590     } else
11591         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11592     
11593     pic16_freeAsmop(result,NULL,ic,TRUE);
11594     pic16_aopOp (right,ic,FALSE);
11595
11596     /* if bitfield then unpack the bits */
11597     if (IS_BITFIELD(retype)) 
11598         genPackBits (retype,result,right,rname,PPOINTER);
11599     else {
11600         /* we have can just get the values */
11601         int size = AOP_SIZE(right);
11602         int offset = 0 ;        
11603         
11604         while (size--) {
11605             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11606             
11607             MOVA(l);
11608             pic16_emitcode("movx","@%s,a",rname);
11609
11610             if (size)
11611                 pic16_emitcode("inc","%s",rname);
11612
11613             offset++;
11614         }
11615     }
11616     
11617     /* now some housekeeping stuff */
11618     if (aop) {
11619         /* we had to allocate for this iCode */
11620         pic16_freeAsmop(NULL,aop,ic,TRUE);
11621     } else { 
11622         /* we did not allocate which means left
11623            already in a pointer register, then
11624            if size > 0 && this could be used again
11625            we have to point it back to where it 
11626            belongs */
11627         if (AOP_SIZE(right) > 1 &&
11628             !OP_SYMBOL(result)->remat &&
11629             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11630               ic->depth )) {
11631             int size = AOP_SIZE(right) - 1;
11632             while (size--)
11633                 pic16_emitcode("dec","%s",rname);
11634         }
11635     }
11636
11637     /* done */
11638     pic16_freeAsmop(right,NULL,ic,TRUE);
11639     
11640         
11641 }
11642
11643 /*-----------------------------------------------------------------*/
11644 /* genFarPointerSet - set value from far space                     */
11645 /*-----------------------------------------------------------------*/
11646 static void genFarPointerSet (operand *right,
11647                               operand *result, iCode *ic)
11648 {
11649     int size, offset ;
11650     sym_link *retype = getSpec(operandType(right));
11651
11652     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11653     pic16_aopOp(result,ic,FALSE);
11654
11655     /* if the operand is already in dptr 
11656     then we do nothing else we move the value to dptr */
11657     if (AOP_TYPE(result) != AOP_STR) {
11658         /* if this is remateriazable */
11659         if (AOP_TYPE(result) == AOP_IMMD)
11660             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11661         else { /* we need to get it byte by byte */
11662             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11663             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11664             if (options.model == MODEL_FLAT24)
11665             {
11666                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11667             }
11668         }
11669     }
11670     /* so dptr know contains the address */
11671     pic16_freeAsmop(result,NULL,ic,TRUE);
11672     pic16_aopOp(right,ic,FALSE);
11673
11674     /* if bit then unpack */
11675     if (IS_BITFIELD(retype)) 
11676         genPackBits(retype,result,right,"dptr",FPOINTER);
11677     else {
11678         size = AOP_SIZE(right);
11679         offset = 0 ;
11680
11681         while (size--) {
11682             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11683             MOVA(l);
11684             pic16_emitcode("movx","@dptr,a");
11685             if (size)
11686                 pic16_emitcode("inc","dptr");
11687         }
11688     }
11689
11690     pic16_freeAsmop(right,NULL,ic,TRUE);
11691 }
11692
11693 /*-----------------------------------------------------------------*/
11694 /* genGenPointerSet - set value from generic pointer space         */
11695 /*-----------------------------------------------------------------*/
11696 #if 0
11697 static void genGenPointerSet (operand *right,
11698                               operand *result, iCode *ic)
11699 {
11700         int i, size, offset, lit;
11701         sym_link *retype = getSpec(operandType(right));
11702
11703         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11704
11705         pic16_aopOp(result,ic,FALSE);
11706         pic16_aopOp(right,ic,FALSE);
11707         size = AOP_SIZE(right);
11708         offset = 0;
11709
11710         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11711
11712         /* if the operand is already in dptr 
11713                 then we do nothing else we move the value to dptr */
11714         if (AOP_TYPE(result) != AOP_STR) {
11715                 /* if this is remateriazable */
11716                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11717                 // WARNING: anythig until "else" is untested!
11718                 if (AOP_TYPE(result) == AOP_IMMD) {
11719                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11720                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11721                         // load FSR0 from immediate
11722                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11723                         offset = 0;
11724                         while(size--) {
11725                                 if(size) {
11726                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11727                                 } else {
11728                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11729                                 }
11730                                 offset++;
11731                         }
11732                         goto release;
11733                 }
11734                 else { /* we need to get it byte by byte */
11735                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11736                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11737
11738                         // set up FSR0 with address of result
11739                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11740                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11741
11742                         /* hack hack! see if this the FSR. If so don't load W */
11743                         if(AOP_TYPE(right) != AOP_ACC) {
11744
11745                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11746
11747                                 if(AOP_TYPE(right) == AOP_LIT)
11748                                 {
11749                                         // copy literal
11750                                         // note: pic16_popGet handles sign extension
11751                                         for(i=0;i<size;i++) {
11752                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11753                                                 if(i < size-1)
11754                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11755                                                 else
11756                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11757                                         }
11758                                 } else {
11759                                         // copy regs
11760
11761                                         for(i=0;i<size;i++) {
11762                                                 if(i < size-1)
11763                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11764                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11765                                                 else
11766                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11767                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11768                                         }
11769                                 }
11770                                 goto release;
11771                         } 
11772                         // right = ACC
11773                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11774                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11775                         goto release;
11776         } // if (AOP_TYPE(result) != AOP_IMMD)
11777
11778         } // if (AOP_TYPE(result) != AOP_STR)
11779         /* so dptr know contains the address */
11780
11781
11782         /* if bit then unpack */
11783         if (IS_BITFIELD(retype)) 
11784                 genPackBits(retype,result,right,"dptr",GPOINTER);
11785         else {
11786                 size = AOP_SIZE(right);
11787                 offset = 0 ;
11788
11789                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11790
11791                 // set up FSR0 with address of result
11792                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11793                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11794         
11795                 while (size--) {
11796                         if (AOP_TYPE(right) == AOP_LIT) {
11797                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11798                                 if (size) {
11799                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11800                                 } else {
11801                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11802                                 }
11803                         } else { // no literal
11804                                 if(size) {
11805                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11806                                 } else {
11807                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11808                                 }
11809                         }
11810                         offset++;
11811                 }
11812         }
11813
11814         release:
11815         pic16_freeAsmop(right,NULL,ic,TRUE);
11816         pic16_freeAsmop(result,NULL,ic,TRUE);
11817 }
11818 #endif
11819
11820 static void genGenPointerSet (operand *right,
11821                               operand *result, iCode *ic)
11822 {
11823   int size;
11824   sym_link *retype = getSpec(operandType(right));
11825   char fgptrput[32];
11826
11827     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11828
11829     pic16_aopOp(result,ic,FALSE);
11830     pic16_aopOp(right,ic,FALSE);
11831     size = AOP_SIZE(right);
11832
11833     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11834
11835
11836     /* if bit then unpack */
11837     if (IS_BITFIELD(retype)) {
11838 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11839       genPackBits(retype,result,right,"dptr",GPOINTER);
11840       goto release;
11841     }
11842
11843     size = AOP_SIZE(right);
11844
11845     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11846
11847
11848
11849     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11850
11851     /* value of right+0 is placed on stack, which will be retrieved
11852      * by the support function this restoring the stack. The important
11853      * thing is that there is no need to manually restore stack pointer
11854      * here */
11855     pushaop(AOP(right), 0);
11856 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11857     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11858     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11859     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11860     
11861     /* load address to write to in WREG:FSR0H:FSR0L */
11862     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11863                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11864     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11865                                 pic16_popCopyReg(&pic16_pc_prodl)));
11866     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11867     
11868
11869     /* put code here */
11870     switch (size) {
11871       case 1: strcpy(fgptrput, "__gptrput1"); break;
11872       case 2: strcpy(fgptrput, "__gptrput2"); break;
11873       case 3: strcpy(fgptrput, "__gptrput3"); break;
11874       case 4: strcpy(fgptrput, "__gptrput4"); break;
11875       default:
11876         werror(W_POSSBUG2, __FILE__, __LINE__);
11877         abort();
11878     }
11879     
11880     pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11881     
11882     {
11883       symbol *sym;
11884                   
11885         sym = newSymbol( fgptrput, 0 );
11886         strcpy(sym->rname, fgptrput);
11887         checkAddSym(&externs, sym);
11888     }
11889
11890 release:
11891     pic16_freeAsmop(right,NULL,ic,TRUE);
11892     pic16_freeAsmop(result,NULL,ic,TRUE);
11893 }
11894
11895 /*-----------------------------------------------------------------*/
11896 /* genPointerSet - stores the value into a pointer location        */
11897 /*-----------------------------------------------------------------*/
11898 static void genPointerSet (iCode *ic)
11899 {    
11900   operand *right, *result ;
11901   sym_link *type, *etype;
11902   int p_type;
11903
11904     FENTRY;
11905
11906     right = IC_RIGHT(ic);
11907     result = IC_RESULT(ic) ;
11908
11909     /* depending on the type of pointer we need to
11910     move it to the correct pointer register */
11911     type = operandType(result);
11912     etype = getSpec(type);
11913     /* if left is of type of pointer then it is simple */
11914     if (IS_PTR(type) && !IS_FUNC(type->next)) {
11915         p_type = DCL_TYPE(type);
11916     }
11917     else {
11918         /* we have to go by the storage class */
11919         p_type = PTR_TYPE(SPEC_OCLS(etype));
11920
11921 /*      if (SPEC_OCLS(etype)->codesp ) { */
11922 /*          p_type = CPOINTER ;  */
11923 /*      } */
11924 /*      else */
11925 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11926 /*              p_type = FPOINTER ; */
11927 /*          else */
11928 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11929 /*                  p_type = PPOINTER ; */
11930 /*              else */
11931 /*                  if (SPEC_OCLS(etype) == idata ) */
11932 /*                      p_type = IPOINTER ; */
11933 /*                  else */
11934 /*                      p_type = POINTER ; */
11935     }
11936
11937     /* now that we have the pointer type we assign
11938     the pointer values */
11939     switch (p_type) {
11940
11941     case POINTER:
11942     case IPOINTER:
11943         genNearPointerSet (right,result,ic);
11944         break;
11945
11946     case PPOINTER:
11947         genPagedPointerSet (right,result,ic);
11948         break;
11949
11950     case FPOINTER:
11951         genFarPointerSet (right,result,ic);
11952         break;
11953
11954     case GPOINTER:
11955         genGenPointerSet (right,result,ic);
11956         break;
11957
11958     default:
11959       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11960               "genPointerSet: illegal pointer type");
11961     }
11962 }
11963
11964 /*-----------------------------------------------------------------*/
11965 /* genIfx - generate code for Ifx statement                        */
11966 /*-----------------------------------------------------------------*/
11967 static void genIfx (iCode *ic, iCode *popIc)
11968 {
11969   operand *cond = IC_COND(ic);
11970   int isbit =0;
11971
11972     FENTRY;
11973
11974     pic16_aopOp(cond,ic,FALSE);
11975
11976     /* get the value into acc */
11977     if (AOP_TYPE(cond) != AOP_CRY)
11978       pic16_toBoolean(cond);
11979     else
11980       isbit = 1;
11981     /* the result is now in the accumulator */
11982     pic16_freeAsmop(cond,NULL,ic,TRUE);
11983
11984     /* if there was something to be popped then do it */
11985     if (popIc)
11986       genIpop(popIc);
11987
11988     /* if the condition is  a bit variable */
11989     if (isbit && IS_ITEMP(cond) && 
11990         SPIL_LOC(cond)) {
11991       genIfxJump(ic,SPIL_LOC(cond)->rname);
11992       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11993     } else {
11994       if (isbit && !IS_ITEMP(cond))
11995         genIfxJump(ic,OP_SYMBOL(cond)->rname);
11996         else
11997         genIfxJump(ic,"a");
11998     }
11999     ic->generated = 1;
12000 }
12001
12002 /*-----------------------------------------------------------------*/
12003 /* genAddrOf - generates code for address of                       */
12004 /*-----------------------------------------------------------------*/
12005 static void genAddrOf (iCode *ic)
12006 {
12007   operand *result, *left;
12008   int size;
12009   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12010   pCodeOp *pcop0, *pcop1, *pcop2;
12011
12012     FENTRY;
12013
12014     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12015
12016     sym = OP_SYMBOL( IC_LEFT(ic) );
12017     
12018     if(sym->onStack) {
12019       /* get address of symbol on stack */
12020       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12021 #if 0
12022       fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12023                   OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12024 #endif
12025
12026       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12027                       pic16_popCopyReg(&pic16_pc_fsr2l),
12028                       pic16_popGet(AOP(result), 0)));
12029       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12030                       pic16_popCopyReg(&pic16_pc_fsr2h),
12031                       pic16_popGet(AOP(result), 1)));
12032       
12033       pic16_emitpcode(POC_MOVLW, pic16_popGetLit( OP_SYMBOL( IC_LEFT(ic))->stack ) /*+ _G.stack_lat*/);
12034       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 0));
12035       emitSKPNC;
12036       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 1));
12037
12038       goto release;
12039     }
12040         
12041 //      if(pic16_debug_verbose) {
12042 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12043 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12044 //      }
12045         
12046     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12047     size = AOP_SIZE(IC_RESULT(ic));
12048
12049
12050     /* Assume that what we want the address of is in data space
12051      * since there is no stack on the PIC, yet! -- VR */
12052   
12053     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12054     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12055     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12056         
12057     if (size == 3) {
12058       pic16_emitpcode(POC_MOVLW, pcop0);
12059       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12060       pic16_emitpcode(POC_MOVLW, pcop1);
12061       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12062       pic16_emitpcode(POC_MOVLW, pcop2);
12063       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12064     } else
12065     if (size == 2) {
12066       pic16_emitpcode(POC_MOVLW, pcop0);
12067       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12068       pic16_emitpcode(POC_MOVLW, pcop1);
12069     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12070     } else {
12071       pic16_emitpcode(POC_MOVLW, pcop0);
12072       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12073     }
12074
12075     pic16_freeAsmop(left, NULL, ic, FALSE);
12076 release:
12077     pic16_freeAsmop(result,NULL,ic,TRUE);
12078 }
12079
12080
12081 #if 0
12082 /*-----------------------------------------------------------------*/
12083 /* genFarFarAssign - assignment when both are in far space         */
12084 /*-----------------------------------------------------------------*/
12085 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12086 {
12087     int size = AOP_SIZE(right);
12088     int offset = 0;
12089     char *l ;
12090     /* first push the right side on to the stack */
12091     while (size--) {
12092         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12093         MOVA(l);
12094         pic16_emitcode ("push","acc");
12095     }
12096     
12097     pic16_freeAsmop(right,NULL,ic,FALSE);
12098     /* now assign DPTR to result */
12099     pic16_aopOp(result,ic,FALSE);
12100     size = AOP_SIZE(result);
12101     while (size--) {
12102         pic16_emitcode ("pop","acc");
12103         pic16_aopPut(AOP(result),"a",--offset);
12104     }
12105     pic16_freeAsmop(result,NULL,ic,FALSE);
12106         
12107 }
12108 #endif
12109
12110 /*-----------------------------------------------------------------*/
12111 /* genAssign - generate code for assignment                        */
12112 /*-----------------------------------------------------------------*/
12113 static void genAssign (iCode *ic)
12114 {
12115   operand *result, *right;
12116   int size, offset,know_W;
12117   unsigned long lit = 0L;
12118
12119   result = IC_RESULT(ic);
12120   right  = IC_RIGHT(ic) ;
12121
12122   FENTRY;
12123   
12124   /* if they are the same */
12125   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12126     return ;
12127
12128   /* reversed order operands are aopOp'ed so that result operand
12129    * is effective in case right is a stack symbol. This maneauver
12130    * allows to use the _G.resDirect flag later */
12131   pic16_aopOp(result,ic,TRUE);
12132   pic16_aopOp(right,ic,FALSE);
12133
12134   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12135
12136   /* if they are the same registers */
12137   if (pic16_sameRegs(AOP(right),AOP(result)))
12138     goto release;
12139
12140   /* if the result is a bit */
12141   if (AOP_TYPE(result) == AOP_CRY) {
12142     /* if the right size is a literal then
12143        we know what the value is */
12144     if (AOP_TYPE(right) == AOP_LIT) {
12145           
12146       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12147                   pic16_popGet(AOP(result),0));
12148
12149       if (((int) operandLitValue(right))) 
12150         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12151                        AOP(result)->aopu.aop_dir,
12152                        AOP(result)->aopu.aop_dir);
12153       else
12154         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12155                        AOP(result)->aopu.aop_dir,
12156                        AOP(result)->aopu.aop_dir);
12157       goto release;
12158     }
12159
12160     /* the right is also a bit variable */
12161     if (AOP_TYPE(right) == AOP_CRY) {
12162       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12163       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12164       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12165
12166       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12167                      AOP(result)->aopu.aop_dir,
12168                      AOP(result)->aopu.aop_dir);
12169       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12170                      AOP(right)->aopu.aop_dir,
12171                      AOP(right)->aopu.aop_dir);
12172       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12173                      AOP(result)->aopu.aop_dir,
12174                      AOP(result)->aopu.aop_dir);
12175       goto release ;
12176     }
12177
12178     /* we need to or */
12179     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12180     pic16_toBoolean(right);
12181     emitSKPZ;
12182     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12183     //pic16_aopPut(AOP(result),"a",0);
12184     goto release ;
12185   }
12186
12187   /* bit variables done */
12188   /* general case */
12189   size = AOP_SIZE(result);
12190   offset = 0 ;
12191
12192   if(AOP_TYPE(right) == AOP_LIT) {
12193         if(!IS_FLOAT(operandType( right )))
12194                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12195         else {
12196            union {
12197               unsigned long lit_int;
12198               float lit_float;
12199             } info;
12200         
12201                 /* take care if literal is a float */
12202                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12203                 lit = info.lit_int;
12204         }
12205   }
12206
12207 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12208 //                      sizeof(unsigned long int), sizeof(float));
12209
12210   if(AOP_TYPE(right) != AOP_LIT
12211         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12212         && !IS_FUNC(OP_SYM_TYPE(right))
12213         ) {
12214         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12215         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12216
12217         // set up table pointer
12218         if(is_LitOp(right)) {
12219 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12220                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12221                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12222                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12223                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12224                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12225                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12226         } else {
12227 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12228                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12229                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12230                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12231                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12232                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12233                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12234         }
12235
12236         size = min(AOP_SIZE(right), AOP_SIZE(result));
12237         while(size--) {
12238                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12239                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12240                         pic16_popGet(AOP(result),offset)));
12241                 offset++;
12242         }
12243
12244         if(AOP_SIZE(result) > AOP_SIZE(right)) {
12245                 size = AOP_SIZE(result) - AOP_SIZE(right);
12246                 while(size--) {
12247                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12248                         offset++;
12249                 }
12250         }
12251         goto release;
12252   }
12253
12254
12255
12256 #if 0
12257 /* VR - What is this?! */
12258   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12259     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12260     if(aopIdx(AOP(result),0) == 4) {
12261
12262       /* this is a workaround to save value of right into wreg too,
12263        * value of wreg is going to be used later */
12264       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12265       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12266       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12267       goto release;
12268     } else
12269 //      assert(0);
12270       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12271   }
12272 #endif
12273
12274   know_W=-1;
12275   while (size--) {
12276   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12277     if(AOP_TYPE(right) == AOP_LIT) {
12278       if(lit&0xff) {
12279         if(know_W != (lit&0xff))
12280           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12281         know_W = lit&0xff;
12282         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12283       } else
12284         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12285
12286       lit >>= 8;
12287
12288     } else if (AOP_TYPE(right) == AOP_CRY) {
12289       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12290       if(offset == 0) {
12291 //        debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12292         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
12293         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12294       }
12295     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12296         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12297         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12298     } else {
12299       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12300
12301       if(!_G.resDirect)         /* use this aopForSym feature */
12302         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12303     }
12304             
12305     offset++;
12306   }
12307   
12308  release:
12309   pic16_freeAsmop (right,NULL,ic,FALSE);
12310   pic16_freeAsmop (result,NULL,ic,TRUE);
12311 }   
12312
12313 /*-----------------------------------------------------------------*/
12314 /* genJumpTab - generates code for jump table                       */
12315 /*-----------------------------------------------------------------*/
12316 static void genJumpTab (iCode *ic)
12317 {
12318   symbol *jtab;
12319   char *l;
12320   pCodeOp *jt_offs;
12321   pCodeOp *jt_offs_hi;
12322   pCodeOp *jt_label;
12323
12324     FENTRY;
12325
12326     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12327     /* get the condition into accumulator */
12328     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12329     MOVA(l);
12330     /* multiply by three */
12331     pic16_emitcode("add","a,acc");
12332     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12333
12334     jtab = newiTempLabel(NULL);
12335     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12336     pic16_emitcode("jmp","@a+dptr");
12337     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12338
12339 #if 0
12340     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12341     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12342     emitSKPNC;
12343     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12344     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12345     pic16_emitpLabel(jtab->key);
12346
12347 #else
12348
12349     jt_offs = pic16_popGetTempReg(0);
12350     jt_offs_hi = pic16_popGetTempReg(1);
12351     jt_label = pic16_popGetLabel (jtab->key);
12352     //fprintf (stderr, "Creating jump table...\n");
12353
12354     // calculate offset into jump table (idx * sizeof (GOTO))
12355     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12356     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12357     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12358     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12359     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12360     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12361     pic16_emitpcode(POC_MOVWF , jt_offs);
12362
12363     // prepare PCLATx (set to first entry in jump table)
12364     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12365     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12366     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12367     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12368     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12369
12370     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12371     pic16_emitpcode(POC_ADDWF , jt_offs);
12372     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12373     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12374     emitSKPNC;
12375     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12376
12377     // release temporaries and prepare jump into table (new PCL --> WREG)
12378     pic16_emitpcode(POC_MOVFW , jt_offs);
12379     pic16_popReleaseTempReg (jt_offs_hi, 1);
12380     pic16_popReleaseTempReg (jt_offs, 0);
12381
12382     // jump into the table
12383     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12384
12385     pic16_emitpLabelFORCE(jtab->key);
12386
12387 #endif
12388     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12389
12390     /* now generate the jump labels */
12391     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12392          jtab = setNextItem(IC_JTLABELS(ic))) {
12393 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12394         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12395         
12396     }
12397
12398 }
12399
12400 /*-----------------------------------------------------------------*/
12401 /* genMixedOperation - gen code for operators between mixed types  */
12402 /*-----------------------------------------------------------------*/
12403 /*
12404   TSD - Written for the PIC port - but this unfortunately is buggy.
12405   This routine is good in that it is able to efficiently promote 
12406   types to different (larger) sizes. Unfortunately, the temporary
12407   variables that are optimized out by this routine are sometimes
12408   used in other places. So until I know how to really parse the 
12409   iCode tree, I'm going to not be using this routine :(.
12410 */
12411 static int genMixedOperation (iCode *ic)
12412 {
12413 #if 0
12414   operand *result = IC_RESULT(ic);
12415   sym_link *ctype = operandType(IC_LEFT(ic));
12416   operand *right = IC_RIGHT(ic);
12417   int ret = 0;
12418   int big,small;
12419   int offset;
12420
12421   iCode *nextic;
12422   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12423
12424   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12425
12426   nextic = ic->next;
12427   if(!nextic)
12428     return 0;
12429
12430   nextright = IC_RIGHT(nextic);
12431   nextleft  = IC_LEFT(nextic);
12432   nextresult = IC_RESULT(nextic);
12433
12434   pic16_aopOp(right,ic,FALSE);
12435   pic16_aopOp(result,ic,FALSE);
12436   pic16_aopOp(nextright,  nextic, FALSE);
12437   pic16_aopOp(nextleft,   nextic, FALSE);
12438   pic16_aopOp(nextresult, nextic, FALSE);
12439
12440   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12441
12442     operand *t = right;
12443     right = nextright;
12444     nextright = t; 
12445
12446     pic16_emitcode(";remove right +","");
12447
12448   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12449 /*
12450     operand *t = right;
12451     right = nextleft;
12452     nextleft = t; 
12453 */
12454     pic16_emitcode(";remove left +","");
12455   } else
12456     return 0;
12457
12458   big = AOP_SIZE(nextleft);
12459   small = AOP_SIZE(nextright);
12460
12461   switch(nextic->op) {
12462
12463   case '+':
12464     pic16_emitcode(";optimize a +","");
12465     /* if unsigned or not an integral type */
12466     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12467       pic16_emitcode(";add a bit to something","");
12468     } else {
12469
12470       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12471
12472       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12473         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12474         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12475       } else
12476         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12477
12478       offset = 0;
12479       while(--big) {
12480
12481         offset++;
12482
12483         if(--small) {
12484           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12485             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12486             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12487           }
12488
12489           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12490           emitSKPNC;
12491           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12492                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12493                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12494           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12495           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12496
12497         } else {
12498           pic16_emitcode("rlf","known_zero,w");
12499
12500           /*
12501             if right is signed
12502               btfsc  right,7
12503                addlw ff
12504           */
12505           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12506             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12507             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12508           } else {
12509             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12510           }
12511         }
12512       }
12513       ret = 1;
12514     }
12515   }
12516   ret = 1;
12517
12518 release:
12519   pic16_freeAsmop(right,NULL,ic,TRUE);
12520   pic16_freeAsmop(result,NULL,ic,TRUE);
12521   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12522   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12523   if(ret)
12524     nextic->generated = 1;
12525
12526   return ret;
12527 #else
12528   return 0;
12529 #endif
12530 }
12531 /*-----------------------------------------------------------------*/
12532 /* genCast - gen code for casting                                  */
12533 /*-----------------------------------------------------------------*/
12534 static void genCast (iCode *ic)
12535 {
12536   operand *result = IC_RESULT(ic);
12537   sym_link *ctype = operandType(IC_LEFT(ic));
12538   sym_link *rtype = operandType(IC_RIGHT(ic));
12539   sym_link *restype = operandType(IC_RESULT(ic));
12540   operand *right = IC_RIGHT(ic);
12541   int size, offset ;
12542
12543
12544     FENTRY;
12545
12546         /* if they are equivalent then do nothing */
12547 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12548 //              return ;
12549
12550         pic16_aopOp(right,ic,FALSE) ;
12551         pic16_aopOp(result,ic,FALSE);
12552
12553         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12554
12555
12556         /* if the result is a bit */
12557         if (AOP_TYPE(result) == AOP_CRY) {
12558         
12559                 /* if the right size is a literal then
12560                  * we know what the value is */
12561                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12562
12563                 if (AOP_TYPE(right) == AOP_LIT) {
12564                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12565                                 pic16_popGet(AOP(result),0));
12566
12567                         if (((int) operandLitValue(right))) 
12568                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12569                                         AOP(result)->aopu.aop_dir,
12570                                         AOP(result)->aopu.aop_dir);
12571                         else
12572                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12573                                         AOP(result)->aopu.aop_dir,
12574                                         AOP(result)->aopu.aop_dir);
12575                         goto release;
12576                 }
12577
12578                 /* the right is also a bit variable */
12579                 if (AOP_TYPE(right) == AOP_CRY) {
12580                         emitCLRC;
12581                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12582
12583                         pic16_emitcode("clrc","");
12584                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12585                                 AOP(right)->aopu.aop_dir,
12586                                 AOP(right)->aopu.aop_dir);
12587                         pic16_aopPut(AOP(result),"c",0);
12588                         goto release ;
12589                 }
12590
12591                 /* we need to or */
12592                 if (AOP_TYPE(right) == AOP_REG) {
12593                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12594                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12595                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12596                 }
12597                 pic16_toBoolean(right);
12598                 pic16_aopPut(AOP(result),"a",0);
12599                 goto release ;
12600         }
12601
12602         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12603           int offset = 1;
12604
12605                 size = AOP_SIZE(result);
12606
12607                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12608
12609                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12610                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12611                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12612
12613                 while (size--)
12614                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12615
12616                 goto release;
12617         }
12618
12619         if(IS_BITFIELD(getSpec(restype))
12620           && IS_BITFIELD(getSpec(rtype))) {
12621           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12622         }
12623
12624         /* if they are the same size : or less */
12625         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12626
12627                 /* if they are in the same place */
12628                 if (pic16_sameRegs(AOP(right),AOP(result)))
12629                         goto release;
12630
12631                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12632 #if 0
12633                 if (IS_PTR_CONST(rtype))
12634 #else
12635                 if (IS_CODEPTR(rtype))
12636 #endif
12637                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12638
12639 #if 0
12640                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12641 #else
12642                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12643 #endif
12644                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12645
12646 #if 0
12647                 if(AOP_TYPE(right) == AOP_IMMD) {
12648                   pCodeOp *pcop0, *pcop1, *pcop2;
12649                   symbol *sym = OP_SYMBOL( right );
12650
12651                         size = AOP_SIZE(result);
12652                         /* low */
12653                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12654                         /* high */
12655                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12656                         /* upper */
12657                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12658         
12659                         if (size == 3) {
12660                                 pic16_emitpcode(POC_MOVLW, pcop0);
12661                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12662                                 pic16_emitpcode(POC_MOVLW, pcop1);
12663                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12664                                 pic16_emitpcode(POC_MOVLW, pcop2);
12665                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12666                         } else
12667                         if (size == 2) {
12668                                 pic16_emitpcode(POC_MOVLW, pcop0);
12669                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12670                                 pic16_emitpcode(POC_MOVLW, pcop1);
12671                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12672                         } else {
12673                                 pic16_emitpcode(POC_MOVLW, pcop0);
12674                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12675                         }
12676                 } else
12677 #endif
12678                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12679                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12680                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12681                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12682                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12683                         if(AOP_SIZE(result) <2)
12684                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12685                 } else {
12686                         /* if they in different places then copy */
12687                         size = AOP_SIZE(result);
12688                         offset = 0 ;
12689                         while (size--) {
12690                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12691                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12692                                 offset++;
12693                         }
12694                 }
12695                 goto release;
12696         }
12697
12698         /* if the result is of type pointer */
12699         if (IS_PTR(ctype)) {
12700           int p_type;
12701           sym_link *type = operandType(right);
12702           sym_link *etype = getSpec(type);
12703
12704                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12705
12706                 /* pointer to generic pointer */
12707                 if (IS_GENPTR(ctype)) {
12708                   char *l = zero;
12709             
12710                         if (IS_PTR(type)) 
12711                                 p_type = DCL_TYPE(type);
12712                         else {
12713                 /* we have to go by the storage class */
12714                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12715
12716 /*              if (SPEC_OCLS(etype)->codesp )  */
12717 /*                  p_type = CPOINTER ;  */
12718 /*              else */
12719 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12720 /*                      p_type = FPOINTER ; */
12721 /*                  else */
12722 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12723 /*                          p_type = PPOINTER; */
12724 /*                      else */
12725 /*                          if (SPEC_OCLS(etype) == idata ) */
12726 /*                              p_type = IPOINTER ; */
12727 /*                          else */
12728 /*                              p_type = POINTER ; */
12729             }
12730                 
12731             /* the first two bytes are known */
12732       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12733             size = GPTRSIZE - 1; 
12734             offset = 0 ;
12735             while (size--) {
12736               if(offset < AOP_SIZE(right)) {
12737                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12738                 mov2f(AOP(result), AOP(right), offset);
12739 /*
12740                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12741                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12742                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12743                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12744                 } else { 
12745                   
12746                   pic16_aopPut(AOP(result),
12747                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12748                          offset);
12749                 }
12750 */
12751               } else 
12752                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12753               offset++;
12754             }
12755             /* the last byte depending on type */
12756             switch (p_type) {
12757             case IPOINTER:
12758             case POINTER:
12759                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12760                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12761 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12762                 break;
12763
12764             case CPOINTER:
12765                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12766                 break;
12767
12768             case FPOINTER:
12769               pic16_emitcode(";BUG!? ","%d",__LINE__);
12770                 l = one;
12771                 break;
12772             case PPOINTER:
12773               pic16_emitcode(";BUG!? ","%d",__LINE__);
12774                 l = "#0x03";
12775                 break;
12776
12777             case GPOINTER:
12778               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12779               break;
12780               
12781             default:
12782                 /* this should never happen */
12783                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12784                        "got unknown pointer type");
12785                 exit(1);
12786             }
12787             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12788             goto release ;
12789         }
12790         
12791         /* just copy the pointers */
12792         size = AOP_SIZE(result);
12793         offset = 0 ;
12794         while (size--) {
12795             pic16_aopPut(AOP(result),
12796                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12797                    offset);
12798             offset++;
12799         }
12800         goto release ;
12801     }
12802     
12803
12804
12805     /* so we now know that the size of destination is greater
12806     than the size of the source.
12807     Now, if the next iCode is an operator then we might be
12808     able to optimize the operation without performing a cast.
12809     */
12810     if(genMixedOperation(ic))
12811       goto release;
12812
12813     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12814     
12815     /* we move to result for the size of source */
12816     size = AOP_SIZE(right);
12817     offset = 0 ;
12818     while (size--) {
12819       mov2f(AOP(result), AOP(right), offset);
12820       offset++;
12821     }
12822
12823     /* now depending on the sign of the destination */
12824     size = AOP_SIZE(result) - AOP_SIZE(right);
12825     /* if unsigned or not an integral type */
12826     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12827       while (size--)
12828         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12829     } else {
12830       /* we need to extend the sign :( */
12831
12832       if(size == 1) {
12833         /* Save one instruction of casting char to int */
12834         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12835         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12836         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
12837       } else {
12838         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12839
12840         if(offset)
12841           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12842         else
12843           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12844         
12845         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12846
12847         while (size--)
12848           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12849       }
12850     }
12851
12852 release:
12853     pic16_freeAsmop(right,NULL,ic,TRUE);
12854     pic16_freeAsmop(result,NULL,ic,TRUE);
12855
12856 }
12857
12858 /*-----------------------------------------------------------------*/
12859 /* genDjnz - generate decrement & jump if not zero instrucion      */
12860 /*-----------------------------------------------------------------*/
12861 static int genDjnz (iCode *ic, iCode *ifx)
12862 {
12863     symbol *lbl, *lbl1;
12864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12865
12866     if (!ifx)
12867         return 0;
12868     
12869     /* if the if condition has a false label
12870        then we cannot save */
12871     if (IC_FALSE(ifx))
12872         return 0;
12873
12874     /* if the minus is not of the form 
12875        a = a - 1 */
12876     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12877         !IS_OP_LITERAL(IC_RIGHT(ic)))
12878         return 0;
12879
12880     if (operandLitValue(IC_RIGHT(ic)) != 1)
12881         return 0;
12882
12883     /* if the size of this greater than one then no
12884        saving */
12885     if (getSize(operandType(IC_RESULT(ic))) > 1)
12886         return 0;
12887
12888     /* otherwise we can save BIG */
12889     lbl = newiTempLabel(NULL);
12890     lbl1= newiTempLabel(NULL);
12891
12892     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12893     
12894     if (IS_AOP_PREG(IC_RESULT(ic))) {
12895         pic16_emitcode("dec","%s",
12896                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12897         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12898         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12899     } else {    
12900
12901
12902       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12903       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12904
12905       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12906       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12907
12908     }
12909     
12910     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12911     ifx->generated = 1;
12912     return 1;
12913 }
12914
12915 /*-----------------------------------------------------------------*/
12916 /* genReceive - generate code for a receive iCode                  */
12917 /*-----------------------------------------------------------------*/
12918 static void genReceive (iCode *ic)
12919 {    
12920
12921   FENTRY;
12922
12923 #if 0
12924   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12925         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12926 #endif
12927 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12928
12929   if (isOperandInFarSpace(IC_RESULT(ic))
12930       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12931           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12932
12933     int size = getSize(operandType(IC_RESULT(ic)));
12934     int offset =  pic16_fReturnSizePic - size;
12935
12936       assert( 0 );
12937       while (size--) {
12938         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12939                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12940                       offset++;
12941         }
12942
12943       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
12944
12945       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12946       size = AOP_SIZE(IC_RESULT(ic));
12947       offset = 0;
12948       while (size--) {
12949         pic16_emitcode ("pop","acc");
12950         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12951       }
12952   } else {
12953     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12954
12955     _G.accInUse++;
12956     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
12957     _G.accInUse--;
12958     assignResultValue(IC_RESULT(ic), 0);
12959   }
12960
12961   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12962 }
12963
12964 /*-----------------------------------------------------------------*/
12965 /* genDummyRead - generate code for dummy read of volatiles        */
12966 /*-----------------------------------------------------------------*/
12967 static void
12968 genDummyRead (iCode * ic)
12969 {
12970   pic16_emitcode ("; genDummyRead","");
12971   pic16_emitcode ("; not implemented","");
12972
12973   ic = ic;
12974 }
12975
12976 /*-----------------------------------------------------------------*/
12977 /* genpic16Code - generate code for pic16 based controllers        */
12978 /*-----------------------------------------------------------------*/
12979 /*
12980  * At this point, ralloc.c has gone through the iCode and attempted
12981  * to optimize in a way suitable for a PIC. Now we've got to generate
12982  * PIC instructions that correspond to the iCode.
12983  *
12984  * Once the instructions are generated, we'll pass through both the
12985  * peep hole optimizer and the pCode optimizer.
12986  *-----------------------------------------------------------------*/
12987
12988 void genpic16Code (iCode *lic)
12989 {
12990   iCode *ic;
12991   int cln = 0;
12992
12993     lineHead = lineCurr = NULL;
12994
12995     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
12996     pic16_addpBlock(pb);
12997
12998 #if 0
12999     /* if debug information required */
13000     if (options.debug && currFunc) {
13001       if (currFunc) {
13002         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13003       }
13004     }
13005 #endif
13006
13007     for (ic = lic ; ic ; ic = ic->next ) {
13008
13009       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13010       if ( cln != ic->lineno ) {
13011         if ( options.debug ) {
13012           debugFile->writeCLine (ic);
13013         }
13014         
13015         if(!options.noCcodeInAsm) {
13016           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13017               printCLine(ic->filename, ic->lineno)));
13018         }
13019
13020         cln = ic->lineno ;
13021       }
13022         
13023       if(options.iCodeInAsm) {
13024         char *l;
13025
13026           /* insert here code to print iCode as comment */
13027           l = Safe_strdup(printILine(ic));
13028           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13029       }
13030         
13031       /* if the result is marked as
13032        * spilt and rematerializable or code for
13033        * this has already been generated then
13034        * do nothing */
13035       if (resultRemat(ic) || ic->generated ) 
13036         continue ;
13037         
13038       /* depending on the operation */
13039       switch (ic->op) {
13040         case '!' :
13041           pic16_genNot(ic);
13042           break;
13043             
13044         case '~' :
13045           pic16_genCpl(ic);
13046           break;
13047             
13048         case UNARYMINUS:
13049           genUminus (ic);
13050           break;
13051             
13052         case IPUSH:
13053           genIpush (ic);
13054           break;
13055             
13056         case IPOP:
13057           /* IPOP happens only when trying to restore a 
13058            * spilt live range, if there is an ifx statement
13059            * following this pop then the if statement might
13060            * be using some of the registers being popped which
13061            * would destroy the contents of the register so
13062            * we need to check for this condition and handle it */
13063            if (ic->next
13064              && ic->next->op == IFX
13065              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13066                genIfx (ic->next,ic);
13067           else
13068             genIpop (ic);
13069           break; 
13070             
13071         case CALL:
13072           genCall (ic);
13073           break;
13074             
13075         case PCALL:
13076           genPcall (ic);
13077           break;
13078             
13079         case FUNCTION:
13080           genFunction (ic);
13081           break;
13082             
13083         case ENDFUNCTION:
13084           genEndFunction (ic);
13085           break;
13086             
13087         case RETURN:
13088           genRet (ic);
13089           break;
13090             
13091         case LABEL:
13092           genLabel (ic);
13093           break;
13094             
13095         case GOTO:
13096           genGoto (ic);
13097           break;
13098             
13099         case '+' :
13100           pic16_genPlus (ic) ;
13101           break;
13102             
13103         case '-' :
13104           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13105             pic16_genMinus (ic);
13106           break;
13107
13108         case '*' :
13109           genMult (ic);
13110           break;
13111             
13112         case '/' :
13113           genDiv (ic) ;
13114           break;
13115             
13116         case '%' :
13117           genMod (ic);
13118           break;
13119             
13120         case '>' :
13121           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13122           break;
13123             
13124         case '<' :
13125           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13126           break;
13127             
13128         case LE_OP:
13129         case GE_OP:
13130         case NE_OP:
13131           /* note these two are xlated by algebraic equivalence
13132            * during parsing SDCC.y */
13133           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13134             "got '>=' or '<=' shouldn't have come here");
13135           break;
13136
13137         case EQ_OP:
13138           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13139           break;            
13140             
13141         case AND_OP:
13142           genAndOp (ic);
13143           break;
13144             
13145         case OR_OP:
13146           genOrOp (ic);
13147           break;
13148             
13149         case '^' :
13150           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13151           break;
13152             
13153         case '|' :
13154           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13155           break;
13156             
13157         case BITWISEAND:
13158           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13159           break;
13160             
13161         case INLINEASM:
13162           genInline (ic);
13163           break;
13164             
13165         case RRC:
13166           genRRC (ic);
13167           break;
13168             
13169         case RLC:
13170           genRLC (ic);
13171           break;
13172             
13173         case GETHBIT:
13174           genGetHbit (ic);
13175           break;
13176             
13177         case LEFT_OP:
13178           genLeftShift (ic);
13179           break;
13180             
13181         case RIGHT_OP:
13182           genRightShift (ic);
13183           break;
13184             
13185         case GET_VALUE_AT_ADDRESS:
13186           genPointerGet(ic);
13187           break;
13188             
13189         case '=' :
13190           if (POINTER_SET(ic))
13191             genPointerSet(ic);
13192           else
13193             genAssign(ic);
13194           break;
13195             
13196         case IFX:
13197           genIfx (ic,NULL);
13198           break;
13199             
13200         case ADDRESS_OF:
13201           genAddrOf (ic);
13202           break;
13203             
13204         case JUMPTABLE:
13205           genJumpTab (ic);
13206           break;
13207             
13208         case CAST:
13209           genCast (ic);
13210           break;
13211             
13212         case RECEIVE:
13213           genReceive(ic);
13214           break;
13215             
13216         case SEND:
13217           addSet(&_G.sendSet,ic);
13218           break;
13219
13220         case DUMMY_READ_VOLATILE:
13221           genDummyRead (ic);
13222           break;
13223
13224         default :
13225           ic = ic;
13226       }
13227     }
13228
13229
13230     /* now we are ready to call the
13231        peep hole optimizer */
13232     if (!options.nopeep)
13233       peepHole (&lineHead);
13234
13235     /* now do the actual printing */
13236     printLine (lineHead, codeOutFile);
13237
13238 #ifdef PCODE_DEBUG
13239     DFPRINTF((stderr,"printing pBlock\n\n"));
13240     pic16_printpBlock(stdout,pb);
13241 #endif
13242
13243     return;
13244 }
13245