Applied patch from Vangelis Rokas <vrokas@otenet.gr> for pic16 multi-operand
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
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   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45
46
47 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
48 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
49 void pic16_genMult8X8_8 (operand *, operand *,operand *);
50 pCode *pic16_AssembleLine(char *line);
51 extern void pic16_printpBlock(FILE *of, pBlock *pb);
52 static asmop *newAsmop (short type);
53 static pCodeOp *popRegFromString(char *str, int size, int offset);
54 static void mov2w (asmop *aop, int offset);
55 static int aopIdx (asmop *aop, int offset);
56
57 static int labelOffset=0;
58 extern int pic16_debug_verbose;
59 static int optimized_for_speed = 0;
60 /*
61   hack hack
62
63 */
64 int options_no_movff = 1;
65
66 /* max_key keeps track of the largest label number used in 
67    a function. This is then used to adjust the label offset
68    for the next function.
69 */
70 static int max_key=0;
71 static int GpsuedoStkPtr=0;
72
73 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
74 unsigned int pic16aopLiteral (value *val, int offset);
75 const char *pic16_AopType(short type);
76 static iCode *ifxForOp ( operand *op, iCode *ic );
77
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
79
80 /* this is the down and dirty file with all kinds of 
81    kludgy & hacky stuff. This is what it is all about
82    CODE GENERATION for a specific MCU . some of the
83    routines may be reusable, will have to see */
84
85 static char *zero = "#0x00";
86 static char *one  = "#0x01";
87 static char *spname = "sp";
88
89 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
90 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
91 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
92 static char **fReturn = fReturnpic16;
93
94 static char *accUse[] = {"a","b"};
95
96 //static short rbank = -1;
97
98 static struct {
99     short r0Pushed;
100     short r1Pushed;
101     short accInUse;
102     short inLine;
103     short debugLine;
104     short nRegsSaved;
105     set *sendSet;
106 } _G;
107
108 /* Resolved ifx structure. This structure stores information
109    about an iCode ifx that makes it easier to generate code.
110 */
111 typedef struct resolvedIfx {
112   symbol *lbl;     /* pointer to a label */
113   int condition;   /* true or false ifx */
114   int generated;   /* set true when the code associated with the ifx
115                     * is generated */
116 } resolvedIfx;
117
118 extern int pic16_ptrRegReq ;
119 extern int pic16_nRegs;
120 extern FILE *codeOutFile;
121 static void saverbank (int, iCode *,bool);
122
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
125
126 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
130
131 static  pBlock *pb;
132
133 /*-----------------------------------------------------------------*/
134 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
135 /*                 exponent of 2 is returned, otherwise -1 is      */
136 /*                 returned.                                       */
137 /* note that this is similar to the function `powof2' in SDCCsymt  */
138 /* if(n == 2^y)                                                    */
139 /*   return y;                                                     */
140 /* return -1;                                                      */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
143 {
144   if(num) {
145     if( (num & (num-1)) == 0) {
146       int nshifts = -1;
147       while(num) {
148         num>>=1;
149         nshifts++;
150       }
151       return nshifts;
152     }
153   }
154
155   return -1;
156 }
157
158 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
159 {
160
161   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
162                        line_no,
163                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
164                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
166                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
168                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
169                        ((result) ? AOP_SIZE(result) : 0));
170
171 }
172
173 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
174 {
175
176   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
177                        line_no,
178                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
179                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
180                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
181                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
182                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
183                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
184
185 }
186
187 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
188 {
189     va_list ap;
190     char lb[INITIAL_INLINEASM];  
191     char *lbp = lb;
192
193     if(!pic16_debug_verbose)
194       return;
195
196     va_start(ap,fmt);   
197
198     if (inst && *inst) {
199         if (fmt && *fmt)
200             sprintf(lb,"%s\t",inst);
201         else
202             sprintf(lb,"%s",inst);
203         vsprintf(lb+(strlen(lb)),fmt,ap);
204     }  else
205         vsprintf(lb,fmt,ap);
206
207     while (isspace(*lbp)) lbp++;
208
209     if (lbp && *lbp) 
210         lineCurr = (lineCurr ?
211                     connectLine(lineCurr,newLineNode(lb)) :
212                     (lineHead = newLineNode(lb)));
213     lineCurr->isInline = _G.inLine;
214     lineCurr->isDebug  = _G.debugLine;
215
216     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
217     va_end(ap);
218
219 //      fprintf(stderr, "%s\n", lb);
220 }
221
222
223 void pic16_emitpLabel(int key)
224 {
225   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
226 }
227
228 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
229 {
230
231   if(pcop)
232     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
233   else
234     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
235     
236 //    fprintf(stderr, "%s\n", pcop->name);
237 }
238
239 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
240 {
241
242   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
243
244 }
245
246 /*-----------------------------------------------------------------*/
247 /* pic16_emitcode - writes the code into a file : for now it is simple    */
248 /*-----------------------------------------------------------------*/
249 void pic16_emitcode (char *inst,char *fmt, ...)
250 {
251     va_list ap;
252     char lb[INITIAL_INLINEASM];  
253     char *lbp = lb;
254
255     va_start(ap,fmt);   
256
257     if (inst && *inst) {
258         if (fmt && *fmt)
259             sprintf(lb,"%s\t",inst);
260         else
261             sprintf(lb,"%s",inst);
262         vsprintf(lb+(strlen(lb)),fmt,ap);
263     }  else
264         vsprintf(lb,fmt,ap);
265
266     while (isspace(*lbp)) lbp++;
267
268     if (lbp && *lbp) 
269         lineCurr = (lineCurr ?
270                     connectLine(lineCurr,newLineNode(lb)) :
271                     (lineHead = newLineNode(lb)));
272     lineCurr->isInline = _G.inLine;
273     lineCurr->isDebug  = _G.debugLine;
274
275 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
276
277     if(pic16_debug_verbose)
278       pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
279
280     va_end(ap);
281 }
282
283
284 /*-----------------------------------------------------------------*/
285 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
286 /*-----------------------------------------------------------------*/
287 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
288 {
289     bool r0iu = FALSE , r1iu = FALSE;
290     bool r0ou = FALSE , r1ou = FALSE;
291
292
293         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
294     /* the logic: if r0 & r1 used in the instruction
295     then we are in trouble otherwise */
296
297     /* first check if r0 & r1 are used by this
298     instruction, in which case we are in trouble */
299     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
300         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
301     {
302         goto endOfWorld;      
303     }
304
305     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
306     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
307
308     /* if no usage of r0 then return it */
309     if (!r0iu && !r0ou) {
310         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
311         (*aopp)->type = AOP_R0;
312         
313         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
314     }
315
316     /* if no usage of r1 then return it */
317     if (!r1iu && !r1ou) {
318         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
319         (*aopp)->type = AOP_R1;
320
321         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
322     }    
323
324     /* now we know they both have usage */
325     /* if r0 not used in this instruction */
326     if (!r0iu) {
327         /* push it if not already pushed */
328         if (!_G.r0Pushed) {
329           //pic16_emitcode ("push","%s",
330           //          pic16_regWithIdx(R0_IDX)->dname);
331             _G.r0Pushed++ ;
332         }
333         
334         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
335         (*aopp)->type = AOP_R0;
336
337         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
338     }
339
340     /* if r1 not used then */
341
342     if (!r1iu) {
343         /* push it if not already pushed */
344         if (!_G.r1Pushed) {
345           //pic16_emitcode ("push","%s",
346           //          pic16_regWithIdx(R1_IDX)->dname);
347             _G.r1Pushed++ ;
348         }
349         
350         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
351         (*aopp)->type = AOP_R1;
352         return pic16_regWithIdx(R1_IDX);
353     }
354
355 endOfWorld :
356     /* I said end of world but not quite end of world yet */
357     /* if this is a result then we can push it on the stack*/
358     if (result) {
359         (*aopp)->type = AOP_STK;    
360         return NULL;
361     }
362
363     /* other wise this is true end of the world */
364     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
365            "getFreePtr should never reach here");
366     exit(0);
367 }
368
369 /*-----------------------------------------------------------------*/
370 /* newAsmop - creates a new asmOp                                  */
371 /*-----------------------------------------------------------------*/
372 static asmop *newAsmop (short type)
373 {
374     asmop *aop;
375
376     aop = Safe_calloc(1,sizeof(asmop));
377     aop->type = type;
378     return aop;
379 }
380
381 static void genSetDPTR(int n)
382 {
383     if (!n)
384     {
385         pic16_emitcode(";", "Select standard DPTR");
386         pic16_emitcode("mov", "dps, #0x00");
387     }
388     else
389     {
390         pic16_emitcode(";", "Select alternate DPTR");
391         pic16_emitcode("mov", "dps, #0x01");
392     }
393 }
394
395 /*-----------------------------------------------------------------*/
396 /* resolveIfx - converts an iCode ifx into a form more useful for  */
397 /*              generating code                                    */
398 /*-----------------------------------------------------------------*/
399 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
400 {
401   if(!resIfx) 
402     return;
403
404   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
405
406   resIfx->condition = 1;    /* assume that the ifx is true */
407   resIfx->generated = 0;    /* indicate that the ifx has not been used */
408
409   if(!ifx) {
410     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
411 /*
412     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
413                         __FUNCTION__,__LINE__,resIfx->lbl->key);
414 */
415   } else {
416     if(IC_TRUE(ifx)) {
417       resIfx->lbl = IC_TRUE(ifx);
418     } else {
419       resIfx->lbl = IC_FALSE(ifx);
420       resIfx->condition = 0;
421     }
422 /*
423     if(IC_TRUE(ifx)) 
424       DEBUGpic16_emitcode("; ***","ifx true is non-null");
425     if(IC_FALSE(ifx)) 
426       DEBUGpic16_emitcode("; ***","ifx false is non-null");
427 */
428   }
429
430   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
431
432 }
433 /*-----------------------------------------------------------------*/
434 /* pointerCode - returns the code for a pointer type               */
435 /*-----------------------------------------------------------------*/
436 static int pointerCode (sym_link *etype)
437 {
438
439     return PTR_TYPE(SPEC_OCLS(etype));
440
441 }
442
443 /*-----------------------------------------------------------------*/
444 /* aopForSym - for a true symbol                                   */
445 /*-----------------------------------------------------------------*/
446 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
447 {
448     asmop *aop;
449     memmap *space= SPEC_OCLS(sym->etype);
450
451     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
452     /* if already has one */
453     if (sym->aop) {
454             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
455         return sym->aop;
456     }
457
458     /* assign depending on the storage class */
459     /* if it is on the stack or indirectly addressable */
460     /* space we need to assign either r0 or r1 to it   */    
461     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
462         sym->aop = aop = newAsmop(0);
463         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
464         aop->size = getSize(sym->type);
465
466         /* now assign the address of the variable to 
467         the pointer register */
468         if (aop->type != AOP_STK) {
469
470             if (sym->onStack) {
471                     if ( _G.accInUse )
472                         pic16_emitcode("push","acc");
473
474                     pic16_emitcode("mov","a,_bp");
475                     pic16_emitcode("add","a,#0x%02x",
476                              ((sym->stack < 0) ?
477                               ((char)(sym->stack - _G.nRegsSaved )) :
478                               ((char)sym->stack)) & 0xff);
479                     pic16_emitcode("mov","%s,a",
480                              aop->aopu.aop_ptr->name);
481
482                     if ( _G.accInUse )
483                         pic16_emitcode("pop","acc");
484             } else
485                 pic16_emitcode("mov","%s,#%s",
486                          aop->aopu.aop_ptr->name,
487                          sym->rname);
488             aop->paged = space->paged;
489         } else
490             aop->aopu.aop_stk = sym->stack;
491         return aop;
492     }
493     
494     if (sym->onStack && options.stack10bit)
495     {
496         /* It's on the 10 bit stack, which is located in
497          * far data space.
498          */
499          
500       //DEBUGpic16_emitcode(";","%d",__LINE__);
501
502         if ( _G.accInUse )
503                 pic16_emitcode("push","acc");
504
505         pic16_emitcode("mov","a,_bp");
506         pic16_emitcode("add","a,#0x%02x",
507                  ((sym->stack < 0) ?
508                    ((char)(sym->stack - _G.nRegsSaved )) :
509                    ((char)sym->stack)) & 0xff);
510         
511         genSetDPTR(1);
512         pic16_emitcode ("mov","dpx1,#0x40");
513         pic16_emitcode ("mov","dph1,#0x00");
514         pic16_emitcode ("mov","dpl1, a");
515         genSetDPTR(0);
516         
517         if ( _G.accInUse )
518             pic16_emitcode("pop","acc");
519             
520         sym->aop = aop = newAsmop(AOP_DPTR2);
521         aop->size = getSize(sym->type); 
522         return aop;
523     }
524
525     //DEBUGpic16_emitcode(";","%d",__LINE__);
526     /* if in bit space */
527     if (IN_BITSPACE(space)) {
528         sym->aop = aop = newAsmop (AOP_CRY);
529         aop->aopu.aop_dir = sym->rname ;
530         aop->size = getSize(sym->type);
531         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
532         return aop;
533     }
534     /* if it is in direct space */
535     if (IN_DIRSPACE(space)) {
536         sym->aop = aop = newAsmop (AOP_DIR);
537         aop->aopu.aop_dir = sym->rname ;
538         aop->size = getSize(sym->type);
539         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
540         return aop;
541     }
542
543     /* special case for a function */
544     if (IS_FUNC(sym->type)) {   
545         sym->aop = aop = newAsmop(AOP_IMMD);    
546         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
547         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
548         strcpy(aop->aopu.aop_immd,sym->rname);
549         aop->size = FPTRSIZE; 
550         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
551         return aop;
552     }
553
554
555     /* only remaining is far space */
556     /* in which case DPTR gets the address */
557     sym->aop = aop = newAsmop(AOP_PCODE);
558
559     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
560     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561     PCOI(aop->aopu.pcop)->index = 0;
562
563     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
564                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
565
566     pic16_allocDirReg (IC_LEFT(ic));
567
568     aop->size = FPTRSIZE; 
569 /*
570     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571     sym->aop = aop = newAsmop(AOP_DPTR);
572     pic16_emitcode ("mov","dptr,#%s", sym->rname);
573     aop->size = getSize(sym->type);
574
575     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
576 */
577
578     /* if it is in code space */
579     if (IN_CODESPACE(space))
580         aop->code = 1;
581
582     return aop;     
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                           */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
589 {
590   symbol *sym = OP_SYMBOL(op);
591   iCode *ic = NULL;
592   asmop *aop = newAsmop(AOP_PCODE);
593   int val = 0;
594   int offset = 0;
595
596   ic = sym->rematiCode;
597
598   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599   if(IS_OP_POINTER(op)) {
600     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
601   }
602   for (;;) {
603     if (ic->op == '+') {
604       val += (int) operandLitValue(IC_RIGHT(ic));
605     } else if (ic->op == '-') {
606       val -= (int) operandLitValue(IC_RIGHT(ic));
607     } else
608       break;
609         
610     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
611   }
612
613   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
615   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616   PCOI(aop->aopu.pcop)->index = val;
617
618   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
619                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620                       val, IS_PTR_CONST(operandType(op)));
621
622   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
623
624   pic16_allocDirReg (IC_LEFT(ic));
625
626   return aop;        
627 }
628
629 static int aopIdx (asmop *aop, int offset)
630 {
631   if(!aop)
632     return -1;
633
634   if(aop->type !=  AOP_REG)
635     return -2;
636         
637   return aop->aopu.aop_reg[offset]->rIdx;
638
639 }
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common       */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
644 {
645     symbol *sym1, *sym2;
646     int i;
647
648     /* if they have registers in common */
649     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
650         return FALSE ;
651
652     sym1 = OP_SYMBOL(op1);
653     sym2 = OP_SYMBOL(op2);
654
655     if (sym1->nRegs == 0 || sym2->nRegs == 0)
656         return FALSE ;
657
658     for (i = 0 ; i < sym1->nRegs ; i++) {
659         int j;
660         if (!sym1->regs[i])
661             continue ;
662
663         for (j = 0 ; j < sym2->nRegs ;j++ ) {
664             if (!sym2->regs[j])
665                 continue ;
666
667             if (sym2->regs[j] == sym1->regs[i])
668                 return TRUE ;
669         }
670     }
671
672     return FALSE ;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent                                        */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
679 {
680     symbol *sym1, *sym2;
681
682     /* if they not symbols */
683     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
684         return FALSE;
685
686     sym1 = OP_SYMBOL(op1);
687     sym2 = OP_SYMBOL(op2);
688
689     /* if both are itemps & one is spilt
690        and the other is not then false */
691     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692         sym1->isspilt != sym2->isspilt )
693         return FALSE ;
694
695     /* if they are the same */
696     if (sym1 == sym2)
697         return TRUE ;
698
699     if (strcmp(sym1->rname,sym2->rname) == 0)
700         return TRUE;
701
702
703     /* if left is a tmp & right is not */
704     if (IS_ITEMP(op1)  && 
705         !IS_ITEMP(op2) &&
706         sym1->isspilt  &&
707         (sym1->usl.spillLoc == sym2))
708         return TRUE;
709
710     if (IS_ITEMP(op2)  && 
711         !IS_ITEMP(op1) &&
712         sym2->isspilt  &&
713         sym1->level > 0 &&
714         (sym2->usl.spillLoc == sym1))
715         return TRUE ;
716
717     return FALSE ;
718 }
719
720 /*-----------------------------------------------------------------*/
721 /* pic16_sameRegs - two asmops have the same registers                   */
722 /*-----------------------------------------------------------------*/
723 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
724 {
725     int i;
726
727     if (aop1 == aop2)
728         return TRUE ;
729
730     if (aop1->type != AOP_REG ||
731         aop2->type != AOP_REG )
732         return FALSE ;
733
734     if (aop1->size != aop2->size )
735         return FALSE ;
736
737     for (i = 0 ; i < aop1->size ; i++ )
738         if (aop1->aopu.aop_reg[i] !=
739             aop2->aopu.aop_reg[i] )
740             return FALSE ;
741
742     return TRUE ;
743 }
744
745 /*-----------------------------------------------------------------*/
746 /* pic16_aopOp - allocates an asmop for an operand  :                    */
747 /*-----------------------------------------------------------------*/
748 void pic16_aopOp (operand *op, iCode *ic, bool result)
749 {
750     asmop *aop;
751     symbol *sym;
752     int i;
753
754     if (!op)
755         return ;
756
757     //    DEBUGpic16_emitcode(";","%d",__LINE__);
758     /* if this a literal */
759     if (IS_OP_LITERAL(op)) {
760         op->aop = aop = newAsmop(AOP_LIT);
761         aop->aopu.aop_lit = op->operand.valOperand;
762         aop->size = getSize(operandType(op));
763         return;
764     }
765
766     {
767       sym_link *type = operandType(op);
768       if(IS_PTR_CONST(type))
769         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
770     }
771
772     /* if already has a asmop then continue */
773     if (op->aop)
774         return ;
775
776     /* if the underlying symbol has a aop */
777     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
779         op->aop = OP_SYMBOL(op)->aop;
780         return;
781     }
782
783     /* if this is a true symbol */
784     if (IS_TRUE_SYMOP(op)) {    
785         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
786       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
787       return ;
788     }
789
790     /* this is a temporary : this has
791     only four choices :
792     a) register
793     b) spillocation
794     c) rematerialize 
795     d) conditional   
796     e) can be a return use only */
797
798     sym = OP_SYMBOL(op);
799
800         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
801     /* if the type is a conditional */
802     if (sym->regType == REG_CND) {
803         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
804         aop->size = 0;
805         return;
806     }
807
808     /* if it is spilt then two situations
809     a) is rematerialize 
810     b) has a spill location */
811     if (sym->isspilt || sym->nRegs == 0) {
812
813       DEBUGpic16_emitcode(";","%d",__LINE__);
814         /* rematerialize it NOW */
815         if (sym->remat) {
816
817             sym->aop = op->aop = aop =
818                                       aopForRemat (op);
819             aop->size = getSize(sym->type);
820             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
821             return;
822         }
823
824         if (sym->accuse) {
825             int i;
826             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
827             aop->size = getSize(sym->type);
828             for ( i = 0 ; i < 2 ; i++ )
829                 aop->aopu.aop_str[i] = accUse[i];
830             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
831             return;  
832         }
833
834         if (sym->ruonly ) {
835           /*
836           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
837           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
838           //pic16_allocDirReg (IC_LEFT(ic));
839           aop->size = getSize(sym->type);
840           */
841
842           unsigned i;
843
844           aop = op->aop = sym->aop = newAsmop(AOP_STR);
845           aop->size = getSize(sym->type);
846           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
847             aop->aopu.aop_str[i] = fReturn[i];
848
849           DEBUGpic16_emitcode(";","%d",__LINE__);
850           return;
851         }
852
853         /* else spill location  */
854         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
855             /* force a new aop if sizes differ */
856             sym->usl.spillLoc->aop = NULL;
857         }
858         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
859                             __FUNCTION__,__LINE__,
860                             sym->usl.spillLoc->rname,
861                             sym->rname, sym->usl.spillLoc->offset);
862
863         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
864         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
865         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
866                                           getSize(sym->type), 
867                                           sym->usl.spillLoc->offset);
868         aop->size = getSize(sym->type);
869
870         return;
871     }
872
873     {
874       sym_link *type = operandType(op);
875       if(IS_PTR_CONST(type)) 
876         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
877     }
878
879     /* must be in a register */
880     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
881     sym->aop = op->aop = aop = newAsmop(AOP_REG);
882     aop->size = sym->nRegs;
883     for ( i = 0 ; i < sym->nRegs ;i++)
884         aop->aopu.aop_reg[i] = sym->regs[i];
885 }
886
887 /*-----------------------------------------------------------------*/
888 /* pic16_freeAsmop - free up the asmop given to an operand               */
889 /*----------------------------------------------------------------*/
890 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
891 {   
892     asmop *aop ;
893
894     if (!op)
895         aop = aaop;
896     else 
897         aop = op->aop;
898
899     if (!aop)
900         return ;
901
902     if (aop->freed)
903         goto dealloc; 
904
905     aop->freed = 1;
906
907     /* depending on the asmop type only three cases need work AOP_RO
908        , AOP_R1 && AOP_STK */
909 #if 0
910     switch (aop->type) {
911         case AOP_R0 :
912             if (_G.r0Pushed ) {
913                 if (pop) {
914                     pic16_emitcode ("pop","ar0");     
915                     _G.r0Pushed--;
916                 }
917             }
918             bitVectUnSetBit(ic->rUsed,R0_IDX);
919             break;
920
921         case AOP_R1 :
922             if (_G.r1Pushed ) {
923                 if (pop) {
924                     pic16_emitcode ("pop","ar1");
925                     _G.r1Pushed--;
926                 }
927             }
928             bitVectUnSetBit(ic->rUsed,R1_IDX);          
929             break;
930
931         case AOP_STK :
932         {
933             int sz = aop->size;    
934             int stk = aop->aopu.aop_stk + aop->size;
935             bitVectUnSetBit(ic->rUsed,R0_IDX);
936             bitVectUnSetBit(ic->rUsed,R1_IDX);          
937
938             getFreePtr(ic,&aop,FALSE);
939             
940             if (options.stack10bit)
941             {
942                 /* I'm not sure what to do here yet... */
943                 /* #STUB */
944                 fprintf(stderr, 
945                         "*** Warning: probably generating bad code for "
946                         "10 bit stack mode.\n");
947             }
948             
949             if (stk) {
950                 pic16_emitcode ("mov","a,_bp");
951                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
952                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
953             } else {
954                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
955             }
956
957             while (sz--) {
958                 pic16_emitcode("pop","acc");
959                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
960                 if (!sz) break;
961                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
962             }
963             op->aop = aop;
964             pic16_freeAsmop(op,NULL,ic,TRUE);
965             if (_G.r0Pushed) {
966                 pic16_emitcode("pop","ar0");
967                 _G.r0Pushed--;
968             }
969
970             if (_G.r1Pushed) {
971                 pic16_emitcode("pop","ar1");
972                 _G.r1Pushed--;
973             }       
974         }
975     }
976 #endif
977
978 dealloc:
979     /* all other cases just dealloc */
980     if (op ) {
981         op->aop = NULL;
982         if (IS_SYMOP(op)) {
983             OP_SYMBOL(op)->aop = NULL;    
984             /* if the symbol has a spill */
985             if (SPIL_LOC(op))
986                 SPIL_LOC(op)->aop = NULL;
987         }
988     }
989 }
990
991 /*-----------------------------------------------------------------*/
992 /* pic16_aopGet - for fetching value of the aop                          */
993 /*-----------------------------------------------------------------*/
994 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
995 {
996     char *s = buffer ;
997     char *rs;
998
999     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1000     /* offset is greater than
1001     size then zero */
1002     if (offset > (aop->size - 1) &&
1003         aop->type != AOP_LIT)
1004         return zero;
1005
1006     /* depending on type */
1007     switch (aop->type) {
1008         
1009     case AOP_R0:
1010     case AOP_R1:
1011         DEBUGpic16_emitcode(";","%d",__LINE__);
1012         /* if we need to increment it */       
1013         while (offset > aop->coff) {        
1014             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1015             aop->coff++;
1016         }
1017         
1018         while (offset < aop->coff) {
1019             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1020             aop->coff--;
1021         }
1022         
1023         aop->coff = offset ;
1024         if (aop->paged) {
1025             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1026             return (dname ? "acc" : "a");
1027         }       
1028         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1029         rs = Safe_calloc(1,strlen(s)+1);
1030         strcpy(rs,s);   
1031         return rs;
1032         
1033     case AOP_DPTR:
1034     case AOP_DPTR2:
1035         DEBUGpic16_emitcode(";","%d",__LINE__);
1036     if (aop->type == AOP_DPTR2)
1037     {
1038         genSetDPTR(1);
1039     }
1040     
1041         while (offset > aop->coff) {
1042             pic16_emitcode ("inc","dptr");
1043             aop->coff++;
1044         }
1045         
1046         while (offset < aop->coff) {        
1047             pic16_emitcode("lcall","__decdptr");
1048             aop->coff--;
1049         }
1050         
1051         aop->coff = offset;
1052         if (aop->code) {
1053             pic16_emitcode("clr","a");
1054             pic16_emitcode("movc","a,@a+dptr");
1055         }
1056     else {
1057             pic16_emitcode("movx","a,@dptr");
1058     }
1059             
1060     if (aop->type == AOP_DPTR2)
1061     {
1062         genSetDPTR(0);
1063     }
1064             
1065     return (dname ? "acc" : "a");
1066         
1067         
1068     case AOP_IMMD:
1069         if (bit16) 
1070             sprintf (s,"%s",aop->aopu.aop_immd);
1071         else
1072             if (offset) 
1073                 sprintf(s,"(%s >> %d)",
1074                         aop->aopu.aop_immd,
1075                         offset*8);
1076             else
1077                 sprintf(s,"%s",
1078                         aop->aopu.aop_immd);
1079         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1080         rs = Safe_calloc(1,strlen(s)+1);
1081         strcpy(rs,s);   
1082         return rs;
1083         
1084     case AOP_DIR:
1085       if (offset) {
1086         sprintf(s,"(%s + %d)",
1087                 aop->aopu.aop_dir,
1088                 offset);
1089         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1090       } else
1091             sprintf(s,"%s",aop->aopu.aop_dir);
1092         rs = Safe_calloc(1,strlen(s)+1);
1093         strcpy(rs,s);   
1094         return rs;
1095         
1096     case AOP_REG:
1097       //if (dname) 
1098       //    return aop->aopu.aop_reg[offset]->dname;
1099       //else
1100             return aop->aopu.aop_reg[offset]->name;
1101         
1102     case AOP_CRY:
1103       //pic16_emitcode(";","%d",__LINE__);
1104       return aop->aopu.aop_dir;
1105         
1106     case AOP_ACC:
1107         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1108         return "AOP_accumulator_bug";
1109
1110     case AOP_LIT:
1111         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1112         rs = Safe_calloc(1,strlen(s)+1);
1113         strcpy(rs,s);   
1114         return rs;
1115         
1116     case AOP_STR:
1117         aop->coff = offset ;
1118         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1119             dname)
1120             return "acc";
1121         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1122         
1123         return aop->aopu.aop_str[offset];
1124         
1125     case AOP_PCODE:
1126       {
1127         pCodeOp *pcop = aop->aopu.pcop;
1128         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1129         if(pcop->name) {
1130           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1131           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1132           sprintf(s,"%s", pcop->name);
1133         } else
1134           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1135
1136       }
1137       rs = Safe_calloc(1,strlen(s)+1);
1138       strcpy(rs,s);   
1139       return rs;
1140
1141     }
1142
1143     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1144            "aopget got unsupported aop->type");
1145     exit(0);
1146 }
1147
1148
1149 /*-----------------------------------------------------------------*/
1150 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1151 /*-----------------------------------------------------------------*/
1152 pCodeOp *pic16_popGetTempReg(void)
1153 {
1154
1155   pCodeOp *pcop;
1156
1157   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1158   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1159     PCOR(pcop)->r->wasUsed=1;
1160     PCOR(pcop)->r->isFree=0;
1161   }
1162
1163   return pcop;
1164 }
1165
1166 /*-----------------------------------------------------------------*/
1167 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1168 /*-----------------------------------------------------------------*/
1169 void pic16_popReleaseTempReg(pCodeOp *pcop)
1170 {
1171
1172   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1173     PCOR(pcop)->r->isFree = 1;
1174
1175 }
1176 /*-----------------------------------------------------------------*/
1177 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1178 /*-----------------------------------------------------------------*/
1179 pCodeOp *pic16_popGetLabel(unsigned int key)
1180 {
1181
1182   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1183
1184   if(key>max_key)
1185     max_key = key;
1186
1187   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1188 }
1189
1190 /*-----------------------------------------------------------------*/
1191 /* pic16_popCopyReg - copy a pcode operator                              */
1192 /*-----------------------------------------------------------------*/
1193 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1194 {
1195   pCodeOpReg *pcor;
1196
1197   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1198   pcor->pcop.type = pc->pcop.type;
1199   if(pc->pcop.name) {
1200     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1201       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1202   } else
1203     pcor->pcop.name = NULL;
1204
1205   pcor->r = pc->r;
1206   pcor->rIdx = pc->rIdx;
1207   pcor->r->wasUsed=1;
1208
1209   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1210
1211   return PCOP(pcor);
1212 }
1213 /*-----------------------------------------------------------------*/
1214 /* pic16_popGet - asm operator to pcode operator conversion              */
1215 /*-----------------------------------------------------------------*/
1216 pCodeOp *pic16_popGetLit(unsigned int lit)
1217 {
1218
1219   return pic16_newpCodeOpLit(lit);
1220 }
1221
1222
1223 /*-----------------------------------------------------------------*/
1224 /* pic16_popGetImmd - asm operator to pcode immediate conversion         */
1225 /*-----------------------------------------------------------------*/
1226 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1227 {
1228
1229   return pic16_newpCodeOpImmd(name, offset,index, 0);
1230 }
1231
1232
1233 /*-----------------------------------------------------------------*/
1234 /* pic16_popGet - asm operator to pcode operator conversion              */
1235 /*-----------------------------------------------------------------*/
1236 pCodeOp *pic16_popGetWithString(char *str)
1237 {
1238   pCodeOp *pcop;
1239
1240
1241   if(!str) {
1242     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1243     exit (1);
1244   }
1245
1246   pcop = pic16_newpCodeOp(str,PO_STR);
1247
1248   return pcop;
1249 }
1250
1251 /*-----------------------------------------------------------------*/
1252 /* popRegFromString -                                              */
1253 /*-----------------------------------------------------------------*/
1254 static pCodeOp *popRegFromString(char *str, int size, int offset)
1255 {
1256
1257   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1258   pcop->type = PO_DIR;
1259
1260   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1261 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1262
1263   if(!str)
1264     str = "BAD_STRING";
1265
1266   pcop->name = Safe_calloc(1,strlen(str)+1);
1267   strcpy(pcop->name,str);
1268
1269   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1270
1271   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1272   if(PCOR(pcop)->r == NULL) {
1273     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1274     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1275         //fprintf(stderr, "allocating new register -> %s\n", str);
1276     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1277   } else {
1278     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1279   }
1280   PCOR(pcop)->instance = offset;
1281
1282   return pcop;
1283 }
1284
1285 static pCodeOp *popRegFromIdx(int rIdx)
1286 {
1287   pCodeOp *pcop;
1288
1289   DEBUGpic16_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1290                        __FUNCTION__,__LINE__,rIdx);
1291
1292   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1293
1294   PCOR(pcop)->rIdx = rIdx;
1295   PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1296   PCOR(pcop)->r->isFree = 0;
1297   PCOR(pcop)->r->wasUsed = 1;
1298
1299   pcop->type = PCOR(pcop)->r->pc_type;
1300
1301
1302   return pcop;
1303 }
1304
1305 /*---------------------------------------------------------------------------------*/
1306 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1307 /*                 VR 030601                                                       */
1308 /*---------------------------------------------------------------------------------*/
1309 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1310 {
1311   pCodeOpReg2 *pcop2;
1312   pCodeOp *temp;
1313   
1314         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1315         temp = pic16_popGet(aop_dst, offset);
1316         pcop2->pcop2 = temp;
1317         
1318   return PCOP(pcop2);
1319 }
1320
1321
1322 /*-----------------------------------------------------------------*/
1323 /* pic16_popGet - asm operator to pcode operator conversion              */
1324 /*-----------------------------------------------------------------*/
1325 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1326 {
1327   //char *s = buffer ;
1328     //char *rs;
1329
1330     pCodeOp *pcop;
1331
1332     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1333     /* offset is greater than
1334     size then zero */
1335
1336     if (offset > (aop->size - 1) &&
1337         aop->type != AOP_LIT)
1338       return NULL;  //zero;
1339
1340     /* depending on type */
1341     switch (aop->type) {
1342         
1343     case AOP_R0:
1344     case AOP_R1:
1345     case AOP_DPTR:
1346     case AOP_DPTR2:
1347     case AOP_ACC:
1348         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1349         return NULL;
1350         
1351     case AOP_IMMD:
1352       DEBUGpic16_emitcode(";","%d",__LINE__);
1353       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1354
1355     case AOP_DIR:
1356       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1357
1358 #if 0
1359         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1360         pcop->type = PO_DIR;
1361
1362         /*
1363         if (offset)
1364             sprintf(s,"(%s + %d)",
1365                     aop->aopu.aop_dir,
1366                     offset);
1367         else
1368             sprintf(s,"%s",aop->aopu.aop_dir);
1369         pcop->name = Safe_calloc(1,strlen(s)+1);
1370         strcpy(pcop->name,s);   
1371         */
1372         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1373         strcpy(pcop->name,aop->aopu.aop_dir);   
1374         PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1375         if(PCOR(pcop)->r == NULL) {
1376           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1377           PCOR(pcop)->r = pic16_allocRegByName (aop->aopu.aop_dir,aop->size);
1378           DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1379         } else {
1380           DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1381         }
1382         PCOR(pcop)->instance = offset;
1383
1384         return pcop;
1385 #endif
1386         
1387     case AOP_REG:
1388       {
1389         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1390
1391         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1392         PCOR(pcop)->rIdx = rIdx;
1393         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1394         PCOR(pcop)->r->wasUsed=1;
1395         PCOR(pcop)->r->isFree=0;
1396
1397         PCOR(pcop)->instance = offset;
1398         pcop->type = PCOR(pcop)->r->pc_type;
1399         //rs = aop->aopu.aop_reg[offset]->name;
1400         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1401         return pcop;
1402       }
1403
1404     case AOP_CRY:
1405       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1406       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1407       //if(PCOR(pcop)->r == NULL)
1408       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1409       return pcop;
1410         
1411     case AOP_LIT:
1412       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1413
1414     case AOP_STR:
1415       DEBUGpic16_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1416       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1417       /*
1418       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1419       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1420       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1421       pcop->type = PCOR(pcop)->r->pc_type;
1422       pcop->name = PCOR(pcop)->r->name;
1423
1424       return pcop;
1425       */
1426
1427     case AOP_PCODE:
1428       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1429                           __LINE__, 
1430                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1431       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1432       PCOI(pcop)->offset = offset;
1433       return pcop;
1434     }
1435
1436     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1437            "pic16_popGet got unsupported aop->type");
1438     exit(0);
1439 }
1440 /*-----------------------------------------------------------------*/
1441 /* pic16_aopPut - puts a string for a aop                                */
1442 /*-----------------------------------------------------------------*/
1443 void pic16_aopPut (asmop *aop, char *s, int offset)
1444 {
1445     char *d = buffer ;
1446     symbol *lbl ;
1447
1448     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1449
1450     if (aop->size && offset > ( aop->size - 1)) {
1451         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1452                "pic16_aopPut got offset > aop->size");
1453         exit(0);
1454     }
1455
1456     /* will assign value to value */
1457     /* depending on where it is ofcourse */
1458     switch (aop->type) {
1459     case AOP_DIR:
1460       if (offset) {
1461         sprintf(d,"(%s + %d)",
1462                 aop->aopu.aop_dir,offset);
1463         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1464
1465       } else
1466             sprintf(d,"%s",aop->aopu.aop_dir);
1467         
1468         if (strcmp(d,s)) {
1469           DEBUGpic16_emitcode(";","%d",__LINE__);
1470           if(strcmp(s,"W"))
1471             pic16_emitcode("movf","%s,w",s);
1472           pic16_emitcode("movwf","%s",d);
1473
1474           if(strcmp(s,"W")) {
1475             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1476             if(offset >= aop->size) {
1477               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1478               break;
1479             } else
1480               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1481           }
1482
1483           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1484
1485
1486         }
1487         break;
1488         
1489     case AOP_REG:
1490       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1491         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1492           /*
1493             if (*s == '@'           ||
1494                 strcmp(s,"r0") == 0 ||
1495                 strcmp(s,"r1") == 0 ||
1496                 strcmp(s,"r2") == 0 ||
1497                 strcmp(s,"r3") == 0 ||
1498                 strcmp(s,"r4") == 0 ||
1499                 strcmp(s,"r5") == 0 ||
1500                 strcmp(s,"r6") == 0 || 
1501                 strcmp(s,"r7") == 0 )
1502                 pic16_emitcode("mov","%s,%s  ; %d",
1503                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1504             else
1505           */
1506
1507           if(strcmp(s,"W")==0 )
1508             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1509
1510           pic16_emitcode("movwf","%s",
1511                    aop->aopu.aop_reg[offset]->name);
1512
1513           if(strcmp(s,zero)==0) {
1514             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1515
1516           } else if(strcmp(s,"W")==0) {
1517             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1518             pcop->type = PO_GPR_REGISTER;
1519
1520             PCOR(pcop)->rIdx = -1;
1521             PCOR(pcop)->r = NULL;
1522
1523             DEBUGpic16_emitcode(";","%d",__LINE__);
1524             pcop->name = Safe_strdup(s);
1525             pic16_emitpcode(POC_MOVFW,pcop);
1526             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1527           } else if(strcmp(s,one)==0) {
1528             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1529             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1530           } else {
1531             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1532           }
1533         }
1534         break;
1535         
1536     case AOP_DPTR:
1537     case AOP_DPTR2:
1538     
1539     if (aop->type == AOP_DPTR2)
1540     {
1541         genSetDPTR(1);
1542     }
1543     
1544         if (aop->code) {
1545             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1546                    "pic16_aopPut writting to code space");
1547             exit(0);
1548         }
1549         
1550         while (offset > aop->coff) {
1551             aop->coff++;
1552             pic16_emitcode ("inc","dptr");
1553         }
1554         
1555         while (offset < aop->coff) {
1556             aop->coff-- ;
1557             pic16_emitcode("lcall","__decdptr");
1558         }
1559         
1560         aop->coff = offset;
1561         
1562         /* if not in accumulater */
1563         MOVA(s);        
1564         
1565         pic16_emitcode ("movx","@dptr,a");
1566         
1567     if (aop->type == AOP_DPTR2)
1568     {
1569         genSetDPTR(0);
1570     }
1571         break;
1572         
1573     case AOP_R0:
1574     case AOP_R1:
1575         while (offset > aop->coff) {
1576             aop->coff++;
1577             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1578         }
1579         while (offset < aop->coff) {
1580             aop->coff-- ;
1581             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1582         }
1583         aop->coff = offset;
1584         
1585         if (aop->paged) {
1586             MOVA(s);           
1587             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1588             
1589         } else
1590             if (*s == '@') {
1591                 MOVA(s);
1592                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1593             } else
1594                 if (strcmp(s,"r0") == 0 ||
1595                     strcmp(s,"r1") == 0 ||
1596                     strcmp(s,"r2") == 0 ||
1597                     strcmp(s,"r3") == 0 ||
1598                     strcmp(s,"r4") == 0 ||
1599                     strcmp(s,"r5") == 0 ||
1600                     strcmp(s,"r6") == 0 || 
1601                     strcmp(s,"r7") == 0 ) {
1602                     char buffer[10];
1603                     sprintf(buffer,"a%s",s);
1604                     pic16_emitcode("mov","@%s,%s",
1605                              aop->aopu.aop_ptr->name,buffer);
1606                 } else
1607                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1608         
1609         break;
1610         
1611     case AOP_STK:
1612         if (strcmp(s,"a") == 0)
1613             pic16_emitcode("push","acc");
1614         else
1615             pic16_emitcode("push","%s",s);
1616         
1617         break;
1618         
1619     case AOP_CRY:
1620         /* if bit variable */
1621         if (!aop->aopu.aop_dir) {
1622             pic16_emitcode("clr","a");
1623             pic16_emitcode("rlc","a");
1624         } else {
1625             if (s == zero) 
1626                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1627             else
1628                 if (s == one)
1629                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1630                 else
1631                     if (!strcmp(s,"c"))
1632                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1633                     else {
1634                         lbl = newiTempLabel(NULL);
1635                         
1636                         if (strcmp(s,"a")) {
1637                             MOVA(s);
1638                         }
1639                         pic16_emitcode("clr","c");
1640                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1641                         pic16_emitcode("cpl","c");
1642                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1643                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1644                     }
1645         }
1646         break;
1647         
1648     case AOP_STR:
1649         aop->coff = offset;
1650         if (strcmp(aop->aopu.aop_str[offset],s))
1651             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1652         break;
1653         
1654     case AOP_ACC:
1655         aop->coff = offset;
1656         if (!offset && (strcmp(s,"acc") == 0))
1657             break;
1658         
1659         if (strcmp(aop->aopu.aop_str[offset],s))
1660             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1661         break;
1662
1663     default :
1664         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1665                "pic16_aopPut got unsupported aop->type");
1666         exit(0);    
1667     }    
1668
1669 }
1670
1671 /*-----------------------------------------------------------------*/
1672 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1673 /*-----------------------------------------------------------------*/
1674 static void mov2w (asmop *aop, int offset)
1675 {
1676
1677   if(!aop)
1678     return;
1679
1680   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1681
1682   if ( aop->type == AOP_PCODE ||
1683        aop->type == AOP_LIT )
1684     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1685   else
1686     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1687
1688 }
1689
1690 /*-----------------------------------------------------------------*/
1691 /* reAdjustPreg - points a register back to where it should        */
1692 /*-----------------------------------------------------------------*/
1693 static void reAdjustPreg (asmop *aop)
1694 {
1695     int size ;
1696
1697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1698     aop->coff = 0;
1699     if ((size = aop->size) <= 1)
1700         return ;
1701     size-- ;
1702     switch (aop->type) {
1703         case AOP_R0 :
1704         case AOP_R1 :
1705             while (size--)
1706                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1707             break;          
1708         case AOP_DPTR :
1709         case AOP_DPTR2:
1710             if (aop->type == AOP_DPTR2)
1711             {
1712                 genSetDPTR(1);
1713             } 
1714             while (size--)
1715             {
1716                 pic16_emitcode("lcall","__decdptr");
1717             }
1718                 
1719             if (aop->type == AOP_DPTR2)
1720             {
1721                 genSetDPTR(0);
1722             }                
1723             break;  
1724
1725     }   
1726
1727 }
1728
1729 /*-----------------------------------------------------------------*/
1730 /* genNotFloat - generates not for float operations              */
1731 /*-----------------------------------------------------------------*/
1732 static void genNotFloat (operand *op, operand *res)
1733 {
1734     int size, offset;
1735     char *l;
1736     symbol *tlbl ;
1737
1738     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1739     /* we will put 127 in the first byte of 
1740     the result */
1741     pic16_aopPut(AOP(res),"#127",0);
1742     size = AOP_SIZE(op) - 1;
1743     offset = 1;
1744
1745     l = pic16_aopGet(op->aop,offset++,FALSE,FALSE);
1746     MOVA(l);    
1747
1748     while(size--) {
1749         pic16_emitcode("orl","a,%s",
1750                  pic16_aopGet(op->aop,
1751                         offset++,FALSE,FALSE));
1752     }
1753     tlbl = newiTempLabel(NULL);
1754
1755     tlbl = newiTempLabel(NULL);
1756     pic16_aopPut(res->aop,one,1);
1757     pic16_emitcode("jz","%05d_DS_",(tlbl->key+100));
1758     pic16_aopPut(res->aop,zero,1);
1759     pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
1760
1761     size = res->aop->size - 2;
1762     offset = 2;    
1763     /* put zeros in the rest */
1764     while (size--) 
1765         pic16_aopPut(res->aop,zero,offset++);
1766 }
1767
1768 #if 0
1769 /*-----------------------------------------------------------------*/
1770 /* opIsGptr: returns non-zero if the passed operand is             */   
1771 /* a generic pointer type.                                         */
1772 /*-----------------------------------------------------------------*/ 
1773 static int opIsGptr(operand *op)
1774 {
1775     sym_link *type = operandType(op);
1776     
1777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1778     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1779     {
1780         return 1;
1781     }
1782     return 0;        
1783 }
1784 #endif
1785
1786 /*-----------------------------------------------------------------*/
1787 /* pic16_getDataSize - get the operand data size                         */
1788 /*-----------------------------------------------------------------*/
1789 int pic16_getDataSize(operand *op)
1790 {
1791     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1792
1793
1794     return AOP_SIZE(op);
1795
1796     // tsd- in the pic port, the genptr size is 1, so this code here
1797     // fails. ( in the 8051 port, the size was 4).
1798 #if 0
1799     int size;
1800     size = AOP_SIZE(op);
1801     if (size == GPTRSIZE)
1802     {
1803         sym_link *type = operandType(op);
1804         if (IS_GENPTR(type))
1805         {
1806             /* generic pointer; arithmetic operations
1807              * should ignore the high byte (pointer type).
1808              */
1809             size--;
1810     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1811         }
1812     }
1813     return size;
1814 #endif
1815 }
1816
1817 /*-----------------------------------------------------------------*/
1818 /* pic16_outAcc - output Acc                                             */
1819 /*-----------------------------------------------------------------*/
1820 void pic16_outAcc(operand *result)
1821 {
1822   int size,offset;
1823   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1824   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1825
1826
1827   size = pic16_getDataSize(result);
1828   if(size){
1829     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1830     size--;
1831     offset = 1;
1832     /* unsigned or positive */
1833     while(size--)
1834       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1835   }
1836
1837 }
1838
1839 /*-----------------------------------------------------------------*/
1840 /* pic16_outBitC - output a bit C                                        */
1841 /*-----------------------------------------------------------------*/
1842 void pic16_outBitC(operand *result)
1843 {
1844
1845     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1846     /* if the result is bit */
1847     if (AOP_TYPE(result) == AOP_CRY) 
1848         pic16_aopPut(AOP(result),"c",0);
1849     else {
1850         pic16_emitcode("clr","a  ; %d", __LINE__);
1851         pic16_emitcode("rlc","a");
1852         pic16_outAcc(result);
1853     }
1854 }
1855
1856 /*-----------------------------------------------------------------*/
1857 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1858 /*-----------------------------------------------------------------*/
1859 void pic16_toBoolean(operand *oper)
1860 {
1861     int size = AOP_SIZE(oper) - 1;
1862     int offset = 1;
1863
1864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1865
1866     if ( AOP_TYPE(oper) != AOP_ACC) {
1867       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1868     }
1869     while (size--) {
1870       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1871     }
1872 }
1873
1874
1875 /*-----------------------------------------------------------------*/
1876 /* genNot - generate code for ! operation                          */
1877 /*-----------------------------------------------------------------*/
1878 static void genNot (iCode *ic)
1879 {
1880   symbol *tlbl;
1881   sym_link *optype = operandType(IC_LEFT(ic));
1882   int size;
1883
1884   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1885   /* assign asmOps to operand & result */
1886   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1887   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1888
1889   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1890   /* if in bit space then a special case */
1891   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1892     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1893       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1894       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1895     } else {
1896       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1897       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1898       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1899     }
1900     goto release;
1901   }
1902
1903   /* if type float then do float */
1904   if (IS_FLOAT(optype)) {
1905     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1906     goto release;
1907   }
1908
1909   size = AOP_SIZE(IC_RESULT(ic));
1910   if(size == 1) {
1911     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1912     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1913     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1914     goto release;
1915   }
1916   pic16_toBoolean(IC_LEFT(ic));
1917
1918   tlbl = newiTempLabel(NULL);
1919   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1920   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1921   pic16_outBitC(IC_RESULT(ic));
1922
1923  release:    
1924   /* release the aops */
1925   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1926   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1927 }
1928
1929
1930 /*-----------------------------------------------------------------*/
1931 /* genCpl - generate code for complement                           */
1932 /*-----------------------------------------------------------------*/
1933 static void genCpl (iCode *ic)
1934 {
1935     int offset = 0;
1936     int size ;
1937
1938
1939     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1940     /* assign asmOps to operand & result */
1941     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1942     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1943
1944     /* if both are in bit space then 
1945     a special case */
1946     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1947         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1948
1949         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1950         pic16_emitcode("cpl","c"); 
1951         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1952         goto release; 
1953     } 
1954
1955     size = AOP_SIZE(IC_RESULT(ic));
1956     while (size--) {
1957 /*
1958         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1959         MOVA(l);       
1960         pic16_emitcode("cpl","a");
1961         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1962 */
1963         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1964               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
1965         } else {
1966                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
1967                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1968         }
1969         offset++;
1970
1971     }
1972
1973
1974 release:
1975     /* release the aops */
1976     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1977     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1978 }
1979
1980 /*-----------------------------------------------------------------*/
1981 /* genUminusFloat - unary minus for floating points                */
1982 /*-----------------------------------------------------------------*/
1983 static void genUminusFloat(operand *op,operand *result)
1984 {
1985     int size ,offset =0 ;
1986     char *l;
1987
1988     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1989     /* for this we just need to flip the 
1990     first it then copy the rest in place */
1991     size = AOP_SIZE(op) - 1;
1992     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
1993
1994     MOVA(l);    
1995
1996     pic16_emitcode("cpl","acc.7");
1997     pic16_aopPut(AOP(result),"a",3);    
1998
1999     while(size--) {
2000         pic16_aopPut(AOP(result),
2001                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2002                offset);
2003         offset++;
2004     }          
2005 }
2006
2007 /*-----------------------------------------------------------------*/
2008 /* genUminus - unary minus code generation                         */
2009 /*-----------------------------------------------------------------*/
2010 static void genUminus (iCode *ic)
2011 {
2012   int size, i;
2013   sym_link *optype, *rtype;
2014
2015
2016   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2017   /* assign asmops */
2018   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2019   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2020
2021   /* if both in bit space then special
2022      case */
2023   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2024       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2025
2026     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2027     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2028     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2029
2030     goto release; 
2031   } 
2032
2033   optype = operandType(IC_LEFT(ic));
2034   rtype = operandType(IC_RESULT(ic));
2035
2036   /* if float then do float stuff */
2037   if (IS_FLOAT(optype)) {
2038     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2039     goto release;
2040   }
2041
2042   /* otherwise subtract from zero by taking the 2's complement */
2043   size = AOP_SIZE(IC_LEFT(ic));
2044
2045   for(i=0; i<size; i++) {
2046     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2047       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2048     else {
2049       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2050       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2051     }
2052   }
2053
2054   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2055   for(i=1; i<size; i++) {
2056     emitSKPNZ;
2057     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2058   }
2059
2060  release:
2061   /* release the aops */
2062   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2063   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2064 }
2065
2066 /*-----------------------------------------------------------------*/
2067 /* saveRegisters - will look for a call and save the registers     */
2068 /*-----------------------------------------------------------------*/
2069 static void saveRegisters(iCode *lic) 
2070 {
2071     int i;
2072     iCode *ic;
2073     bitVect *rsave;
2074     sym_link *dtype;
2075
2076     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2077     /* look for call */
2078     for (ic = lic ; ic ; ic = ic->next) 
2079         if (ic->op == CALL || ic->op == PCALL)
2080             break;
2081
2082     if (!ic) {
2083         fprintf(stderr,"found parameter push with no function call\n");
2084         return ;
2085     }
2086
2087     /* if the registers have been saved already then
2088     do nothing */
2089     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2090         return ;
2091
2092     /* find the registers in use at this time 
2093     and push them away to safety */
2094     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2095                           ic->rUsed);
2096
2097     ic->regsSaved = 1;
2098     if (options.useXstack) {
2099         if (bitVectBitValue(rsave,R0_IDX))
2100             pic16_emitcode("mov","b,r0");
2101         pic16_emitcode("mov","r0,%s",spname);
2102         for (i = 0 ; i < pic16_nRegs ; i++) {
2103             if (bitVectBitValue(rsave,i)) {
2104                 if (i == R0_IDX)
2105                     pic16_emitcode("mov","a,b");
2106                 else
2107                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2108                 pic16_emitcode("movx","@r0,a");
2109                 pic16_emitcode("inc","r0");
2110             }
2111         }
2112         pic16_emitcode("mov","%s,r0",spname);
2113         if (bitVectBitValue(rsave,R0_IDX))
2114             pic16_emitcode("mov","r0,b");           
2115     }// else
2116     //for (i = 0 ; i < pic16_nRegs ; i++) {
2117     //    if (bitVectBitValue(rsave,i))
2118     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2119     //}
2120
2121     dtype = operandType(IC_LEFT(ic));
2122     if (currFunc && dtype && 
2123         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2124         IFFUNC_ISISR(currFunc->type) &&
2125         !ic->bankSaved) 
2126
2127         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2128
2129 }
2130 /*-----------------------------------------------------------------*/
2131 /* unsaveRegisters - pop the pushed registers                      */
2132 /*-----------------------------------------------------------------*/
2133 static void unsaveRegisters (iCode *ic)
2134 {
2135     int i;
2136     bitVect *rsave;
2137
2138     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2139     /* find the registers in use at this time 
2140     and push them away to safety */
2141     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2142                           ic->rUsed);
2143     
2144     if (options.useXstack) {
2145         pic16_emitcode("mov","r0,%s",spname);   
2146         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2147             if (bitVectBitValue(rsave,i)) {
2148                 pic16_emitcode("dec","r0");
2149                 pic16_emitcode("movx","a,@r0");
2150                 if (i == R0_IDX)
2151                     pic16_emitcode("mov","b,a");
2152                 else
2153                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2154             }       
2155
2156         }
2157         pic16_emitcode("mov","%s,r0",spname);
2158         if (bitVectBitValue(rsave,R0_IDX))
2159             pic16_emitcode("mov","r0,b");
2160     } //else
2161     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2162     //    if (bitVectBitValue(rsave,i))
2163     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2164     //}
2165
2166 }  
2167
2168
2169 /*-----------------------------------------------------------------*/
2170 /* pushSide -                                                      */
2171 /*-----------------------------------------------------------------*/
2172 static void pushSide(operand * oper, int size)
2173 {
2174 #if 0
2175         int offset = 0;
2176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2177         while (size--) {
2178                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2179                 if (AOP_TYPE(oper) != AOP_REG &&
2180                     AOP_TYPE(oper) != AOP_DIR &&
2181                     strcmp(l,"a") ) {
2182                         pic16_emitcode("mov","a,%s",l);
2183                         pic16_emitcode("push","acc");
2184                 } else
2185                         pic16_emitcode("push","%s",l);
2186         }
2187 #endif
2188 }
2189
2190 /*-----------------------------------------------------------------*/
2191 /* assignResultValue -                                             */
2192 /*-----------------------------------------------------------------*/
2193 static void assignResultValue(operand * oper)
2194 {
2195   int size = AOP_SIZE(oper);
2196
2197   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2198
2199   DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2200
2201   if(!GpsuedoStkPtr) {
2202     /* The last byte in the assignment is in W */
2203     size--;
2204     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2205     GpsuedoStkPtr++;
2206   }
2207
2208   while (size--) {
2209     pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2210     GpsuedoStkPtr++;
2211     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2212   }
2213 }
2214
2215
2216 /*-----------------------------------------------------------------*/
2217 /* genIpush - genrate code for pushing this gets a little complex  */
2218 /*-----------------------------------------------------------------*/
2219 static void genIpush (iCode *ic)
2220 {
2221
2222   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2223 #if 0
2224     int size, offset = 0 ;
2225     char *l;
2226
2227
2228     /* if this is not a parm push : ie. it is spill push 
2229     and spill push is always done on the local stack */
2230     if (!ic->parmPush) {
2231
2232         /* and the item is spilt then do nothing */
2233         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2234             return ;
2235
2236         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2237         size = AOP_SIZE(IC_LEFT(ic));
2238         /* push it on the stack */
2239         while(size--) {
2240             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2241             if (*l == '#') {
2242                 MOVA(l);
2243                 l = "acc";
2244             }
2245             pic16_emitcode("push","%s",l);
2246         }
2247         return ;        
2248     }
2249
2250     /* this is a paramter push: in this case we call
2251     the routine to find the call and save those
2252     registers that need to be saved */   
2253     saveRegisters(ic);
2254
2255     /* then do the push */
2256     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2257
2258
2259         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2260     size = AOP_SIZE(IC_LEFT(ic));
2261
2262     while (size--) {
2263         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2264         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2265             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2266             strcmp(l,"a") ) {
2267             pic16_emitcode("mov","a,%s",l);
2268             pic16_emitcode("push","acc");
2269         } else
2270             pic16_emitcode("push","%s",l);
2271     }       
2272
2273     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2274 #endif
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* genIpop - recover the registers: can happen only for spilling   */
2279 /*-----------------------------------------------------------------*/
2280 static void genIpop (iCode *ic)
2281 {
2282   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2283 #if 0
2284     int size,offset ;
2285
2286
2287     /* if the temp was not pushed then */
2288     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2289         return ;
2290
2291     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2292     size = AOP_SIZE(IC_LEFT(ic));
2293     offset = (size-1);
2294     while (size--) 
2295         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2296                                    FALSE,TRUE));
2297
2298     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2299 #endif
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* unsaverbank - restores the resgister bank from stack            */
2304 /*-----------------------------------------------------------------*/
2305 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2306 {
2307   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2308 #if 0
2309     int i;
2310     asmop *aop ;
2311     regs *r = NULL;
2312
2313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2314     if (popPsw) {
2315         if (options.useXstack) {
2316             aop = newAsmop(0);
2317             r = getFreePtr(ic,&aop,FALSE);
2318             
2319             
2320             pic16_emitcode("mov","%s,_spx",r->name);
2321             pic16_emitcode("movx","a,@%s",r->name);
2322             pic16_emitcode("mov","psw,a");
2323             pic16_emitcode("dec","%s",r->name);
2324             
2325         }else
2326             pic16_emitcode ("pop","psw");
2327     }
2328
2329     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2330         if (options.useXstack) {       
2331             pic16_emitcode("movx","a,@%s",r->name);
2332             //pic16_emitcode("mov","(%s+%d),a",
2333             //       regspic16[i].base,8*bank+regspic16[i].offset);
2334             pic16_emitcode("dec","%s",r->name);
2335
2336         } else 
2337           pic16_emitcode("pop",""); //"(%s+%d)",
2338         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2339     }
2340
2341     if (options.useXstack) {
2342
2343         pic16_emitcode("mov","_spx,%s",r->name);
2344         pic16_freeAsmop(NULL,aop,ic,TRUE);
2345
2346     }
2347 #endif 
2348 }
2349
2350 /*-----------------------------------------------------------------*/
2351 /* saverbank - saves an entire register bank on the stack          */
2352 /*-----------------------------------------------------------------*/
2353 static void saverbank (int bank, iCode *ic, bool pushPsw)
2354 {
2355   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2356 #if 0
2357     int i;
2358     asmop *aop ;
2359     regs *r = NULL;
2360
2361     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2362     if (options.useXstack) {
2363
2364         aop = newAsmop(0);
2365         r = getFreePtr(ic,&aop,FALSE);  
2366         pic16_emitcode("mov","%s,_spx",r->name);
2367
2368     }
2369
2370     for (i = 0 ; i < pic16_nRegs ;i++) {
2371         if (options.useXstack) {
2372             pic16_emitcode("inc","%s",r->name);
2373             //pic16_emitcode("mov","a,(%s+%d)",
2374             //         regspic16[i].base,8*bank+regspic16[i].offset);
2375             pic16_emitcode("movx","@%s,a",r->name);           
2376         } else 
2377           pic16_emitcode("push","");// "(%s+%d)",
2378                      //regspic16[i].base,8*bank+regspic16[i].offset);
2379     }
2380     
2381     if (pushPsw) {
2382         if (options.useXstack) {
2383             pic16_emitcode("mov","a,psw");
2384             pic16_emitcode("movx","@%s,a",r->name);     
2385             pic16_emitcode("inc","%s",r->name);
2386             pic16_emitcode("mov","_spx,%s",r->name);       
2387             pic16_freeAsmop (NULL,aop,ic,TRUE);
2388             
2389         } else
2390             pic16_emitcode("push","psw");
2391         
2392         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2393     }
2394     ic->bankSaved = 1;
2395 #endif
2396 }
2397
2398 /*-----------------------------------------------------------------*/
2399 /* genCall - generates a call statement                            */
2400 /*-----------------------------------------------------------------*/
2401 static void genCall (iCode *ic)
2402 {
2403   sym_link *dtype;   
2404
2405   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406
2407   /* if caller saves & we have not saved then */
2408   if (!ic->regsSaved)
2409     saveRegisters(ic);
2410
2411   /* if we are calling a function that is not using
2412      the same register bank then we need to save the
2413      destination registers on the stack */
2414   dtype = operandType(IC_LEFT(ic));
2415   if (currFunc && dtype && 
2416       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2417       IFFUNC_ISISR(currFunc->type) &&
2418       !ic->bankSaved) 
2419
2420     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2421
2422   /* if send set is not empty the assign */
2423   if (_G.sendSet) {
2424     iCode *sic;
2425     /* For the Pic port, there is no data stack.
2426      * So parameters passed to functions are stored
2427      * in registers. (The pCode optimizer will get
2428      * rid of most of these :).
2429      */
2430     int psuedoStkPtr=-1; 
2431     int firstTimeThruLoop = 1;
2432
2433     _G.sendSet = reverseSet(_G.sendSet);
2434
2435     /* First figure how many parameters are getting passed */
2436     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2437          sic = setNextItem(_G.sendSet)) {
2438
2439       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2440       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2441       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2442     }
2443
2444     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2445          sic = setNextItem(_G.sendSet)) {
2446       int size, offset = 0;
2447
2448       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2449       size = AOP_SIZE(IC_LEFT(sic));
2450
2451       while (size--) {
2452         DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2453                              pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2454
2455         if(!firstTimeThruLoop) {
2456           /* If this is not the first time we've been through the loop
2457            * then we need to save the parameter in a temporary
2458            * register. The last byte of the last parameter is
2459            * passed in W. */
2460           pic16_emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2461
2462         }
2463         firstTimeThruLoop=0;
2464
2465         //if (strcmp(l,fReturn[offset])) {
2466         mov2w (AOP(IC_LEFT(sic)),  offset);
2467 /*
2468         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2469              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2470           pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2471         else
2472           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2473 */
2474         //}
2475         offset++;
2476       }
2477       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2478     }
2479     _G.sendSet = NULL;
2480   }
2481   /* make the call */
2482   pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2483                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2484                                       OP_SYMBOL(IC_LEFT(ic))->name));
2485
2486   GpsuedoStkPtr=0;
2487   /* if we need assign a result value */
2488   if ((IS_ITEMP(IC_RESULT(ic)) && 
2489        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2490         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2491       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2492
2493     _G.accInUse++;
2494     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2495     _G.accInUse--;
2496
2497     assignResultValue(IC_RESULT(ic));
2498
2499     DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2500                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2501                 
2502     pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2503   }
2504
2505   /* adjust the stack for parameters if 
2506      required */
2507   if (ic->parmBytes) {
2508     int i;
2509     if (ic->parmBytes > 3) {
2510       pic16_emitcode("mov","a,%s",spname);
2511       pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2512       pic16_emitcode("mov","%s,a",spname);
2513     } else 
2514       for ( i = 0 ; i <  ic->parmBytes ;i++)
2515         pic16_emitcode("dec","%s",spname);
2516
2517   }
2518
2519   /* if register bank was saved then pop them */
2520   if (ic->bankSaved)
2521     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2522
2523   /* if we hade saved some registers then unsave them */
2524   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2525     unsaveRegisters (ic);
2526
2527
2528 }
2529
2530 /*-----------------------------------------------------------------*/
2531 /* genPcall - generates a call by pointer statement                */
2532 /*-----------------------------------------------------------------*/
2533 static void genPcall (iCode *ic)
2534 {
2535     sym_link *dtype;
2536     symbol *rlbl = newiTempLabel(NULL);
2537
2538
2539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2540     /* if caller saves & we have not saved then */
2541     if (!ic->regsSaved)
2542         saveRegisters(ic);
2543
2544     /* if we are calling a function that is not using
2545     the same register bank then we need to save the
2546     destination registers on the stack */
2547     dtype = operandType(IC_LEFT(ic));
2548     if (currFunc && dtype && 
2549         IFFUNC_ISISR(currFunc->type) &&
2550         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2551         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2552
2553
2554     /* push the return address on to the stack */
2555     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2556     pic16_emitcode("push","acc");    
2557     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2558     pic16_emitcode("push","acc");
2559     
2560     if (options.model == MODEL_FLAT24)
2561     {
2562         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2563         pic16_emitcode("push","acc");    
2564     }
2565
2566     /* now push the calling address */
2567     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2568
2569     pushSide(IC_LEFT(ic), FPTRSIZE);
2570
2571     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2572
2573     /* if send set is not empty the assign */
2574     if (_G.sendSet) {
2575         iCode *sic ;
2576
2577         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2578              sic = setNextItem(_G.sendSet)) {
2579             int size, offset = 0;
2580             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2581             size = AOP_SIZE(IC_LEFT(sic));
2582             while (size--) {
2583                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2584                                 FALSE,FALSE);
2585                 if (strcmp(l,fReturn[offset]))
2586                     pic16_emitcode("mov","%s,%s",
2587                              fReturn[offset],
2588                              l);
2589                 offset++;
2590             }
2591             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2592         }
2593         _G.sendSet = NULL;
2594     }
2595
2596     pic16_emitcode("ret","");
2597     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2598
2599
2600     /* if we need assign a result value */
2601     if ((IS_ITEMP(IC_RESULT(ic)) &&
2602          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2603           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2604         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2605
2606         _G.accInUse++;
2607         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2608         _G.accInUse--;
2609         
2610         assignResultValue(IC_RESULT(ic));
2611
2612         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2613     }
2614
2615     /* adjust the stack for parameters if 
2616     required */
2617     if (ic->parmBytes) {
2618         int i;
2619         if (ic->parmBytes > 3) {
2620             pic16_emitcode("mov","a,%s",spname);
2621             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2622             pic16_emitcode("mov","%s,a",spname);
2623         } else 
2624             for ( i = 0 ; i <  ic->parmBytes ;i++)
2625                 pic16_emitcode("dec","%s",spname);
2626
2627     }
2628
2629     /* if register bank was saved then unsave them */
2630     if (currFunc && dtype && 
2631         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2632         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2633
2634     /* if we hade saved some registers then
2635     unsave them */
2636     if (ic->regsSaved)
2637         unsaveRegisters (ic);
2638
2639 }
2640
2641 /*-----------------------------------------------------------------*/
2642 /* resultRemat - result  is rematerializable                       */
2643 /*-----------------------------------------------------------------*/
2644 static int resultRemat (iCode *ic)
2645 {
2646   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647   if (SKIP_IC(ic) || ic->op == IFX)
2648     return 0;
2649
2650   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2651     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2652     if (sym->remat && !POINTER_SET(ic)) 
2653       return 1;
2654   }
2655
2656   return 0;
2657 }
2658
2659 #if defined(__BORLANDC__) || defined(_MSC_VER)
2660 #define STRCASECMP stricmp
2661 #else
2662 #define STRCASECMP strcasecmp
2663 #endif
2664
2665 #if 0
2666 /*-----------------------------------------------------------------*/
2667 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2668 /*-----------------------------------------------------------------*/
2669 static bool inExcludeList(char *s)
2670 {
2671   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2672     int i =0;
2673     
2674     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2675     if (options.excludeRegs[i] &&
2676     STRCASECMP(options.excludeRegs[i],"none") == 0)
2677         return FALSE ;
2678
2679     for ( i = 0 ; options.excludeRegs[i]; i++) {
2680         if (options.excludeRegs[i] &&
2681         STRCASECMP(s,options.excludeRegs[i]) == 0)
2682             return TRUE;
2683     }
2684     return FALSE ;
2685 }
2686 #endif
2687
2688 /*-----------------------------------------------------------------*/
2689 /* genFunction - generated code for function entry                 */
2690 /*-----------------------------------------------------------------*/
2691 static void genFunction (iCode *ic)
2692 {
2693     symbol *sym;
2694     sym_link *ftype;
2695
2696     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2697
2698     labelOffset += (max_key+4);
2699     max_key=0;
2700     GpsuedoStkPtr=0;
2701     _G.nRegsSaved = 0;
2702     /* create the function header */
2703     pic16_emitcode(";","-----------------------------------------");
2704     pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2705     pic16_emitcode(";","-----------------------------------------");
2706
2707     pic16_emitcode("","%s:",sym->rname);
2708     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,sym->rname));
2709
2710     ftype = operandType(IC_LEFT(ic));
2711
2712     /* if critical function then turn interrupts off */
2713     if (IFFUNC_ISCRITICAL(ftype))
2714         pic16_emitcode("clr","ea");
2715
2716     /* here we need to generate the equates for the
2717        register bank if required */
2718 #if 0
2719     if (FUNC_REGBANK(ftype) != rbank) {
2720         int i ;
2721
2722         rbank = FUNC_REGBANK(ftype);
2723         for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2724             if (strcmp(regspic16[i].base,"0") == 0)
2725                 pic16_emitcode("","%s = 0x%02x",
2726                          regspic16[i].dname,
2727                          8*rbank+regspic16[i].offset);
2728             else
2729                 pic16_emitcode ("","%s = %s + 0x%02x",
2730                           regspic16[i].dname,
2731                           regspic16[i].base,
2732                           8*rbank+regspic16[i].offset);
2733         }
2734     }
2735 #endif
2736
2737     /* if this is an interrupt service routine then
2738     save acc, b, dpl, dph  */
2739     if (IFFUNC_ISISR(sym->type)) {
2740       pic16_addpCode2pBlock(pb,pic16_newpCode(POC_BRA,pic16_newpCodeOp("END_OF_INTERRUPT+2",PO_STR)));
2741       pic16_emitpcodeNULLop(POC_NOP);
2742       pic16_emitpcodeNULLop(POC_NOP);
2743       pic16_emitpcodeNULLop(POC_NOP);
2744       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2745       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2746       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2747       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2748
2749       pic16_pBlockConvert2ISR(pb);
2750 #if 0  
2751         if (!inExcludeList("acc"))          
2752             pic16_emitcode ("push","acc");      
2753         if (!inExcludeList("b"))
2754             pic16_emitcode ("push","b");
2755         if (!inExcludeList("dpl"))
2756             pic16_emitcode ("push","dpl");
2757         if (!inExcludeList("dph"))
2758             pic16_emitcode ("push","dph");
2759         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2760         {
2761             pic16_emitcode ("push", "dpx");
2762             /* Make sure we're using standard DPTR */
2763             pic16_emitcode ("push", "dps");
2764             pic16_emitcode ("mov", "dps, #0x00");
2765             if (options.stack10bit)
2766             {   
2767                 /* This ISR could conceivably use DPTR2. Better save it. */
2768                 pic16_emitcode ("push", "dpl1");
2769                 pic16_emitcode ("push", "dph1");
2770                 pic16_emitcode ("push", "dpx1");
2771             }
2772         }
2773         /* if this isr has no bank i.e. is going to
2774            run with bank 0 , then we need to save more
2775            registers :-) */
2776         if (!FUNC_REGBANK(sym->type)) {
2777
2778             /* if this function does not call any other
2779                function then we can be economical and
2780                save only those registers that are used */
2781             if (! IFFUNC_HASFCALL(sym->type)) {
2782                 int i;
2783
2784                 /* if any registers used */
2785                 if (sym->regsUsed) {
2786                     /* save the registers used */
2787                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2788                         if (bitVectBitValue(sym->regsUsed,i) ||
2789                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2790                           pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                         
2791                     }
2792                 }
2793                 
2794             } else {
2795                 /* this function has  a function call cannot
2796                    determines register usage so we will have the
2797                    entire bank */
2798                 saverbank(0,ic,FALSE);
2799             }       
2800         }
2801 #endif
2802     } else {
2803         /* if callee-save to be used for this function
2804            then save the registers being used in this function */
2805         if (IFFUNC_CALLEESAVES(sym->type)) {
2806             int i;
2807             
2808             /* if any registers used */
2809             if (sym->regsUsed) {
2810                 /* save the registers used */
2811                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2812                     if (bitVectBitValue(sym->regsUsed,i) ||
2813                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2814                       //pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2815                         _G.nRegsSaved++;
2816                     }
2817                 }
2818             }
2819         }
2820     }
2821
2822     /* set the register bank to the desired value */
2823     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2824         pic16_emitcode("push","psw");
2825         pic16_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2826     }
2827
2828     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2829
2830         if (options.useXstack) {
2831             pic16_emitcode("mov","r0,%s",spname);
2832             pic16_emitcode("mov","a,_bp");
2833             pic16_emitcode("movx","@r0,a");
2834             pic16_emitcode("inc","%s",spname);
2835         }
2836         else
2837         {
2838             /* set up the stack */
2839             pic16_emitcode ("push","_bp");     /* save the callers stack  */
2840         }
2841         pic16_emitcode ("mov","_bp,%s",spname);
2842     }
2843
2844     /* adjust the stack for the function */
2845     if (sym->stack) {
2846
2847         int i = sym->stack;
2848         if (i > 256 ) 
2849             werror(W_STACK_OVERFLOW,sym->name);
2850
2851         if (i > 3 && sym->recvSize < 4) {              
2852
2853             pic16_emitcode ("mov","a,sp");
2854             pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2855             pic16_emitcode ("mov","sp,a");
2856            
2857         }
2858         else
2859             while(i--)
2860                 pic16_emitcode("inc","sp");
2861     }
2862
2863      if (sym->xstack) {
2864
2865         pic16_emitcode ("mov","a,_spx");
2866         pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2867         pic16_emitcode ("mov","_spx,a");
2868     }    
2869
2870 }
2871
2872 /*-----------------------------------------------------------------*/
2873 /* genEndFunction - generates epilogue for functions               */
2874 /*-----------------------------------------------------------------*/
2875 static void genEndFunction (iCode *ic)
2876 {
2877     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2878
2879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2880
2881     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2882     {
2883         pic16_emitcode ("mov","%s,_bp",spname);
2884     }
2885
2886     /* if use external stack but some variables were
2887     added to the local stack then decrement the
2888     local stack */
2889     if (options.useXstack && sym->stack) {      
2890         pic16_emitcode("mov","a,sp");
2891         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2892         pic16_emitcode("mov","sp,a");
2893     }
2894
2895
2896     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2897         if (options.useXstack) {
2898             pic16_emitcode("mov","r0,%s",spname);
2899             pic16_emitcode("movx","a,@r0");
2900             pic16_emitcode("mov","_bp,a");
2901             pic16_emitcode("dec","%s",spname);
2902         }
2903         else
2904         {
2905             pic16_emitcode ("pop","_bp");
2906         }
2907     }
2908
2909     /* restore the register bank  */    
2910     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2911         pic16_emitcode ("pop","psw");
2912
2913     if (IFFUNC_ISISR(sym->type)) {
2914
2915         /* now we need to restore the registers */
2916         /* if this isr has no bank i.e. is going to
2917            run with bank 0 , then we need to save more
2918            registers :-) */
2919         if (!FUNC_REGBANK(sym->type)) {
2920             
2921             /* if this function does not call any other
2922                function then we can be economical and
2923                save only those registers that are used */
2924             if (! IFFUNC_HASFCALL(sym->type)) {
2925                 int i;
2926                 
2927                 /* if any registers used */
2928                 if (sym->regsUsed) {
2929                     /* save the registers used */
2930                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2931                         if (bitVectBitValue(sym->regsUsed,i) ||
2932                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2933                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2934                     }
2935                 }
2936                 
2937             } else {
2938                 /* this function has  a function call cannot
2939                    determines register usage so we will have the
2940                    entire bank */
2941                 unsaverbank(0,ic,FALSE);
2942             }       
2943         }
2944 #if 0
2945         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2946         {
2947             if (options.stack10bit)
2948             {
2949                 pic16_emitcode ("pop", "dpx1");
2950                 pic16_emitcode ("pop", "dph1");
2951                 pic16_emitcode ("pop", "dpl1");
2952             }   
2953             pic16_emitcode ("pop", "dps");
2954             pic16_emitcode ("pop", "dpx");
2955         }
2956         if (!inExcludeList("dph"))
2957             pic16_emitcode ("pop","dph");
2958         if (!inExcludeList("dpl"))
2959             pic16_emitcode ("pop","dpl");
2960         if (!inExcludeList("b"))
2961             pic16_emitcode ("pop","b");
2962         if (!inExcludeList("acc"))
2963             pic16_emitcode ("pop","acc");
2964
2965         if (IFFUNC_ISCRITICAL(sym->type))
2966             pic16_emitcode("setb","ea");
2967 #endif
2968
2969         /* if debug then send end of function */
2970 /*      if (options.debug && currFunc) { */
2971         if (currFunc) {
2972             _G.debugLine = 1;
2973             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
2974                      FileBaseName(ic->filename),currFunc->lastLine,
2975                      ic->level,ic->block); 
2976             if (IS_STATIC(currFunc->etype))         
2977                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2978             else
2979                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2980             _G.debugLine = 0;
2981         }
2982         
2983         pic16_emitcode ("reti","");
2984
2985         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2986         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
2987         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
2988         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
2989         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
2990         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
2991
2992         pic16_emitpcodeNULLop(POC_RETFIE);
2993
2994     }
2995     else {
2996         if (IFFUNC_ISCRITICAL(sym->type))
2997             pic16_emitcode("setb","ea");
2998         
2999         if (IFFUNC_CALLEESAVES(sym->type)) {
3000             int i;
3001             
3002             /* if any registers used */
3003             if (sym->regsUsed) {
3004                 /* save the registers used */
3005                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3006                     if (bitVectBitValue(sym->regsUsed,i) ||
3007                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3008                       pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3009                 }
3010             }
3011             
3012         }
3013
3014         /* if debug then send end of function */
3015         if (currFunc) {
3016             _G.debugLine = 1;
3017             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3018                      FileBaseName(ic->filename),currFunc->lastLine,
3019                      ic->level,ic->block); 
3020             if (IS_STATIC(currFunc->etype))         
3021                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3022             else
3023                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3024             _G.debugLine = 0;
3025         }
3026
3027         pic16_emitcode ("return","");
3028         pic16_emitpcodeNULLop(POC_RETURN);
3029
3030         /* Mark the end of a function */
3031         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3032     }
3033
3034 }
3035
3036 /*-----------------------------------------------------------------*/
3037 /* genRet - generate code for return statement                     */
3038 /*-----------------------------------------------------------------*/
3039 static void genRet (iCode *ic)
3040 {
3041   int size,offset = 0 , pushed = 0;
3042     
3043   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3044   /* if we have no return value then
3045      just generate the "ret" */
3046   if (!IC_LEFT(ic)) 
3047     goto jumpret;       
3048     
3049   /* we have something to return then
3050      move the return value into place */
3051   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3052   size = AOP_SIZE(IC_LEFT(ic));
3053     
3054   while (size--) {
3055     char *l ;
3056     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3057       /* #NOCHANGE */
3058       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3059                  FALSE,TRUE);
3060       pic16_emitcode("push","%s",l);
3061       pushed++;
3062     } else {
3063       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3064                  FALSE,FALSE);
3065       if (strcmp(fReturn[offset],l)) {
3066         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3067             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3068           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3069         }else {
3070           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3071         }
3072         if(size) {
3073           pic16_emitpcode(POC_MOVWF,popRegFromIdx(offset + pic16_Gstack_base_addr));
3074         }
3075         offset++;
3076       }
3077     }
3078   }    
3079
3080   if (pushed) {
3081     while(pushed) {
3082       pushed--;
3083       if (strcmp(fReturn[pushed],"a"))
3084         pic16_emitcode("pop",fReturn[pushed]);
3085       else
3086         pic16_emitcode("pop","acc");
3087     }
3088   }
3089   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3090     
3091  jumpret:
3092   /* generate a jump to the return label
3093      if the next is not the return statement */
3094   if (!(ic->next && ic->next->op == LABEL &&
3095         IC_LABEL(ic->next) == returnLabel)) {
3096         
3097     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3098     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3099   }
3100     
3101 }
3102
3103 /*-----------------------------------------------------------------*/
3104 /* genLabel - generates a label                                    */
3105 /*-----------------------------------------------------------------*/
3106 static void genLabel (iCode *ic)
3107 {
3108     /* special case never generate */
3109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3110     if (IC_LABEL(ic) == entryLabel)
3111         return ;
3112
3113     pic16_emitpLabel(IC_LABEL(ic)->key);
3114     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3115 }
3116
3117 /*-----------------------------------------------------------------*/
3118 /* genGoto - generates a goto                                      */
3119 /*-----------------------------------------------------------------*/
3120 //tsd
3121 static void genGoto (iCode *ic)
3122 {
3123   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3124   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3125 }
3126
3127
3128 /*-----------------------------------------------------------------*/
3129 /* genMultbits :- multiplication of bits                           */
3130 /*-----------------------------------------------------------------*/
3131 static void genMultbits (operand *left, 
3132                          operand *right, 
3133                          operand *result)
3134 {
3135   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3136
3137   if(!pic16_sameRegs(AOP(result),AOP(right)))
3138     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3139
3140   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3141   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3142   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3143
3144 }
3145
3146
3147 /*-----------------------------------------------------------------*/
3148 /* genMultOneByte : 8 bit multiplication & division                */
3149 /*-----------------------------------------------------------------*/
3150 static void genMultOneByte (operand *left,
3151                             operand *right,
3152                             operand *result)
3153 {
3154   sym_link *opetype = operandType(result);
3155
3156   // symbol *lbl ;
3157   int size,offset;
3158
3159   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3160   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3161   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3162
3163   /* (if two literals, the value is computed before) */
3164   /* if one literal, literal on the right */
3165   if (AOP_TYPE(left) == AOP_LIT){
3166     operand *t = right;
3167     right = left;
3168     left = t;
3169   }
3170
3171   size = AOP_SIZE(result);
3172   if(size == 1) {
3173
3174     if (AOP_TYPE(right) == AOP_LIT){
3175       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3176                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3177                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3178                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3179       pic16_emitcode("call","genMultLit");
3180     } else {
3181       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3182                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3183                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3184                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3185       pic16_emitcode("call","pic16_genMult8X8_8");
3186
3187     }
3188     pic16_genMult8X8_8 (left, right,result);
3189
3190
3191     /* signed or unsigned */
3192     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3193     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3194     //MOVA(l);       
3195     //pic16_emitcode("mul","ab");
3196     /* if result size = 1, mul signed = mul unsigned */
3197     //pic16_aopPut(AOP(result),"a",0);
3198
3199   } else {  // (size > 1)
3200
3201     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3202                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3203                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3204                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3205
3206     if (SPEC_USIGN(opetype)){
3207       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3208       pic16_genUMult8X8_16 (left, right, result, NULL);
3209
3210       if (size > 2) {
3211         /* for filling the MSBs */
3212         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3213         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3214       }
3215     }
3216     else{
3217       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3218
3219       pic16_emitcode("mov","a,b");
3220
3221       /* adjust the MSB if left or right neg */
3222
3223       /* if one literal */
3224       if (AOP_TYPE(right) == AOP_LIT){
3225         pic16_emitcode("multiply ","right is a lit");
3226         /* AND literal negative */
3227         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3228           /* adjust MSB (c==0 after mul) */
3229           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3230         }
3231       }
3232       else{
3233         pic16_genSMult8X8_16 (left, right, result, NULL);
3234       }
3235
3236       if(size > 2){
3237         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3238         /* get the sign */
3239         pic16_emitcode("rlc","a");
3240         pic16_emitcode("subb","a,acc");
3241       }
3242     }
3243
3244     size -= 2;   
3245     offset = 2;
3246     if (size > 0)
3247       while (size--)
3248         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3249     //pic16_aopPut(AOP(result),"a",offset++);
3250   }
3251 }
3252
3253 /*-----------------------------------------------------------------*/
3254 /* genMult - generates code for multiplication                     */
3255 /*-----------------------------------------------------------------*/
3256 static void genMult (iCode *ic)
3257 {
3258     operand *left = IC_LEFT(ic);
3259     operand *right = IC_RIGHT(ic);
3260     operand *result= IC_RESULT(ic);   
3261
3262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3263     /* assign the amsops */
3264     pic16_aopOp (left,ic,FALSE);
3265     pic16_aopOp (right,ic,FALSE);
3266     pic16_aopOp (result,ic,TRUE);
3267
3268   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3269
3270     /* special cases first */
3271     /* both are bits */
3272     if (AOP_TYPE(left) == AOP_CRY &&
3273         AOP_TYPE(right)== AOP_CRY) {
3274         genMultbits(left,right,result);
3275         goto release ;
3276     }
3277
3278     /* if both are of size == 1 */
3279     if (AOP_SIZE(left) == 1 &&
3280         AOP_SIZE(right) == 1 ) {
3281         genMultOneByte(left,right,result);
3282         goto release ;
3283     }
3284
3285     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3286
3287     /* should have been converted to function call */
3288     //assert(0) ;
3289
3290 release :
3291     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3292     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3293     pic16_freeAsmop(result,NULL,ic,TRUE); 
3294 }
3295
3296 /*-----------------------------------------------------------------*/
3297 /* genDivbits :- division of bits                                  */
3298 /*-----------------------------------------------------------------*/
3299 static void genDivbits (operand *left, 
3300                         operand *right, 
3301                         operand *result)
3302 {
3303
3304     char *l;
3305
3306     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3307     /* the result must be bit */    
3308     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3309     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3310
3311     MOVA(l);    
3312
3313     pic16_emitcode("div","ab");
3314     pic16_emitcode("rrc","a");
3315     pic16_aopPut(AOP(result),"c",0);
3316 }
3317
3318 /*-----------------------------------------------------------------*/
3319 /* genDivOneByte : 8 bit division                                  */
3320 /*-----------------------------------------------------------------*/
3321 static void genDivOneByte (operand *left,
3322                            operand *right,
3323                            operand *result)
3324 {
3325     sym_link *opetype = operandType(result);
3326     char *l ;
3327     symbol *lbl ;
3328     int size,offset;
3329
3330     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3331     size = AOP_SIZE(result) - 1;
3332     offset = 1;
3333     /* signed or unsigned */
3334     if (SPEC_USIGN(opetype)) {
3335         /* unsigned is easy */
3336         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3337         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3338         MOVA(l);        
3339         pic16_emitcode("div","ab");
3340         pic16_aopPut(AOP(result),"a",0);
3341         while (size--)
3342             pic16_aopPut(AOP(result),zero,offset++);
3343         return ;
3344     }
3345
3346     /* signed is a little bit more difficult */
3347
3348     /* save the signs of the operands */
3349     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3350     MOVA(l);    
3351     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3352     pic16_emitcode("push","acc"); /* save it on the stack */
3353
3354     /* now sign adjust for both left & right */
3355     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3356     MOVA(l);       
3357     lbl = newiTempLabel(NULL);
3358     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3359     pic16_emitcode("cpl","a");   
3360     pic16_emitcode("inc","a");
3361     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3362     pic16_emitcode("mov","b,a");
3363
3364     /* sign adjust left side */
3365     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3366     MOVA(l);
3367
3368     lbl = newiTempLabel(NULL);
3369     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3370     pic16_emitcode("cpl","a");
3371     pic16_emitcode("inc","a");
3372     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3373
3374     /* now the division */
3375     pic16_emitcode("div","ab");
3376     /* we are interested in the lower order
3377     only */
3378     pic16_emitcode("mov","b,a");
3379     lbl = newiTempLabel(NULL);
3380     pic16_emitcode("pop","acc");   
3381     /* if there was an over flow we don't 
3382     adjust the sign of the result */
3383     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3384     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3385     CLRC;
3386     pic16_emitcode("clr","a");
3387     pic16_emitcode("subb","a,b");
3388     pic16_emitcode("mov","b,a");
3389     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3390
3391     /* now we are done */
3392     pic16_aopPut(AOP(result),"b",0);
3393     if(size > 0){
3394         pic16_emitcode("mov","c,b.7");
3395         pic16_emitcode("subb","a,acc");   
3396     }
3397     while (size--)
3398         pic16_aopPut(AOP(result),"a",offset++);
3399
3400 }
3401
3402 /*-----------------------------------------------------------------*/
3403 /* genDiv - generates code for division                            */
3404 /*-----------------------------------------------------------------*/
3405 static void genDiv (iCode *ic)
3406 {
3407     operand *left = IC_LEFT(ic);
3408     operand *right = IC_RIGHT(ic);
3409     operand *result= IC_RESULT(ic);   
3410
3411     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3412     /* assign the amsops */
3413     pic16_aopOp (left,ic,FALSE);
3414     pic16_aopOp (right,ic,FALSE);
3415     pic16_aopOp (result,ic,TRUE);
3416
3417     /* special cases first */
3418     /* both are bits */
3419     if (AOP_TYPE(left) == AOP_CRY &&
3420         AOP_TYPE(right)== AOP_CRY) {
3421         genDivbits(left,right,result);
3422         goto release ;
3423     }
3424
3425     /* if both are of size == 1 */
3426     if (AOP_SIZE(left) == 1 &&
3427         AOP_SIZE(right) == 1 ) {
3428         genDivOneByte(left,right,result);
3429         goto release ;
3430     }
3431
3432     /* should have been converted to function call */
3433     assert(0);
3434 release :
3435     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3436     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3437     pic16_freeAsmop(result,NULL,ic,TRUE); 
3438 }
3439
3440 /*-----------------------------------------------------------------*/
3441 /* genModbits :- modulus of bits                                   */
3442 /*-----------------------------------------------------------------*/
3443 static void genModbits (operand *left, 
3444                         operand *right, 
3445                         operand *result)
3446 {
3447
3448     char *l;
3449
3450     /* the result must be bit */    
3451     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3452     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3453
3454     MOVA(l);       
3455
3456     pic16_emitcode("div","ab");
3457     pic16_emitcode("mov","a,b");
3458     pic16_emitcode("rrc","a");
3459     pic16_aopPut(AOP(result),"c",0);
3460 }
3461
3462 /*-----------------------------------------------------------------*/
3463 /* genModOneByte : 8 bit modulus                                   */
3464 /*-----------------------------------------------------------------*/
3465 static void genModOneByte (operand *left,
3466                            operand *right,
3467                            operand *result)
3468 {
3469     sym_link *opetype = operandType(result);
3470     char *l ;
3471     symbol *lbl ;
3472
3473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3474     /* signed or unsigned */
3475     if (SPEC_USIGN(opetype)) {
3476         /* unsigned is easy */
3477         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3478         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3479         MOVA(l);    
3480         pic16_emitcode("div","ab");
3481         pic16_aopPut(AOP(result),"b",0);
3482         return ;
3483     }
3484
3485     /* signed is a little bit more difficult */
3486
3487     /* save the signs of the operands */
3488     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3489     MOVA(l);
3490
3491     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3492     pic16_emitcode("push","acc"); /* save it on the stack */
3493
3494     /* now sign adjust for both left & right */
3495     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3496     MOVA(l);
3497
3498     lbl = newiTempLabel(NULL);
3499     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3500     pic16_emitcode("cpl","a");   
3501     pic16_emitcode("inc","a");
3502     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3503     pic16_emitcode("mov","b,a"); 
3504
3505     /* sign adjust left side */
3506     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3507     MOVA(l);
3508
3509     lbl = newiTempLabel(NULL);
3510     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3511     pic16_emitcode("cpl","a");   
3512     pic16_emitcode("inc","a");
3513     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3514
3515     /* now the multiplication */
3516     pic16_emitcode("div","ab");
3517     /* we are interested in the lower order
3518     only */
3519     lbl = newiTempLabel(NULL);
3520     pic16_emitcode("pop","acc");   
3521     /* if there was an over flow we don't 
3522     adjust the sign of the result */
3523     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3524     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3525     CLRC ;
3526     pic16_emitcode("clr","a");
3527     pic16_emitcode("subb","a,b");
3528     pic16_emitcode("mov","b,a");
3529     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3530
3531     /* now we are done */
3532     pic16_aopPut(AOP(result),"b",0);
3533
3534 }
3535
3536 /*-----------------------------------------------------------------*/
3537 /* genMod - generates code for division                            */
3538 /*-----------------------------------------------------------------*/
3539 static void genMod (iCode *ic)
3540 {
3541     operand *left = IC_LEFT(ic);
3542     operand *right = IC_RIGHT(ic);
3543     operand *result= IC_RESULT(ic);  
3544
3545     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3546     /* assign the amsops */
3547     pic16_aopOp (left,ic,FALSE);
3548     pic16_aopOp (right,ic,FALSE);
3549     pic16_aopOp (result,ic,TRUE);
3550
3551     /* special cases first */
3552     /* both are bits */
3553     if (AOP_TYPE(left) == AOP_CRY &&
3554         AOP_TYPE(right)== AOP_CRY) {
3555         genModbits(left,right,result);
3556         goto release ;
3557     }
3558
3559     /* if both are of size == 1 */
3560     if (AOP_SIZE(left) == 1 &&
3561         AOP_SIZE(right) == 1 ) {
3562         genModOneByte(left,right,result);
3563         goto release ;
3564     }
3565
3566     /* should have been converted to function call */
3567     assert(0);
3568
3569 release :
3570     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3571     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3572     pic16_freeAsmop(result,NULL,ic,TRUE); 
3573 }
3574
3575 /*-----------------------------------------------------------------*/
3576 /* genIfxJump :- will create a jump depending on the ifx           */
3577 /*-----------------------------------------------------------------*/
3578 /*
3579   note: May need to add parameter to indicate when a variable is in bit space.
3580 */
3581 static void genIfxJump (iCode *ic, char *jval)
3582 {
3583
3584     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3585     /* if true label then we jump if condition
3586     supplied is true */
3587     if ( IC_TRUE(ic) ) {
3588
3589         if(strcmp(jval,"a") == 0)
3590           emitSKPZ;
3591         else if (strcmp(jval,"c") == 0)
3592           emitSKPC;
3593         else {
3594           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3595           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3596         }
3597
3598         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3599         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3600
3601     }
3602     else {
3603         /* false label is present */
3604         if(strcmp(jval,"a") == 0)
3605           emitSKPNZ;
3606         else if (strcmp(jval,"c") == 0)
3607           emitSKPNC;
3608         else {
3609           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3610           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3611         }
3612
3613         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3614         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3615
3616     }
3617
3618
3619     /* mark the icode as generated */
3620     ic->generated = 1;
3621 }
3622
3623 /*-----------------------------------------------------------------*/
3624 /* genSkip                                                         */
3625 /*-----------------------------------------------------------------*/
3626 static void genSkip(iCode *ifx,int status_bit)
3627 {
3628   if(!ifx)
3629     return;
3630
3631   if ( IC_TRUE(ifx) ) {
3632     switch(status_bit) {
3633     case 'z':
3634       emitSKPNZ;
3635       break;
3636
3637     case 'c':
3638       emitSKPNC;
3639       break;
3640
3641     case 'd':
3642       emitSKPDC;
3643       break;
3644
3645     }
3646
3647     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3648     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3649
3650   } else {
3651
3652     switch(status_bit) {
3653
3654     case 'z':
3655       emitSKPZ;
3656       break;
3657
3658     case 'c':
3659       emitSKPC;
3660       break;
3661
3662     case 'd':
3663       emitSKPDC;
3664       break;
3665     }
3666     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3667     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3668
3669   }
3670
3671 }
3672
3673 /*-----------------------------------------------------------------*/
3674 /* genSkipc                                                        */
3675 /*-----------------------------------------------------------------*/
3676 static void genSkipc(resolvedIfx *rifx)
3677 {
3678   if(!rifx)
3679     return;
3680
3681   if(rifx->condition)
3682     emitSKPC;
3683   else
3684     emitSKPNC;
3685
3686   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3687   rifx->generated = 1;
3688 }
3689
3690 /*-----------------------------------------------------------------*/
3691 /* genSkipz2                                                       */
3692 /*-----------------------------------------------------------------*/
3693 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3694 {
3695   if(!rifx)
3696     return;
3697
3698   if( (rifx->condition ^ invert_condition) & 1)
3699     emitSKPZ;
3700   else
3701     emitSKPNZ;
3702
3703   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3704   rifx->generated = 1;
3705 }
3706
3707 /*-----------------------------------------------------------------*/
3708 /* genSkipz                                                        */
3709 /*-----------------------------------------------------------------*/
3710 static void genSkipz(iCode *ifx, int condition)
3711 {
3712   if(!ifx)
3713     return;
3714
3715   if(condition)
3716     emitSKPNZ;
3717   else
3718     emitSKPZ;
3719
3720   if ( IC_TRUE(ifx) )
3721     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3722   else
3723     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3724
3725   if ( IC_TRUE(ifx) )
3726     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3727   else
3728     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3729
3730 }
3731 /*-----------------------------------------------------------------*/
3732 /* genSkipCond                                                     */
3733 /*-----------------------------------------------------------------*/
3734 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3735 {
3736   if(!rifx)
3737     return;
3738
3739   if(rifx->condition)
3740     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3741   else
3742     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3743
3744
3745   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3746   rifx->generated = 1;
3747 }
3748
3749 #if 0
3750 /*-----------------------------------------------------------------*/
3751 /* genChkZeroes :- greater or less than comparison                 */
3752 /*     For each byte in a literal that is zero, inclusive or the   */
3753 /*     the corresponding byte in the operand with W                */
3754 /*     returns true if any of the bytes are zero                   */
3755 /*-----------------------------------------------------------------*/
3756 static int genChkZeroes(operand *op, int lit,  int size)
3757 {
3758
3759   int i;
3760   int flag =1;
3761
3762   while(size--) {
3763     i = (lit >> (size*8)) & 0xff;
3764
3765     if(i==0) {
3766       if(flag) 
3767         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3768       else
3769         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3770       flag = 0;
3771     }
3772   }
3773
3774   return (flag==0);
3775 }
3776 #endif
3777
3778 /*-----------------------------------------------------------------*/
3779 /* genCmp :- greater or less than comparison                       */
3780 /*-----------------------------------------------------------------*/
3781 static void genCmp (operand *left,operand *right,
3782                     operand *result, iCode *ifx, int sign)
3783 {
3784   int size; //, offset = 0 ;
3785   unsigned long lit = 0L,i = 0;
3786   resolvedIfx rFalseIfx;
3787   //  resolvedIfx rTrueIfx;
3788   symbol *truelbl;
3789   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3790 /*
3791   if(ifx) {
3792     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3793     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3794   }
3795 */
3796
3797   resolveIfx(&rFalseIfx,ifx);
3798   truelbl  = newiTempLabel(NULL);
3799   size = max(AOP_SIZE(left),AOP_SIZE(right));
3800
3801   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3802
3803 #define _swapp
3804
3805   /* if literal is on the right then swap with left */
3806   if ((AOP_TYPE(right) == AOP_LIT)) {
3807     operand *tmp = right ;
3808     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3809     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3810 #ifdef _swapp
3811
3812     lit = (lit - 1) & mask;
3813     right = left;
3814     left = tmp;
3815     rFalseIfx.condition ^= 1;
3816 #endif
3817
3818   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3819     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3820   }
3821
3822
3823   //if(IC_TRUE(ifx) == NULL)
3824   /* if left & right are bit variables */
3825   if (AOP_TYPE(left) == AOP_CRY &&
3826       AOP_TYPE(right) == AOP_CRY ) {
3827     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3828     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3829   } else {
3830     /* subtract right from left if at the
3831        end the carry flag is set then we know that
3832        left is greater than right */
3833
3834     //    {
3835
3836     symbol *lbl  = newiTempLabel(NULL);
3837
3838 #ifndef _swapp
3839     if(AOP_TYPE(right) == AOP_LIT) {
3840
3841       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3842
3843       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3844
3845       /* special cases */
3846
3847       if(lit == 0) {
3848
3849         if(sign != 0) 
3850           genSkipCond(&rFalseIfx,left,size-1,7);
3851         else 
3852           /* no need to compare to 0...*/
3853           /* NOTE: this is a de-generate compare that most certainly 
3854            *       creates some dead code. */
3855           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
3856
3857         if(ifx) ifx->generated = 1;
3858         return;
3859
3860       }
3861       size--;
3862
3863       if(size == 0) {
3864         //i = (lit >> (size*8)) & 0xff;
3865         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3866         
3867         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3868
3869         i = ((0-lit) & 0xff);
3870         if(sign) {
3871           if( i == 0x81) { 
3872             /* lit is 0x7f, all signed chars are less than
3873              * this except for 0x7f itself */
3874             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
3875             genSkipz2(&rFalseIfx,0);
3876           } else {
3877             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
3878             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
3879             genSkipc(&rFalseIfx);
3880           }
3881
3882         } else {
3883           if(lit == 1) {
3884             genSkipz2(&rFalseIfx,1);
3885           } else {
3886             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
3887             genSkipc(&rFalseIfx);
3888           }
3889         }
3890
3891         if(ifx) ifx->generated = 1;
3892         return;
3893       }
3894
3895       /* chars are out of the way. now do ints and longs */
3896
3897
3898       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3899         
3900       /* special cases */
3901
3902       if(sign) {
3903
3904         if(lit == 0) {
3905           genSkipCond(&rFalseIfx,left,size,7);
3906           if(ifx) ifx->generated = 1;
3907           return;
3908         }
3909
3910         if(lit <0x100) {
3911           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3912
3913           //rFalseIfx.condition ^= 1;
3914           //genSkipCond(&rFalseIfx,left,size,7);
3915           //rFalseIfx.condition ^= 1;
3916
3917           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3918           if(rFalseIfx.condition)
3919             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3920           else
3921             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3922
3923           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
3924           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3925           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
3926
3927           while(size > 1)
3928             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
3929
3930           if(rFalseIfx.condition) {
3931             emitSKPZ;
3932             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3933
3934           } else {
3935             emitSKPNZ;
3936           }
3937
3938           genSkipc(&rFalseIfx);
3939           pic16_emitpLabel(truelbl->key);
3940           if(ifx) ifx->generated = 1;
3941           return;
3942
3943         }
3944
3945         if(size == 1) {
3946
3947           if( (lit & 0xff) == 0) {
3948             /* lower byte is zero */
3949             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3950             i = ((lit >> 8) & 0xff) ^0x80;
3951             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3952             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3953             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3954             genSkipc(&rFalseIfx);
3955
3956
3957             if(ifx) ifx->generated = 1;
3958             return;
3959
3960           }
3961         } else {
3962           /* Special cases for signed longs */
3963           if( (lit & 0xffffff) == 0) {
3964             /* lower byte is zero */
3965             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3966             i = ((lit >> 8*3) & 0xff) ^0x80;
3967             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3968             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3969             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3970             genSkipc(&rFalseIfx);
3971
3972
3973             if(ifx) ifx->generated = 1;
3974             return;
3975
3976           }
3977
3978         }
3979
3980
3981         if(lit & (0x80 << (size*8))) {
3982           /* lit is negative */
3983           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3984
3985           //genSkipCond(&rFalseIfx,left,size,7);
3986
3987           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3988
3989           if(rFalseIfx.condition)
3990             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3991           else
3992             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3993
3994
3995         } else {
3996           /* lit is positive */
3997           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3998           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3999           if(rFalseIfx.condition)
4000             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4001           else
4002             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4003
4004         }
4005
4006         /*
4007           This works, but is only good for ints.
4008           It also requires a "known zero" register.
4009           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4010           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4011           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4012           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4013           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4014           genSkipc(&rFalseIfx);
4015
4016           pic16_emitpLabel(truelbl->key);
4017           if(ifx) ifx->generated = 1;
4018           return;
4019         **/
4020           
4021         /* There are no more special cases, so perform a general compare */
4022   
4023         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4024         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4025
4026         while(size--) {
4027
4028           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4029           emitSKPNZ;
4030           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4031         }
4032         //rFalseIfx.condition ^= 1;
4033         genSkipc(&rFalseIfx);
4034
4035         pic16_emitpLabel(truelbl->key);
4036
4037         if(ifx) ifx->generated = 1;
4038         return;
4039
4040
4041       }
4042
4043
4044       /* sign is out of the way. So now do an unsigned compare */
4045       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4046
4047
4048       /* General case - compare to an unsigned literal on the right.*/
4049
4050       i = (lit >> (size*8)) & 0xff;
4051       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4052       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4053       while(size--) {
4054         i = (lit >> (size*8)) & 0xff;
4055
4056         if(i) {
4057           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4058           emitSKPNZ;
4059           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4060         } else {
4061           /* this byte of the lit is zero, 
4062            *if it's not the last then OR in the variable */
4063           if(size)
4064             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4065         }
4066       }
4067
4068
4069       pic16_emitpLabel(lbl->key);
4070       //if(emitFinalCheck)
4071       genSkipc(&rFalseIfx);
4072       if(sign)
4073         pic16_emitpLabel(truelbl->key);
4074
4075       if(ifx) ifx->generated = 1;
4076       return;
4077
4078
4079     }
4080 #endif  // _swapp
4081
4082     if(AOP_TYPE(left) == AOP_LIT) {
4083       //symbol *lbl = newiTempLabel(NULL);
4084
4085       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4086
4087
4088       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4089
4090       /* Special cases */
4091       if((lit == 0) && (sign == 0)){
4092
4093         size--;
4094         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4095         while(size) 
4096           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4097
4098         genSkipz2(&rFalseIfx,0);
4099         if(ifx) ifx->generated = 1;
4100         return;
4101       }
4102
4103       if(size==1) {
4104         /* Special cases */
4105         lit &= 0xff;
4106         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4107           /* degenerate compare can never be true */
4108           if(rFalseIfx.condition == 0)
4109             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4110
4111           if(ifx) ifx->generated = 1;
4112           return;
4113         }
4114
4115         if(sign) {
4116           /* signed comparisons to a literal byte */
4117
4118           int lp1 = (lit+1) & 0xff;
4119
4120           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4121           switch (lp1) {
4122           case 0:
4123             rFalseIfx.condition ^= 1;
4124             genSkipCond(&rFalseIfx,right,0,7);
4125             break;
4126           case 0x7f:
4127             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4128             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4129             genSkipz2(&rFalseIfx,1);
4130             break;
4131           default:
4132             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4133             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4134             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4135             rFalseIfx.condition ^= 1;
4136             genSkipc(&rFalseIfx);
4137             break;
4138           }
4139         } else {
4140           /* unsigned comparisons to a literal byte */
4141
4142           switch(lit & 0xff ) {
4143           case 0:
4144             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4145             genSkipz2(&rFalseIfx,0);
4146             break;
4147           case 0x7f:
4148             rFalseIfx.condition ^= 1;
4149             genSkipCond(&rFalseIfx,right,0,7);
4150             break;
4151
4152           default:
4153             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4154             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4155             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4156             rFalseIfx.condition ^= 1;
4157             if (AOP_TYPE(result) == AOP_CRY)
4158               genSkipc(&rFalseIfx);
4159             else {
4160               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4161               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4162             }         
4163             break;
4164           }
4165         }
4166
4167         if(ifx) ifx->generated = 1;
4168         //goto check_carry;
4169         return;
4170
4171       } else {
4172
4173         /* Size is greater than 1 */
4174
4175         if(sign) {
4176           int lp1 = lit+1;
4177
4178           size--;
4179
4180           if(lp1 == 0) {
4181             /* this means lit = 0xffffffff, or -1 */
4182
4183
4184             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4185             rFalseIfx.condition ^= 1;
4186             genSkipCond(&rFalseIfx,right,size,7);
4187             if(ifx) ifx->generated = 1;
4188             return;
4189           }
4190
4191           if(lit == 0) {
4192             int s = size;
4193
4194             if(rFalseIfx.condition) {
4195               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4196               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4197             }
4198
4199             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4200             while(size--)
4201               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4202
4203
4204             emitSKPZ;
4205             if(rFalseIfx.condition) {
4206               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4207               pic16_emitpLabel(truelbl->key);
4208             }else {
4209               rFalseIfx.condition ^= 1;
4210               genSkipCond(&rFalseIfx,right,s,7);
4211             }
4212
4213             if(ifx) ifx->generated = 1;
4214             return;
4215           }
4216
4217           if((size == 1) &&  (0 == (lp1&0xff))) {
4218             /* lower byte of signed word is zero */
4219             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4220             i = ((lp1 >> 8) & 0xff) ^0x80;
4221             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4222             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4223             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4224             rFalseIfx.condition ^= 1;
4225             genSkipc(&rFalseIfx);
4226
4227
4228             if(ifx) ifx->generated = 1;
4229             return;
4230           }
4231
4232           if(lit & (0x80 << (size*8))) {
4233             /* Lit is less than zero */
4234             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4235             //rFalseIfx.condition ^= 1;
4236             //genSkipCond(&rFalseIfx,left,size,7);
4237             //rFalseIfx.condition ^= 1;
4238             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4239             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4240
4241             if(rFalseIfx.condition)
4242               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4243             else
4244               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4245
4246
4247           } else {
4248             /* Lit is greater than or equal to zero */
4249             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4250             //rFalseIfx.condition ^= 1;
4251             //genSkipCond(&rFalseIfx,right,size,7);
4252             //rFalseIfx.condition ^= 1;
4253
4254             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4255             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4256
4257             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4258             if(rFalseIfx.condition)
4259               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4260             else
4261               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4262
4263           }
4264
4265
4266           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4267           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4268
4269           while(size--) {
4270
4271             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4272             emitSKPNZ;
4273             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4274           }
4275           rFalseIfx.condition ^= 1;
4276           //rFalseIfx.condition = 1;
4277           genSkipc(&rFalseIfx);
4278
4279           pic16_emitpLabel(truelbl->key);
4280
4281           if(ifx) ifx->generated = 1;
4282           return;
4283           // end of if (sign)
4284         } else {
4285
4286           /* compare word or long to an unsigned literal on the right.*/
4287
4288
4289           size--;
4290           if(lit < 0xff) {
4291             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4292             switch (lit) {
4293             case 0:
4294               break; /* handled above */
4295 /*
4296             case 0xff:
4297               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4298               while(size--)
4299                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4300               genSkipz2(&rFalseIfx,0);
4301               break;
4302 */
4303             default:
4304               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4305               while(--size)
4306                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4307
4308               emitSKPZ;
4309               if(rFalseIfx.condition)
4310                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4311               else
4312                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4313
4314
4315               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4316               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4317
4318               rFalseIfx.condition ^= 1;
4319               genSkipc(&rFalseIfx);
4320             }
4321
4322             pic16_emitpLabel(truelbl->key);
4323
4324             if(ifx) ifx->generated = 1;
4325             return;
4326           }
4327
4328
4329           lit++;
4330           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4331           i = (lit >> (size*8)) & 0xff;
4332
4333           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4334           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4335
4336           while(size--) {
4337             i = (lit >> (size*8)) & 0xff;
4338
4339             if(i) {
4340               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4341               emitSKPNZ;
4342               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4343             } else {
4344               /* this byte of the lit is zero, 
4345                *if it's not the last then OR in the variable */
4346               if(size)
4347                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4348             }
4349           }
4350
4351
4352           pic16_emitpLabel(lbl->key);
4353
4354           rFalseIfx.condition ^= 1;
4355           genSkipc(&rFalseIfx);
4356         }
4357
4358         if(sign)
4359           pic16_emitpLabel(truelbl->key);
4360         if(ifx) ifx->generated = 1;
4361         return;
4362       }
4363     }
4364     /* Compare two variables */
4365
4366     DEBUGpic16_emitcode(";sign","%d",sign);
4367
4368     size--;
4369     if(sign) {
4370       /* Sigh. thus sucks... */
4371       if(size) {
4372         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4373         pic16_emitpcode(POC_MOVWF, popRegFromIdx(pic16_Gstack_base_addr));
4374         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4375         pic16_emitpcode(POC_XORWF, popRegFromIdx(pic16_Gstack_base_addr));
4376         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4377         pic16_emitpcode(POC_SUBFW, popRegFromIdx(pic16_Gstack_base_addr));
4378       } else {
4379         /* Signed char comparison */
4380         /* Special thanks to Nikolai Golovchenko for this snippet */
4381         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4382         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4383         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4384         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4385         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4386         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4387
4388         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4389         genSkipc(&rFalseIfx);
4390           
4391         if(ifx) ifx->generated = 1;
4392         return;
4393       }
4394
4395     } else {
4396
4397       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4398       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4399     }
4400
4401
4402     /* The rest of the bytes of a multi-byte compare */
4403     while (size) {
4404
4405       emitSKPZ;
4406       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4407       size--;
4408
4409       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4410       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4411
4412
4413     }
4414
4415     pic16_emitpLabel(lbl->key);
4416
4417     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4418     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4419         (AOP_TYPE(result) == AOP_REG)) {
4420       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4421       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4422     } else {
4423       genSkipc(&rFalseIfx);
4424     }         
4425     //genSkipc(&rFalseIfx);
4426     if(ifx) ifx->generated = 1;
4427
4428     return;
4429
4430   }
4431
4432   // check_carry:
4433   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4434     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4435     pic16_outBitC(result);
4436   } else {
4437     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4438     /* if the result is used in the next
4439        ifx conditional branch then generate
4440        code a little differently */
4441     if (ifx )
4442       genIfxJump (ifx,"c");
4443     else
4444       pic16_outBitC(result);
4445     /* leave the result in acc */
4446   }
4447
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genCmpGt :- greater than comparison                             */
4452 /*-----------------------------------------------------------------*/
4453 static void genCmpGt (iCode *ic, iCode *ifx)
4454 {
4455     operand *left, *right, *result;
4456     sym_link *letype , *retype;
4457     int sign ;
4458
4459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4460     left = IC_LEFT(ic);
4461     right= IC_RIGHT(ic);
4462     result = IC_RESULT(ic);
4463
4464     letype = getSpec(operandType(left));
4465     retype =getSpec(operandType(right));
4466     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4467     /* assign the amsops */
4468     pic16_aopOp (left,ic,FALSE);
4469     pic16_aopOp (right,ic,FALSE);
4470     pic16_aopOp (result,ic,TRUE);
4471
4472     genCmp(right, left, result, ifx, sign);
4473
4474     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4475     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4476     pic16_freeAsmop(result,NULL,ic,TRUE); 
4477 }
4478
4479 /*-----------------------------------------------------------------*/
4480 /* genCmpLt - less than comparisons                                */
4481 /*-----------------------------------------------------------------*/
4482 static void genCmpLt (iCode *ic, iCode *ifx)
4483 {
4484     operand *left, *right, *result;
4485     sym_link *letype , *retype;
4486     int sign ;
4487
4488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4489     left = IC_LEFT(ic);
4490     right= IC_RIGHT(ic);
4491     result = IC_RESULT(ic);
4492
4493     letype = getSpec(operandType(left));
4494     retype =getSpec(operandType(right));
4495     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4496
4497     /* assign the amsops */
4498     pic16_aopOp (left,ic,FALSE);
4499     pic16_aopOp (right,ic,FALSE);
4500     pic16_aopOp (result,ic,TRUE);
4501
4502     genCmp(left, right, result, ifx, sign);
4503
4504     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4505     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4506     pic16_freeAsmop(result,NULL,ic,TRUE); 
4507 }
4508
4509 /*-----------------------------------------------------------------*/
4510 /* genc16bit2lit - compare a 16 bit value to a literal             */
4511 /*-----------------------------------------------------------------*/
4512 static void genc16bit2lit(operand *op, int lit, int offset)
4513 {
4514   int i;
4515
4516   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4517   if( (lit&0xff) == 0) 
4518     i=1;
4519   else
4520     i=0;
4521
4522   switch( BYTEofLONG(lit,i)) { 
4523   case 0:
4524     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4525     break;
4526   case 1:
4527     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4528     break;
4529   case 0xff:
4530     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4531     break;
4532   default:
4533     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4534     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4535   }
4536
4537   i ^= 1;
4538
4539   switch( BYTEofLONG(lit,i)) { 
4540   case 0:
4541     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4542     break;
4543   case 1:
4544     emitSKPNZ;
4545     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4546     break;
4547   case 0xff:
4548     emitSKPNZ;
4549     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4550     break;
4551   default:
4552     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4553     emitSKPNZ;
4554     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4555
4556   }
4557
4558 }
4559
4560 /*-----------------------------------------------------------------*/
4561 /* gencjneshort - compare and jump if not equal                    */
4562 /*-----------------------------------------------------------------*/
4563 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4564 {
4565   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4566   int offset = 0;
4567   int res_offset = 0;  /* the result may be a different size then left or right */
4568   int res_size = AOP_SIZE(result);
4569   resolvedIfx rIfx;
4570   symbol *lbl;
4571
4572   unsigned long lit = 0L;
4573   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4574   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4575   if(result)
4576     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4577   resolveIfx(&rIfx,ifx);
4578   lbl =  newiTempLabel(NULL);
4579
4580
4581   /* if the left side is a literal or 
4582      if the right is in a pointer register and left 
4583      is not */
4584   if ((AOP_TYPE(left) == AOP_LIT) || 
4585       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4586     operand *t = right;
4587     right = left;
4588     left = t;
4589   }
4590   if(AOP_TYPE(right) == AOP_LIT)
4591     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4592
4593   /* if the right side is a literal then anything goes */
4594   if (AOP_TYPE(right) == AOP_LIT &&
4595       AOP_TYPE(left) != AOP_DIR ) {
4596     switch(size) {
4597     case 2:
4598       genc16bit2lit(left, lit, 0);
4599       emitSKPNZ;
4600       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4601       break;
4602     default:
4603       while (size--) {
4604         if(lit & 0xff) {
4605           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4606           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4607         } else {
4608           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4609         }
4610
4611         emitSKPNZ;
4612         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4613         offset++;
4614         if(res_offset < res_size-1)
4615           res_offset++;
4616         lit >>= 8;
4617       }
4618       break;
4619     }
4620   }
4621
4622   /* if the right side is in a register or in direct space or
4623      if the left is a pointer register & right is not */    
4624   else if (AOP_TYPE(right) == AOP_REG ||
4625            AOP_TYPE(right) == AOP_DIR || 
4626            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4627            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4628     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4629     int lbl_key = lbl->key;
4630
4631     if(result) {
4632       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4633       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4634     }else {
4635       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4636       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4637               __FUNCTION__,__LINE__);
4638       return;
4639     }
4640
4641 /*     switch(size) { */
4642 /*     case 2: */
4643 /*       genc16bit2lit(left, lit, 0); */
4644 /*       emitSKPNZ; */
4645 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4646 /*       break; */
4647 /*     default: */
4648     while (size--) {
4649       int emit_skip=1;
4650       if((AOP_TYPE(left) == AOP_DIR) && 
4651          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4652
4653         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4654         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4655
4656       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4657             
4658         switch (lit & 0xff) {
4659         case 0:
4660           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4661           break;
4662         case 1:
4663           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4664           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4665           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4666           emit_skip=0;
4667           break;
4668         case 0xff:
4669           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4670           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4671           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4672           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4673           emit_skip=0;
4674           break;
4675         default:
4676           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4677           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4678         }
4679         lit >>= 8;
4680
4681       } else {
4682         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4683       }
4684       if(emit_skip) {
4685         if(AOP_TYPE(result) == AOP_CRY) {
4686           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4687           if(rIfx.condition)
4688             emitSKPNZ;
4689           else
4690             emitSKPZ;
4691           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4692         } else {
4693           /* fix me. probably need to check result size too */
4694           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4695           if(rIfx.condition)
4696             emitSKPZ;
4697           else
4698             emitSKPNZ;
4699           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4700           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4701         }
4702         if(ifx)
4703           ifx->generated=1;
4704       }
4705       emit_skip++;
4706       offset++;
4707       if(res_offset < res_size-1)
4708         res_offset++;
4709     }
4710 /*       break; */
4711 /*     } */
4712   } else if(AOP_TYPE(right) == AOP_REG &&
4713             AOP_TYPE(left) != AOP_DIR){
4714
4715     while(size--) {
4716       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4717       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4718       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4719       if(rIfx.condition)
4720         emitSKPNZ;
4721       else
4722         emitSKPZ;
4723       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4724       offset++;
4725       if(res_offset < res_size-1)
4726         res_offset++;
4727     }
4728       
4729   }else{
4730     /* right is a pointer reg need both a & b */
4731     while(size--) {
4732       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4733       if(strcmp(l,"b"))
4734         pic16_emitcode("mov","b,%s",l);
4735       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4736       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4737       offset++;
4738     }
4739   }
4740
4741   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4742   if(!rIfx.condition)
4743     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4744
4745   pic16_emitpLabel(lbl->key);
4746
4747   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4748
4749   if(ifx)
4750     ifx->generated = 1;
4751 }
4752
4753 #if 0
4754 /*-----------------------------------------------------------------*/
4755 /* gencjne - compare and jump if not equal                         */
4756 /*-----------------------------------------------------------------*/
4757 static void gencjne(operand *left, operand *right, iCode *ifx)
4758 {
4759     symbol *tlbl  = newiTempLabel(NULL);
4760
4761     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4762     gencjneshort(left, right, lbl);
4763
4764     pic16_emitcode("mov","a,%s",one);
4765     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4766     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4767     pic16_emitcode("clr","a");
4768     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4769
4770     pic16_emitpLabel(lbl->key);
4771     pic16_emitpLabel(tlbl->key);
4772
4773 }
4774 #endif
4775
4776 /*-----------------------------------------------------------------*/
4777 /* genCmpEq - generates code for equal to                          */
4778 /*-----------------------------------------------------------------*/
4779 static void genCmpEq (iCode *ic, iCode *ifx)
4780 {
4781     operand *left, *right, *result;
4782     unsigned long lit = 0L;
4783     int size,offset=0;
4784
4785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4786
4787     if(ifx)
4788       DEBUGpic16_emitcode ("; ifx is non-null","");
4789     else
4790       DEBUGpic16_emitcode ("; ifx is null","");
4791
4792     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4793     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4794     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4795
4796     size = max(AOP_SIZE(left),AOP_SIZE(right));
4797
4798     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4799
4800     /* if literal, literal on the right or 
4801     if the right is in a pointer register and left 
4802     is not */
4803     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4804         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4805       operand *tmp = right ;
4806       right = left;
4807       left = tmp;
4808     }
4809
4810
4811     if(ifx && !AOP_SIZE(result)){
4812         symbol *tlbl;
4813         /* if they are both bit variables */
4814         if (AOP_TYPE(left) == AOP_CRY &&
4815             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4816             if(AOP_TYPE(right) == AOP_LIT){
4817                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4818                 if(lit == 0L){
4819                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4820                     pic16_emitcode("cpl","c");
4821                 } else if(lit == 1L) {
4822                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4823                 } else {
4824                     pic16_emitcode("clr","c");
4825                 }
4826                 /* AOP_TYPE(right) == AOP_CRY */
4827             } else {
4828                 symbol *lbl = newiTempLabel(NULL);
4829                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4830                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4831                 pic16_emitcode("cpl","c");
4832                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4833             }
4834             /* if true label then we jump if condition
4835             supplied is true */
4836             tlbl = newiTempLabel(NULL);
4837             if ( IC_TRUE(ifx) ) {
4838                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4839                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4840             } else {
4841                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4842                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4843             }
4844             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4845
4846             {
4847               /* left and right are both bit variables, result is carry */
4848               resolvedIfx rIfx;
4849               
4850               resolveIfx(&rIfx,ifx);
4851
4852               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4853               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4854               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4855               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4856               genSkipz2(&rIfx,0);
4857             }
4858         } else {
4859
4860           /* They're not both bit variables. Is the right a literal? */
4861           if(AOP_TYPE(right) == AOP_LIT) {
4862             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4863             
4864             switch(size) {
4865
4866             case 1:
4867               switch(lit & 0xff) {
4868               case 1:
4869                 if ( IC_TRUE(ifx) ) {
4870                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4871                   emitSKPNZ;
4872                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4873                 } else {
4874                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4875                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4876                 }
4877                 break;
4878               case 0xff:
4879                 if ( IC_TRUE(ifx) ) {
4880                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4881                   emitSKPNZ;
4882                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4883                 } else {
4884                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4885                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4886                 }
4887                 break;
4888               default:
4889                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4890                 if(lit)
4891                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4892                 genSkip(ifx,'z');
4893               }
4894
4895
4896               /* end of size == 1 */
4897               break;
4898               
4899             case 2:
4900               genc16bit2lit(left,lit,offset);
4901               genSkip(ifx,'z');
4902               break;
4903               /* end of size == 2 */
4904
4905             default:
4906               /* size is 4 */
4907               if(lit==0) {
4908                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4909                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4910                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4911                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4912
4913               } else {
4914
4915                 /* search for patterns that can be optimized */
4916
4917                 genc16bit2lit(left,lit,0);
4918                 lit >>= 16;
4919                 if(lit) {
4920                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4921                   //genSkip(ifx,'z');
4922                   genc16bit2lit(left,lit,2);
4923                 } else {
4924                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4925                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4926
4927                 }
4928                 
4929               }
4930
4931               genSkip(ifx,'z');
4932             }
4933           
4934             ifx->generated = 1;
4935             goto release ;
4936             
4937
4938           } else if(AOP_TYPE(right) == AOP_CRY ) {
4939             /* we know the left is not a bit, but that the right is */
4940             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4941             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4942                       pic16_popGet(AOP(right),offset));
4943             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4944
4945             /* if the two are equal, then W will be 0 and the Z bit is set
4946              * we could test Z now, or go ahead and check the high order bytes if
4947              * the variable we're comparing is larger than a byte. */
4948
4949             while(--size)
4950               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4951
4952             if ( IC_TRUE(ifx) ) {
4953               emitSKPNZ;
4954               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4955               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4956             } else {
4957               emitSKPZ;
4958               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4959               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4960             }
4961
4962           } else {
4963             /* They're both variables that are larger than bits */
4964             int s = size;
4965
4966             tlbl = newiTempLabel(NULL);
4967
4968             while(size--) {
4969               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4970               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4971
4972               if ( IC_TRUE(ifx) ) {
4973                 if(size) {
4974                   emitSKPZ;
4975                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4976                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4977                 } else {
4978                   emitSKPNZ;
4979                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4980                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4981                 }
4982               } else {
4983                 emitSKPZ;
4984                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4985                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4986               }
4987               offset++;
4988             }
4989             if(s>1 && IC_TRUE(ifx)) {
4990               pic16_emitpLabel(tlbl->key);
4991               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4992             }
4993           }
4994         }
4995         /* mark the icode as generated */
4996         ifx->generated = 1;
4997         goto release ;
4998     }
4999
5000     /* if they are both bit variables */
5001     if (AOP_TYPE(left) == AOP_CRY &&
5002         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5003         if(AOP_TYPE(right) == AOP_LIT){
5004             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5005             if(lit == 0L){
5006                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5007                 pic16_emitcode("cpl","c");
5008             } else if(lit == 1L) {
5009                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5010             } else {
5011                 pic16_emitcode("clr","c");
5012             }
5013             /* AOP_TYPE(right) == AOP_CRY */
5014         } else {
5015             symbol *lbl = newiTempLabel(NULL);
5016             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5017             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5018             pic16_emitcode("cpl","c");
5019             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5020         }
5021         /* c = 1 if egal */
5022         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5023             pic16_outBitC(result);
5024             goto release ;
5025         }
5026         if (ifx) {
5027             genIfxJump (ifx,"c");
5028             goto release ;
5029         }
5030         /* if the result is used in an arithmetic operation
5031         then put the result in place */
5032         pic16_outBitC(result);
5033     } else {
5034       
5035       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5036       gencjne(left,right,result,ifx);
5037 /*
5038       if(ifx) 
5039         gencjne(left,right,newiTempLabel(NULL));
5040       else {
5041         if(IC_TRUE(ifx)->key)
5042           gencjne(left,right,IC_TRUE(ifx)->key);
5043         else
5044           gencjne(left,right,IC_FALSE(ifx)->key);
5045         ifx->generated = 1;
5046         goto release ;
5047       }
5048       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5049         pic16_aopPut(AOP(result),"a",0);
5050         goto release ;
5051       }
5052
5053       if (ifx) {
5054         genIfxJump (ifx,"a");
5055         goto release ;
5056       }
5057 */
5058       /* if the result is used in an arithmetic operation
5059          then put the result in place */
5060 /*
5061       if (AOP_TYPE(result) != AOP_CRY) 
5062         pic16_outAcc(result);
5063 */
5064       /* leave the result in acc */
5065     }
5066
5067 release:
5068     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5069     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5070     pic16_freeAsmop(result,NULL,ic,TRUE);
5071 }
5072
5073 /*-----------------------------------------------------------------*/
5074 /* ifxForOp - returns the icode containing the ifx for operand     */
5075 /*-----------------------------------------------------------------*/
5076 static iCode *ifxForOp ( operand *op, iCode *ic )
5077 {
5078     /* if true symbol then needs to be assigned */
5079     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5080     if (IS_TRUE_SYMOP(op))
5081         return NULL ;
5082
5083     /* if this has register type condition and
5084     the next instruction is ifx with the same operand
5085     and live to of the operand is upto the ifx only then */
5086     if (ic->next &&
5087         ic->next->op == IFX &&
5088         IC_COND(ic->next)->key == op->key &&
5089         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5090         return ic->next;
5091
5092     if (ic->next &&
5093         ic->next->op == IFX &&
5094         IC_COND(ic->next)->key == op->key) {
5095       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5096       return ic->next;
5097     }
5098
5099     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5100     if (ic->next &&
5101         ic->next->op == IFX)
5102       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5103
5104     if (ic->next &&
5105         ic->next->op == IFX &&
5106         IC_COND(ic->next)->key == op->key) {
5107       DEBUGpic16_emitcode ("; "," key is okay");
5108       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5109                            OP_SYMBOL(op)->liveTo,
5110                            ic->next->seq);
5111     }
5112
5113
5114     return NULL;
5115 }
5116 /*-----------------------------------------------------------------*/
5117 /* genAndOp - for && operation                                     */
5118 /*-----------------------------------------------------------------*/
5119 static void genAndOp (iCode *ic)
5120 {
5121     operand *left,*right, *result;
5122 /*     symbol *tlbl; */
5123
5124     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5125     /* note here that && operations that are in an
5126     if statement are taken away by backPatchLabels
5127     only those used in arthmetic operations remain */
5128     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5129     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5130     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5131
5132     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5133
5134     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5135     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5136     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5137
5138     /* if both are bit variables */
5139 /*     if (AOP_TYPE(left) == AOP_CRY && */
5140 /*         AOP_TYPE(right) == AOP_CRY ) { */
5141 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5142 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5143 /*         pic16_outBitC(result); */
5144 /*     } else { */
5145 /*         tlbl = newiTempLabel(NULL); */
5146 /*         pic16_toBoolean(left);     */
5147 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5148 /*         pic16_toBoolean(right); */
5149 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5150 /*         pic16_outBitAcc(result); */
5151 /*     } */
5152
5153     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5154     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5155     pic16_freeAsmop(result,NULL,ic,TRUE);
5156 }
5157
5158
5159 /*-----------------------------------------------------------------*/
5160 /* genOrOp - for || operation                                      */
5161 /*-----------------------------------------------------------------*/
5162 /*
5163   tsd pic port -
5164   modified this code, but it doesn't appear to ever get called
5165 */
5166
5167 static void genOrOp (iCode *ic)
5168 {
5169     operand *left,*right, *result;
5170     symbol *tlbl;
5171
5172     /* note here that || operations that are in an
5173     if statement are taken away by backPatchLabels
5174     only those used in arthmetic operations remain */
5175     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5176     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5177     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5178     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5179
5180     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5181
5182     /* if both are bit variables */
5183     if (AOP_TYPE(left) == AOP_CRY &&
5184         AOP_TYPE(right) == AOP_CRY ) {
5185       pic16_emitcode("clrc","");
5186       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5187                AOP(left)->aopu.aop_dir,
5188                AOP(left)->aopu.aop_dir);
5189       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5190                AOP(right)->aopu.aop_dir,
5191                AOP(right)->aopu.aop_dir);
5192       pic16_emitcode("setc","");
5193
5194     } else {
5195         tlbl = newiTempLabel(NULL);
5196         pic16_toBoolean(left);
5197         emitSKPZ;
5198         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5199         pic16_toBoolean(right);
5200         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5201
5202         pic16_outBitAcc(result);
5203     }
5204
5205     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5206     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5207     pic16_freeAsmop(result,NULL,ic,TRUE);            
5208 }
5209
5210 /*-----------------------------------------------------------------*/
5211 /* isLiteralBit - test if lit == 2^n                               */
5212 /*-----------------------------------------------------------------*/
5213 static int isLiteralBit(unsigned long lit)
5214 {
5215     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5216     0x100L,0x200L,0x400L,0x800L,
5217     0x1000L,0x2000L,0x4000L,0x8000L,
5218     0x10000L,0x20000L,0x40000L,0x80000L,
5219     0x100000L,0x200000L,0x400000L,0x800000L,
5220     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5221     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5222     int idx;
5223     
5224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5225     for(idx = 0; idx < 32; idx++)
5226         if(lit == pw[idx])
5227             return idx+1;
5228     return 0;
5229 }
5230
5231 /*-----------------------------------------------------------------*/
5232 /* continueIfTrue -                                                */
5233 /*-----------------------------------------------------------------*/
5234 static void continueIfTrue (iCode *ic)
5235 {
5236     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5237     if(IC_TRUE(ic))
5238         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5239     ic->generated = 1;
5240 }
5241
5242 /*-----------------------------------------------------------------*/
5243 /* jmpIfTrue -                                                     */
5244 /*-----------------------------------------------------------------*/
5245 static void jumpIfTrue (iCode *ic)
5246 {
5247     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5248     if(!IC_TRUE(ic))
5249         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5250     ic->generated = 1;
5251 }
5252
5253 /*-----------------------------------------------------------------*/
5254 /* jmpTrueOrFalse -                                                */
5255 /*-----------------------------------------------------------------*/
5256 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5257 {
5258     // ugly but optimized by peephole
5259     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5260     if(IC_TRUE(ic)){
5261         symbol *nlbl = newiTempLabel(NULL);
5262         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5263         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5264         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5265         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5266     }
5267     else{
5268         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5269         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5270     }
5271     ic->generated = 1;
5272 }
5273
5274 /*-----------------------------------------------------------------*/
5275 /* genAnd  - code for and                                          */
5276 /*-----------------------------------------------------------------*/
5277 static void genAnd (iCode *ic, iCode *ifx)
5278 {
5279   operand *left, *right, *result;
5280   int size, offset=0;  
5281   unsigned long lit = 0L;
5282   int bytelit = 0;
5283   resolvedIfx rIfx;
5284
5285
5286   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5287   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5288   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5289   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5290
5291   resolveIfx(&rIfx,ifx);
5292
5293   /* if left is a literal & right is not then exchange them */
5294   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5295       AOP_NEEDSACC(left)) {
5296     operand *tmp = right ;
5297     right = left;
5298     left = tmp;
5299   }
5300
5301   /* if result = right then exchange them */
5302   if(pic16_sameRegs(AOP(result),AOP(right))){
5303     operand *tmp = right ;
5304     right = left;
5305     left = tmp;
5306   }
5307
5308   /* if right is bit then exchange them */
5309   if (AOP_TYPE(right) == AOP_CRY &&
5310       AOP_TYPE(left) != AOP_CRY){
5311     operand *tmp = right ;
5312     right = left;
5313     left = tmp;
5314   }
5315   if(AOP_TYPE(right) == AOP_LIT)
5316     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5317
5318   size = AOP_SIZE(result);
5319
5320   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5321
5322   // if(bit & yy)
5323   // result = bit & yy;
5324   if (AOP_TYPE(left) == AOP_CRY){
5325     // c = bit & literal;
5326     if(AOP_TYPE(right) == AOP_LIT){
5327       if(lit & 1) {
5328         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5329           // no change
5330           goto release;
5331         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5332       } else {
5333         // bit(result) = 0;
5334         if(size && (AOP_TYPE(result) == AOP_CRY)){
5335           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5336           goto release;
5337         }
5338         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5339           jumpIfTrue(ifx);
5340           goto release;
5341         }
5342         pic16_emitcode("clr","c");
5343       }
5344     } else {
5345       if (AOP_TYPE(right) == AOP_CRY){
5346         // c = bit & bit;
5347         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5348         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5349       } else {
5350         // c = bit & val;
5351         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5352         // c = lsb
5353         pic16_emitcode("rrc","a");
5354         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5355       }
5356     }
5357     // bit = c
5358     // val = c
5359     if(size)
5360       pic16_outBitC(result);
5361     // if(bit & ...)
5362     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5363       genIfxJump(ifx, "c");           
5364     goto release ;
5365   }
5366
5367   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5368   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5369   if((AOP_TYPE(right) == AOP_LIT) &&
5370      (AOP_TYPE(result) == AOP_CRY) &&
5371      (AOP_TYPE(left) != AOP_CRY)){
5372     int posbit = isLiteralBit(lit);
5373     /* left &  2^n */
5374     if(posbit){
5375       posbit--;
5376       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5377       // bit = left & 2^n
5378       if(size)
5379         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5380       // if(left &  2^n)
5381       else{
5382         if(ifx){
5383 /*
5384           if(IC_TRUE(ifx)) {
5385             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5386             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5387           } else {
5388             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5389             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5390           }
5391 */
5392           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5393                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5394           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5395           
5396           ifx->generated = 1;
5397         }
5398         goto release;
5399       }
5400     } else {
5401       symbol *tlbl = newiTempLabel(NULL);
5402       int sizel = AOP_SIZE(left);
5403       if(size)
5404         pic16_emitcode("setb","c");
5405       while(sizel--){
5406         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5407           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5408           // byte ==  2^n ?
5409           if((posbit = isLiteralBit(bytelit)) != 0)
5410             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5411           else{
5412             if(bytelit != 0x0FFL)
5413               pic16_emitcode("anl","a,%s",
5414                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5415             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5416           }
5417         }
5418         offset++;
5419       }
5420       // bit = left & literal
5421       if(size){
5422         pic16_emitcode("clr","c");
5423         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5424       }
5425       // if(left & literal)
5426       else{
5427         if(ifx)
5428           jmpTrueOrFalse(ifx, tlbl);
5429         goto release ;
5430       }
5431     }
5432     pic16_outBitC(result);
5433     goto release ;
5434   }
5435
5436   /* if left is same as result */
5437   if(pic16_sameRegs(AOP(result),AOP(left))){
5438     int know_W = -1;
5439     for(;size--; offset++,lit>>=8) {
5440       if(AOP_TYPE(right) == AOP_LIT){
5441         switch(lit & 0xff) {
5442         case 0x00:
5443           /*  and'ing with 0 has clears the result */
5444 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5445           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5446           break;
5447         case 0xff:
5448           /* and'ing with 0xff is a nop when the result and left are the same */
5449           break;
5450
5451         default:
5452           {
5453             int p = my_powof2( (~lit) & 0xff );
5454             if(p>=0) {
5455               /* only one bit is set in the literal, so use a bcf instruction */
5456 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5457               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5458
5459             } else {
5460               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5461               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5462               if(know_W != (lit&0xff))
5463                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5464               know_W = lit &0xff;
5465               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5466             }
5467           }    
5468         }
5469       } else {
5470         if (AOP_TYPE(left) == AOP_ACC) {
5471           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5472         } else {                    
5473           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5474           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5475
5476         }
5477       }
5478     }
5479
5480   } else {
5481     // left & result in different registers
5482     if(AOP_TYPE(result) == AOP_CRY){
5483       // result = bit
5484       // if(size), result in bit
5485       // if(!size && ifx), conditional oper: if(left & right)
5486       symbol *tlbl = newiTempLabel(NULL);
5487       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5488       if(size)
5489         pic16_emitcode("setb","c");
5490       while(sizer--){
5491         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5492         pic16_emitcode("anl","a,%s",
5493                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5494         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5495         offset++;
5496       }
5497       if(size){
5498         CLRC;
5499         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5500         pic16_outBitC(result);
5501       } else if(ifx)
5502         jmpTrueOrFalse(ifx, tlbl);
5503     } else {
5504       for(;(size--);offset++) {
5505         // normal case
5506         // result = left & right
5507         if(AOP_TYPE(right) == AOP_LIT){
5508           int t = (lit >> (offset*8)) & 0x0FFL;
5509           switch(t) { 
5510           case 0x00:
5511             pic16_emitcode("clrf","%s",
5512                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5513             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5514             break;
5515           case 0xff:
5516             pic16_emitcode("movf","%s,w",
5517                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5518             pic16_emitcode("movwf","%s",
5519                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5520             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5521             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5522             break;
5523           default:
5524             pic16_emitcode("movlw","0x%x",t);
5525             pic16_emitcode("andwf","%s,w",
5526                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5527             pic16_emitcode("movwf","%s",
5528                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5529               
5530             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5531             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5532             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5533           }
5534           continue;
5535         }
5536
5537         if (AOP_TYPE(left) == AOP_ACC) {
5538           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5539           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5540         } else {
5541           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5542           pic16_emitcode("andwf","%s,w",
5543                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5544           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5545           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5546         }
5547         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5548         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5549       }
5550     }
5551   }
5552
5553   release :
5554     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5555   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5556   pic16_freeAsmop(result,NULL,ic,TRUE);     
5557 }
5558
5559 /*-----------------------------------------------------------------*/
5560 /* genOr  - code for or                                            */
5561 /*-----------------------------------------------------------------*/
5562 static void genOr (iCode *ic, iCode *ifx)
5563 {
5564     operand *left, *right, *result;
5565     int size, offset=0;
5566     unsigned long lit = 0L;
5567
5568     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5569
5570     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5571     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5572     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5573
5574     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5575
5576     /* if left is a literal & right is not then exchange them */
5577     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5578         AOP_NEEDSACC(left)) {
5579         operand *tmp = right ;
5580         right = left;
5581         left = tmp;
5582     }
5583
5584     /* if result = right then exchange them */
5585     if(pic16_sameRegs(AOP(result),AOP(right))){
5586         operand *tmp = right ;
5587         right = left;
5588         left = tmp;
5589     }
5590
5591     /* if right is bit then exchange them */
5592     if (AOP_TYPE(right) == AOP_CRY &&
5593         AOP_TYPE(left) != AOP_CRY){
5594         operand *tmp = right ;
5595         right = left;
5596         left = tmp;
5597     }
5598
5599     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5600
5601     if(AOP_TYPE(right) == AOP_LIT)
5602         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5603
5604     size = AOP_SIZE(result);
5605
5606     // if(bit | yy)
5607     // xx = bit | yy;
5608     if (AOP_TYPE(left) == AOP_CRY){
5609         if(AOP_TYPE(right) == AOP_LIT){
5610             // c = bit & literal;
5611             if(lit){
5612                 // lit != 0 => result = 1
5613                 if(AOP_TYPE(result) == AOP_CRY){
5614                   if(size)
5615                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5616                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5617                   //     AOP(result)->aopu.aop_dir,
5618                   //     AOP(result)->aopu.aop_dir);
5619                     else if(ifx)
5620                         continueIfTrue(ifx);
5621                     goto release;
5622                 }
5623             } else {
5624                 // lit == 0 => result = left
5625                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5626                     goto release;
5627                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5628             }
5629         } else {
5630             if (AOP_TYPE(right) == AOP_CRY){
5631               if(pic16_sameRegs(AOP(result),AOP(left))){
5632                 // c = bit | bit;
5633                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5634                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5635                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5636
5637                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5638                          AOP(result)->aopu.aop_dir,
5639                          AOP(result)->aopu.aop_dir);
5640                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5641                          AOP(right)->aopu.aop_dir,
5642                          AOP(right)->aopu.aop_dir);
5643                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5644                          AOP(result)->aopu.aop_dir,
5645                          AOP(result)->aopu.aop_dir);
5646               } else {
5647                 if( AOP_TYPE(result) == AOP_ACC) {
5648                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5649                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5650                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5651                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5652
5653                 } else {
5654
5655                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5656                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5657                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5658                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5659
5660                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5661                                  AOP(result)->aopu.aop_dir,
5662                                  AOP(result)->aopu.aop_dir);
5663                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5664                                  AOP(right)->aopu.aop_dir,
5665                                  AOP(right)->aopu.aop_dir);
5666                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5667                                  AOP(left)->aopu.aop_dir,
5668                                  AOP(left)->aopu.aop_dir);
5669                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5670                                  AOP(result)->aopu.aop_dir,
5671                                  AOP(result)->aopu.aop_dir);
5672                 }
5673               }
5674             } else {
5675                 // c = bit | val;
5676                 symbol *tlbl = newiTempLabel(NULL);
5677                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5678
5679
5680                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5681                 if( AOP_TYPE(right) == AOP_ACC) {
5682                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5683                   emitSKPNZ;
5684                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5685                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5686                 }
5687
5688
5689
5690                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5691                     pic16_emitcode(";XXX setb","c");
5692                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5693                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5694                 pic16_toBoolean(right);
5695                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5696                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5697                     jmpTrueOrFalse(ifx, tlbl);
5698                     goto release;
5699                 } else {
5700                     CLRC;
5701                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5702                 }
5703             }
5704         }
5705         // bit = c
5706         // val = c
5707         if(size)
5708             pic16_outBitC(result);
5709         // if(bit | ...)
5710         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5711             genIfxJump(ifx, "c");           
5712         goto release ;
5713     }
5714
5715     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5716     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5717     if((AOP_TYPE(right) == AOP_LIT) &&
5718        (AOP_TYPE(result) == AOP_CRY) &&
5719        (AOP_TYPE(left) != AOP_CRY)){
5720         if(lit){
5721           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5722             // result = 1
5723             if(size)
5724                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5725             else 
5726                 continueIfTrue(ifx);
5727             goto release;
5728         } else {
5729           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5730             // lit = 0, result = boolean(left)
5731             if(size)
5732                 pic16_emitcode(";XXX setb","c");
5733             pic16_toBoolean(right);
5734             if(size){
5735                 symbol *tlbl = newiTempLabel(NULL);
5736                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5737                 CLRC;
5738                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5739             } else {
5740                 genIfxJump (ifx,"a");
5741                 goto release;
5742             }
5743         }
5744         pic16_outBitC(result);
5745         goto release ;
5746     }
5747
5748     /* if left is same as result */
5749     if(pic16_sameRegs(AOP(result),AOP(left))){
5750       int know_W = -1;
5751       for(;size--; offset++,lit>>=8) {
5752         if(AOP_TYPE(right) == AOP_LIT){
5753           if((lit & 0xff) == 0)
5754             /*  or'ing with 0 has no effect */
5755             continue;
5756           else {
5757             int p = my_powof2(lit & 0xff);
5758             if(p>=0) {
5759               /* only one bit is set in the literal, so use a bsf instruction */
5760               pic16_emitpcode(POC_BSF,
5761                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5762             } else {
5763               if(know_W != (lit & 0xff))
5764                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5765               know_W = lit & 0xff;
5766               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5767             }
5768                     
5769           }
5770         } else {
5771           if (AOP_TYPE(left) == AOP_ACC) {
5772             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5773             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5774           } else {                  
5775             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5776             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5777
5778             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5779             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5780
5781           }
5782         }
5783       }
5784     } else {
5785         // left & result in different registers
5786         if(AOP_TYPE(result) == AOP_CRY){
5787             // result = bit
5788             // if(size), result in bit
5789             // if(!size && ifx), conditional oper: if(left | right)
5790             symbol *tlbl = newiTempLabel(NULL);
5791             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5792             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5793
5794
5795             if(size)
5796                 pic16_emitcode(";XXX setb","c");
5797             while(sizer--){
5798                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5799                 pic16_emitcode(";XXX orl","a,%s",
5800                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5801                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5802                 offset++;
5803             }
5804             if(size){
5805                 CLRC;
5806                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5807                 pic16_outBitC(result);
5808             } else if(ifx)
5809                 jmpTrueOrFalse(ifx, tlbl);
5810         } else for(;(size--);offset++){
5811           // normal case
5812           // result = left & right
5813           if(AOP_TYPE(right) == AOP_LIT){
5814             int t = (lit >> (offset*8)) & 0x0FFL;
5815             switch(t) { 
5816             case 0x00:
5817               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5818               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5819
5820               pic16_emitcode("movf","%s,w",
5821                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5822               pic16_emitcode("movwf","%s",
5823                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5824               break;
5825             default:
5826               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5827               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5828               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5829
5830               pic16_emitcode("movlw","0x%x",t);
5831               pic16_emitcode("iorwf","%s,w",
5832                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5833               pic16_emitcode("movwf","%s",
5834                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5835               
5836             }
5837             continue;
5838           }
5839
5840           // faster than result <- left, anl result,right
5841           // and better if result is SFR
5842           if (AOP_TYPE(left) == AOP_ACC) {
5843             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5844             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5845           } else {
5846             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5847             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5848
5849             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5850             pic16_emitcode("iorwf","%s,w",
5851                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5852           }
5853           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5854           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5855         }
5856     }
5857
5858 release :
5859     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5860     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5861     pic16_freeAsmop(result,NULL,ic,TRUE);     
5862 }
5863
5864 /*-----------------------------------------------------------------*/
5865 /* genXor - code for xclusive or                                   */
5866 /*-----------------------------------------------------------------*/
5867 static void genXor (iCode *ic, iCode *ifx)
5868 {
5869   operand *left, *right, *result;
5870   int size, offset=0;
5871   unsigned long lit = 0L;
5872
5873   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5874
5875   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5876   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5877   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5878
5879   /* if left is a literal & right is not ||
5880      if left needs acc & right does not */
5881   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5882       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5883     operand *tmp = right ;
5884     right = left;
5885     left = tmp;
5886   }
5887
5888   /* if result = right then exchange them */
5889   if(pic16_sameRegs(AOP(result),AOP(right))){
5890     operand *tmp = right ;
5891     right = left;
5892     left = tmp;
5893   }
5894
5895   /* if right is bit then exchange them */
5896   if (AOP_TYPE(right) == AOP_CRY &&
5897       AOP_TYPE(left) != AOP_CRY){
5898     operand *tmp = right ;
5899     right = left;
5900     left = tmp;
5901   }
5902   if(AOP_TYPE(right) == AOP_LIT)
5903     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5904
5905   size = AOP_SIZE(result);
5906
5907   // if(bit ^ yy)
5908   // xx = bit ^ yy;
5909   if (AOP_TYPE(left) == AOP_CRY){
5910     if(AOP_TYPE(right) == AOP_LIT){
5911       // c = bit & literal;
5912       if(lit>>1){
5913         // lit>>1  != 0 => result = 1
5914         if(AOP_TYPE(result) == AOP_CRY){
5915           if(size)
5916             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
5917             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5918           else if(ifx)
5919             continueIfTrue(ifx);
5920           goto release;
5921         }
5922         pic16_emitcode("setb","c");
5923       } else{
5924         // lit == (0 or 1)
5925         if(lit == 0){
5926           // lit == 0, result = left
5927           if(size && pic16_sameRegs(AOP(result),AOP(left)))
5928             goto release;
5929           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5930         } else{
5931           // lit == 1, result = not(left)
5932           if(size && pic16_sameRegs(AOP(result),AOP(left))){
5933             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
5934             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
5935             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5936             goto release;
5937           } else {
5938             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5939             pic16_emitcode("cpl","c");
5940           }
5941         }
5942       }
5943
5944     } else {
5945       // right != literal
5946       symbol *tlbl = newiTempLabel(NULL);
5947       if (AOP_TYPE(right) == AOP_CRY){
5948         // c = bit ^ bit;
5949         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5950       }
5951       else{
5952         int sizer = AOP_SIZE(right);
5953         // c = bit ^ val
5954         // if val>>1 != 0, result = 1
5955         pic16_emitcode("setb","c");
5956         while(sizer){
5957           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
5958           if(sizer == 1)
5959             // test the msb of the lsb
5960             pic16_emitcode("anl","a,#0xfe");
5961           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5962           sizer--;
5963         }
5964         // val = (0,1)
5965         pic16_emitcode("rrc","a");
5966       }
5967       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5968       pic16_emitcode("cpl","c");
5969       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
5970     }
5971     // bit = c
5972     // val = c
5973     if(size)
5974       pic16_outBitC(result);
5975     // if(bit | ...)
5976     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5977       genIfxJump(ifx, "c");           
5978     goto release ;
5979   }
5980
5981   if(pic16_sameRegs(AOP(result),AOP(left))){
5982     /* if left is same as result */
5983     for(;size--; offset++) {
5984       if(AOP_TYPE(right) == AOP_LIT){
5985         int t  = (lit >> (offset*8)) & 0x0FFL;
5986         if(t == 0x00L)
5987           continue;
5988         else
5989           if (IS_AOP_PREG(left)) {
5990             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5991             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5992             pic16_aopPut(AOP(result),"a",offset);
5993           } else {
5994             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5995             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5996             pic16_emitcode("xrl","%s,%s",
5997                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
5998                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5999           }
6000       } else {
6001         if (AOP_TYPE(left) == AOP_ACC)
6002           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6003         else {
6004           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6005           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6006 /*
6007           if (IS_AOP_PREG(left)) {
6008             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6009             pic16_aopPut(AOP(result),"a",offset);
6010           } else
6011             pic16_emitcode("xrl","%s,a",
6012                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6013 */
6014         }
6015       }
6016     }
6017   } else {
6018     // left & result in different registers
6019     if(AOP_TYPE(result) == AOP_CRY){
6020       // result = bit
6021       // if(size), result in bit
6022       // if(!size && ifx), conditional oper: if(left ^ right)
6023       symbol *tlbl = newiTempLabel(NULL);
6024       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6025       if(size)
6026         pic16_emitcode("setb","c");
6027       while(sizer--){
6028         if((AOP_TYPE(right) == AOP_LIT) &&
6029            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6030           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6031         } else {
6032           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6033           pic16_emitcode("xrl","a,%s",
6034                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6035         }
6036         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6037         offset++;
6038       }
6039       if(size){
6040         CLRC;
6041         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6042         pic16_outBitC(result);
6043       } else if(ifx)
6044         jmpTrueOrFalse(ifx, tlbl);
6045     } else for(;(size--);offset++){
6046       // normal case
6047       // result = left & right
6048       if(AOP_TYPE(right) == AOP_LIT){
6049         int t = (lit >> (offset*8)) & 0x0FFL;
6050         switch(t) { 
6051         case 0x00:
6052           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6053           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6054           pic16_emitcode("movf","%s,w",
6055                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6056           pic16_emitcode("movwf","%s",
6057                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6058           break;
6059         case 0xff:
6060           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6061           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6062           pic16_emitcode("comf","%s,w",
6063                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6064           pic16_emitcode("movwf","%s",
6065                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6066           break;
6067         default:
6068           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6069           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6070           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6071           pic16_emitcode("movlw","0x%x",t);
6072           pic16_emitcode("xorwf","%s,w",
6073                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6074           pic16_emitcode("movwf","%s",
6075                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6076
6077         }
6078         continue;
6079       }
6080
6081       // faster than result <- left, anl result,right
6082       // and better if result is SFR
6083       if (AOP_TYPE(left) == AOP_ACC) {
6084         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6085         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6086       } else {
6087         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6088         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6089         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6090         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6091       }
6092       if ( AOP_TYPE(result) != AOP_ACC){
6093         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6094         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6095       }
6096     }
6097   }
6098
6099   release :
6100     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6101   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6102   pic16_freeAsmop(result,NULL,ic,TRUE);     
6103 }
6104
6105 /*-----------------------------------------------------------------*/
6106 /* genInline - write the inline code out                           */
6107 /*-----------------------------------------------------------------*/
6108 static void genInline (iCode *ic)
6109 {
6110     char *buffer, *bp, *bp1;
6111     
6112     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6113
6114     _G.inLine += (!options.asmpeep);
6115
6116     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6117     strcpy(buffer,IC_INLINE(ic));
6118
6119     /* emit each line as a code */
6120     while (*bp) {
6121         if (*bp == '\n') {
6122             *bp++ = '\0';
6123
6124             if(*bp1)
6125               pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6126             bp1 = bp;
6127         } else {
6128             if (*bp == ':') {
6129                 bp++;
6130                 *bp = '\0';
6131                 bp++;
6132                 pic16_emitcode(bp1,"");
6133                 bp1 = bp;
6134             } else
6135                 bp++;
6136         }
6137     }
6138     if ((bp1 != bp) && *bp1)
6139       pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6140
6141     Safe_free(buffer);
6142
6143     _G.inLine -= (!options.asmpeep);
6144 }
6145
6146 /*-----------------------------------------------------------------*/
6147 /* genRRC - rotate right with carry                                */
6148 /*-----------------------------------------------------------------*/
6149 static void genRRC (iCode *ic)
6150 {
6151   operand *left , *result ;
6152   int size, offset = 0, same;
6153
6154   /* rotate right with carry */
6155   left = IC_LEFT(ic);
6156   result=IC_RESULT(ic);
6157   pic16_aopOp (left,ic,FALSE);
6158   pic16_aopOp (result,ic,FALSE);
6159
6160   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6161
6162   same = pic16_sameRegs(AOP(result),AOP(left));
6163
6164   size = AOP_SIZE(result);    
6165
6166   /* get the lsb and put it into the carry */
6167   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6168
6169   offset = 0 ;
6170
6171   while(size--) {
6172
6173     if(same) {
6174       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6175     } else {
6176       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6177       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6178     }
6179
6180     offset++;
6181   }
6182
6183   pic16_freeAsmop(left,NULL,ic,TRUE);
6184   pic16_freeAsmop(result,NULL,ic,TRUE);
6185 }
6186
6187 /*-----------------------------------------------------------------*/
6188 /* genRLC - generate code for rotate left with carry               */
6189 /*-----------------------------------------------------------------*/
6190 static void genRLC (iCode *ic)
6191 {    
6192   operand *left , *result ;
6193   int size, offset = 0;
6194   int same;
6195
6196   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6197   /* rotate right with carry */
6198   left = IC_LEFT(ic);
6199   result=IC_RESULT(ic);
6200   pic16_aopOp (left,ic,FALSE);
6201   pic16_aopOp (result,ic,FALSE);
6202
6203   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6204
6205   same = pic16_sameRegs(AOP(result),AOP(left));
6206
6207   /* move it to the result */
6208   size = AOP_SIZE(result);    
6209
6210   /* get the msb and put it into the carry */
6211   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6212
6213   offset = 0 ;
6214
6215   while(size--) {
6216
6217     if(same) {
6218       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6219     } else {
6220       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6221       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6222     }
6223
6224     offset++;
6225   }
6226
6227
6228   pic16_freeAsmop(left,NULL,ic,TRUE);
6229   pic16_freeAsmop(result,NULL,ic,TRUE);
6230 }
6231
6232 /*-----------------------------------------------------------------*/
6233 /* genGetHbit - generates code get highest order bit               */
6234 /*-----------------------------------------------------------------*/
6235 static void genGetHbit (iCode *ic)
6236 {
6237     operand *left, *result;
6238     left = IC_LEFT(ic);
6239     result=IC_RESULT(ic);
6240     pic16_aopOp (left,ic,FALSE);
6241     pic16_aopOp (result,ic,FALSE);
6242
6243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6244     /* get the highest order byte into a */
6245     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6246     if(AOP_TYPE(result) == AOP_CRY){
6247         pic16_emitcode("rlc","a");
6248         pic16_outBitC(result);
6249     }
6250     else{
6251         pic16_emitcode("rl","a");
6252         pic16_emitcode("anl","a,#0x01");
6253         pic16_outAcc(result);
6254     }
6255
6256
6257     pic16_freeAsmop(left,NULL,ic,TRUE);
6258     pic16_freeAsmop(result,NULL,ic,TRUE);
6259 }
6260
6261 /*-----------------------------------------------------------------*/
6262 /* AccRol - rotate left accumulator by known count                 */
6263 /*-----------------------------------------------------------------*/
6264 static void AccRol (int shCount)
6265 {
6266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6267     shCount &= 0x0007;              // shCount : 0..7
6268     switch(shCount){
6269         case 0 :
6270             break;
6271         case 1 :
6272             pic16_emitcode("rl","a");
6273             break;
6274         case 2 :
6275             pic16_emitcode("rl","a");
6276             pic16_emitcode("rl","a");
6277             break;
6278         case 3 :
6279             pic16_emitcode("swap","a");
6280             pic16_emitcode("rr","a");
6281             break;
6282         case 4 :
6283             pic16_emitcode("swap","a");
6284             break;
6285         case 5 :
6286             pic16_emitcode("swap","a");
6287             pic16_emitcode("rl","a");
6288             break;
6289         case 6 :
6290             pic16_emitcode("rr","a");
6291             pic16_emitcode("rr","a");
6292             break;
6293         case 7 :
6294             pic16_emitcode("rr","a");
6295             break;
6296     }
6297 }
6298
6299 /*-----------------------------------------------------------------*/
6300 /* AccLsh - left shift accumulator by known count                  */
6301 /*-----------------------------------------------------------------*/
6302 static void AccLsh (int shCount)
6303 {
6304     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6305     if(shCount != 0){
6306         if(shCount == 1)
6307             pic16_emitcode("add","a,acc");
6308         else 
6309             if(shCount == 2) {
6310             pic16_emitcode("add","a,acc");
6311             pic16_emitcode("add","a,acc");
6312         } else {
6313             /* rotate left accumulator */
6314             AccRol(shCount);
6315             /* and kill the lower order bits */
6316             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6317         }
6318     }
6319 }
6320
6321 /*-----------------------------------------------------------------*/
6322 /* AccRsh - right shift accumulator by known count                 */
6323 /*-----------------------------------------------------------------*/
6324 static void AccRsh (int shCount)
6325 {
6326     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6327     if(shCount != 0){
6328         if(shCount == 1){
6329             CLRC;
6330             pic16_emitcode("rrc","a");
6331         } else {
6332             /* rotate right accumulator */
6333             AccRol(8 - shCount);
6334             /* and kill the higher order bits */
6335             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6336         }
6337     }
6338 }
6339
6340 #if 0
6341 /*-----------------------------------------------------------------*/
6342 /* AccSRsh - signed right shift accumulator by known count                 */
6343 /*-----------------------------------------------------------------*/
6344 static void AccSRsh (int shCount)
6345 {
6346     symbol *tlbl ;
6347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6348     if(shCount != 0){
6349         if(shCount == 1){
6350             pic16_emitcode("mov","c,acc.7");
6351             pic16_emitcode("rrc","a");
6352         } else if(shCount == 2){
6353             pic16_emitcode("mov","c,acc.7");
6354             pic16_emitcode("rrc","a");
6355             pic16_emitcode("mov","c,acc.7");
6356             pic16_emitcode("rrc","a");
6357         } else {
6358             tlbl = newiTempLabel(NULL);
6359             /* rotate right accumulator */
6360             AccRol(8 - shCount);
6361             /* and kill the higher order bits */
6362             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6363             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6364             pic16_emitcode("orl","a,#0x%02x",
6365                      (unsigned char)~SRMask[shCount]);
6366             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6367         }
6368     }
6369 }
6370 #endif
6371 /*-----------------------------------------------------------------*/
6372 /* shiftR1Left2Result - shift right one byte from left to result   */
6373 /*-----------------------------------------------------------------*/
6374 static void shiftR1Left2ResultSigned (operand *left, int offl,
6375                                 operand *result, int offr,
6376                                 int shCount)
6377 {
6378   int same;
6379
6380   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6381
6382   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6383
6384   switch(shCount) {
6385   case 1:
6386     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6387     if(same) 
6388       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6389     else {
6390       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6391       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6392     }
6393
6394     break;
6395   case 2:
6396
6397     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6398     if(same) 
6399       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6400     else {
6401       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6402       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6403     }
6404     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6405     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6406
6407     break;
6408
6409   case 3:
6410     if(same)
6411       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6412     else {
6413       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6414       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6415     }
6416
6417     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6418     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6419     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6420
6421     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6422     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6423
6424     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6425     break;
6426
6427   case 4:
6428     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6429     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6430     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6431     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6432     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6433     break;
6434   case 5:
6435     if(same) {
6436       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6437     } else {
6438       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6439       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6440     }
6441     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6442     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6443     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6444     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6445     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6446     break;
6447
6448   case 6:
6449     if(same) {
6450       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6451       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6452       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6453       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6454       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6455       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6456     } else {
6457       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6458       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6459       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6460       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6461       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6462     }
6463     break;
6464
6465   case 7:
6466     if(same) {
6467       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6468       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6469       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6470       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6471     } else {
6472       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6473       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6474       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6475     }
6476
6477   default:
6478     break;
6479   }
6480 }
6481
6482 /*-----------------------------------------------------------------*/
6483 /* shiftR1Left2Result - shift right one byte from left to result   */
6484 /*-----------------------------------------------------------------*/
6485 static void shiftR1Left2Result (operand *left, int offl,
6486                                 operand *result, int offr,
6487                                 int shCount, int sign)
6488 {
6489   int same;
6490
6491   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6492
6493   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6494
6495   /* Copy the msb into the carry if signed. */
6496   if(sign) {
6497     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6498     return;
6499   }
6500
6501
6502
6503   switch(shCount) {
6504   case 1:
6505     emitCLRC;
6506     if(same) 
6507       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6508     else {
6509       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6510       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6511     }
6512     break;
6513   case 2:
6514     emitCLRC;
6515     if(same) {
6516       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6517     } else {
6518       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6519       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6520     }
6521     emitCLRC;
6522     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6523
6524     break;
6525   case 3:
6526     if(same)
6527       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6528     else {
6529       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6530       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6531     }
6532
6533     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6534     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6535     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6536     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6537     break;
6538       
6539   case 4:
6540     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6541     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6542     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6543     break;
6544
6545   case 5:
6546     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6547     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6548     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6549     emitCLRC;
6550     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6551
6552     break;
6553   case 6:
6554
6555     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6556     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6557     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6558     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6559     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6560     break;
6561
6562   case 7:
6563
6564     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6565     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6566     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6567
6568     break;
6569
6570   default:
6571     break;
6572   }
6573 }
6574
6575 /*-----------------------------------------------------------------*/
6576 /* shiftL1Left2Result - shift left one byte from left to result    */
6577 /*-----------------------------------------------------------------*/
6578 static void shiftL1Left2Result (operand *left, int offl,
6579                                 operand *result, int offr, int shCount)
6580 {
6581   int same;
6582
6583   //    char *l;
6584   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6585
6586   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6587   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6588     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6589     //    MOVA(l);
6590     /* shift left accumulator */
6591     //AccLsh(shCount); // don't comment out just yet...
6592   //    pic16_aopPut(AOP(result),"a",offr);
6593
6594   switch(shCount) {
6595   case 1:
6596     /* Shift left 1 bit position */
6597     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6598     if(same) {
6599       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6600     } else {
6601       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6602       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6603     }
6604     break;
6605   case 2:
6606     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6607     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6608     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6609     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6610     break;
6611   case 3:
6612     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6613     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6614     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6615     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6616     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6617     break;
6618   case 4:
6619     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6620     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6621     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6622     break;
6623   case 5:
6624     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6625     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6626     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6627     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6628     break;
6629   case 6:
6630     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6631     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6632     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6633     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6634     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6635     break;
6636   case 7:
6637     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6638     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6639     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6640     break;
6641
6642   default:
6643     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6644   }
6645
6646 }
6647
6648 /*-----------------------------------------------------------------*/
6649 /* movLeft2Result - move byte from left to result                  */
6650 /*-----------------------------------------------------------------*/
6651 static void movLeft2Result (operand *left, int offl,
6652                             operand *result, int offr)
6653 {
6654   char *l;
6655   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6656   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6657     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6658
6659     if (*l == '@' && (IS_AOP_PREG(result))) {
6660       pic16_emitcode("mov","a,%s",l);
6661       pic16_aopPut(AOP(result),"a",offr);
6662     } else {
6663       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6664       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6665     }
6666   }
6667 }
6668
6669 /*-----------------------------------------------------------------*/
6670 /* shiftL2Left2Result - shift left two bytes from left to result   */
6671 /*-----------------------------------------------------------------*/
6672 static void shiftL2Left2Result (operand *left, int offl,
6673                                 operand *result, int offr, int shCount)
6674 {
6675
6676
6677   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6678
6679   if(pic16_sameRegs(AOP(result), AOP(left))) {
6680     switch(shCount) {
6681     case 0:
6682       break;
6683     case 1:
6684     case 2:
6685     case 3:
6686
6687       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6688       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6689       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6690
6691       while(--shCount) {
6692         emitCLRC;
6693         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6694         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6695       }
6696
6697       break;
6698     case 4:
6699     case 5:
6700       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6701       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6702       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6703       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6704       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6705       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6706       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6707       if(shCount >=5) {
6708         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6709         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6710       }
6711       break;
6712     case 6:
6713       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6714       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6715       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6716       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6717       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6718       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6719       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6720       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6721       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6722       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6723       break;
6724     case 7:
6725       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6726       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6727       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6728       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6729       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6730     }
6731
6732   } else {
6733     switch(shCount) {
6734     case 0:
6735       break;
6736     case 1:
6737     case 2:
6738     case 3:
6739       /* note, use a mov/add for the shift since the mov has a
6740          chance of getting optimized out */
6741       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6742       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6743       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6744       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6745       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6746
6747       while(--shCount) {
6748         emitCLRC;
6749         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6750         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6751       }
6752       break;
6753
6754     case 4:
6755     case 5:
6756       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6757       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6758       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6759       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6760       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6761       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6762       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6763       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6764
6765
6766       if(shCount == 5) {
6767         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6768         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6769       }
6770       break;
6771     case 6:
6772       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6773       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6774       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6775       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6776
6777       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6778       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6779       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6780       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6781       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6782       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6783       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6784       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6785       break;
6786     case 7:
6787       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6788       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6789       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6790       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6791       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6792     }
6793   }
6794
6795 }
6796 /*-----------------------------------------------------------------*/
6797 /* shiftR2Left2Result - shift right two bytes from left to result  */
6798 /*-----------------------------------------------------------------*/
6799 static void shiftR2Left2Result (operand *left, int offl,
6800                                 operand *result, int offr,
6801                                 int shCount, int sign)
6802 {
6803   int same=0;
6804
6805   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6806   same = pic16_sameRegs(AOP(result), AOP(left));
6807
6808   if(same && ((offl + MSB16) == offr)){
6809     same=1;
6810     /* don't crash result[offr] */
6811     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6812     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6813   }
6814 /* else {
6815     movLeft2Result(left,offl, result, offr);
6816     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6817   }
6818 */
6819   /* a:x >> shCount (x = lsb(result))*/
6820 /*
6821   if(sign)
6822     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6823   else {
6824     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6825 */
6826   switch(shCount) {
6827   case 0:
6828     break;
6829   case 1:
6830   case 2:
6831   case 3:
6832     if(sign)
6833       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6834     else
6835       emitCLRC;
6836
6837     if(same) {
6838       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6839       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6840     } else {
6841       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6842       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6843       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6844       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6845     }
6846
6847     while(--shCount) {
6848       if(sign)
6849         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6850       else
6851         emitCLRC;
6852       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6853       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6854     }
6855     break;
6856   case 4:
6857   case 5:
6858     if(same) {
6859
6860       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
6861       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
6862       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6863
6864       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6865       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
6866       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6867       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6868     } else {
6869       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6870       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6871       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6872
6873       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6874       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6875       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6876       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6877       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6878     }
6879
6880     if(shCount >=5) {
6881       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6882       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6883     }
6884
6885     if(sign) {
6886       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
6887       pic16_emitpcode(POC_BTFSC, 
6888                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6889       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6890     }
6891
6892     break;
6893
6894   case 6:
6895     if(same) {
6896
6897       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6898       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6899
6900       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6901       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6902       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6903       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6904       if(sign) {
6905         pic16_emitpcode(POC_BTFSC, 
6906                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6907         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6908       }
6909       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6910       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
6911       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6912       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6913     } else {
6914       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6915       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6916       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6917       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6918       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6919       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6920       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
6921       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6922       if(sign) {
6923         pic16_emitpcode(POC_BTFSC, 
6924                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6925         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6926       }
6927       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6928       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6929
6930         
6931     }
6932
6933     break;
6934   case 7:
6935     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6936     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6937     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6938     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
6939     if(sign) {
6940       emitSKPNC;
6941       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
6942     } else 
6943       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6944   }
6945 }
6946
6947
6948 /*-----------------------------------------------------------------*/
6949 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6950 /*-----------------------------------------------------------------*/
6951 static void shiftLLeftOrResult (operand *left, int offl,
6952                                 operand *result, int offr, int shCount)
6953 {
6954     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6955     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6956     /* shift left accumulator */
6957     AccLsh(shCount);
6958     /* or with result */
6959     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6960     /* back to result */
6961     pic16_aopPut(AOP(result),"a",offr);
6962 }
6963
6964 /*-----------------------------------------------------------------*/
6965 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6966 /*-----------------------------------------------------------------*/
6967 static void shiftRLeftOrResult (operand *left, int offl,
6968                                 operand *result, int offr, int shCount)
6969 {
6970     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6971     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6972     /* shift right accumulator */
6973     AccRsh(shCount);
6974     /* or with result */
6975     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6976     /* back to result */
6977     pic16_aopPut(AOP(result),"a",offr);
6978 }
6979
6980 /*-----------------------------------------------------------------*/
6981 /* genlshOne - left shift a one byte quantity by known count       */
6982 /*-----------------------------------------------------------------*/
6983 static void genlshOne (operand *result, operand *left, int shCount)
6984 {       
6985     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6986     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6987 }
6988
6989 /*-----------------------------------------------------------------*/
6990 /* genlshTwo - left shift two bytes by known amount != 0           */
6991 /*-----------------------------------------------------------------*/
6992 static void genlshTwo (operand *result,operand *left, int shCount)
6993 {
6994     int size;
6995     
6996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6997     size = pic16_getDataSize(result);
6998
6999     /* if shCount >= 8 */
7000     if (shCount >= 8) {
7001         shCount -= 8 ;
7002
7003         if (size > 1){
7004             if (shCount)
7005                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7006             else 
7007                 movLeft2Result(left, LSB, result, MSB16);
7008         }
7009         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7010     }
7011
7012     /*  1 <= shCount <= 7 */
7013     else {  
7014         if(size == 1)
7015             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7016         else 
7017             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7018     }
7019 }
7020
7021 /*-----------------------------------------------------------------*/
7022 /* shiftLLong - shift left one long from left to result            */
7023 /* offl = LSB or MSB16                                             */
7024 /*-----------------------------------------------------------------*/
7025 static void shiftLLong (operand *left, operand *result, int offr )
7026 {
7027     char *l;
7028     int size = AOP_SIZE(result);
7029
7030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7031     if(size >= LSB+offr){
7032         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7033         MOVA(l);
7034         pic16_emitcode("add","a,acc");
7035         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7036             size >= MSB16+offr && offr != LSB )
7037             pic16_emitcode("xch","a,%s",
7038                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7039         else        
7040             pic16_aopPut(AOP(result),"a",LSB+offr);
7041     }
7042
7043     if(size >= MSB16+offr){
7044         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7045             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7046             MOVA(l);
7047         }
7048         pic16_emitcode("rlc","a");
7049         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7050             size >= MSB24+offr && offr != LSB)
7051             pic16_emitcode("xch","a,%s",
7052                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7053         else        
7054             pic16_aopPut(AOP(result),"a",MSB16+offr);
7055     }
7056
7057     if(size >= MSB24+offr){
7058         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7059             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7060             MOVA(l);
7061         }
7062         pic16_emitcode("rlc","a");
7063         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7064             size >= MSB32+offr && offr != LSB )
7065             pic16_emitcode("xch","a,%s",
7066                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7067         else        
7068             pic16_aopPut(AOP(result),"a",MSB24+offr);
7069     }
7070
7071     if(size > MSB32+offr){
7072         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7073             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7074             MOVA(l);    
7075         }
7076         pic16_emitcode("rlc","a");
7077         pic16_aopPut(AOP(result),"a",MSB32+offr);
7078     }
7079     if(offr != LSB)
7080         pic16_aopPut(AOP(result),zero,LSB);       
7081 }
7082
7083 /*-----------------------------------------------------------------*/
7084 /* genlshFour - shift four byte by a known amount != 0             */
7085 /*-----------------------------------------------------------------*/
7086 static void genlshFour (operand *result, operand *left, int shCount)
7087 {
7088     int size;
7089
7090     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7091     size = AOP_SIZE(result);
7092
7093     /* if shifting more that 3 bytes */
7094     if (shCount >= 24 ) {
7095         shCount -= 24;
7096         if (shCount)
7097             /* lowest order of left goes to the highest
7098             order of the destination */
7099             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7100         else
7101             movLeft2Result(left, LSB, result, MSB32);
7102         pic16_aopPut(AOP(result),zero,LSB);
7103         pic16_aopPut(AOP(result),zero,MSB16);
7104         pic16_aopPut(AOP(result),zero,MSB32);
7105         return;
7106     }
7107
7108     /* more than two bytes */
7109     else if ( shCount >= 16 ) {
7110         /* lower order two bytes goes to higher order two bytes */
7111         shCount -= 16;
7112         /* if some more remaining */
7113         if (shCount)
7114             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7115         else {
7116             movLeft2Result(left, MSB16, result, MSB32);
7117             movLeft2Result(left, LSB, result, MSB24);
7118         }
7119         pic16_aopPut(AOP(result),zero,MSB16);
7120         pic16_aopPut(AOP(result),zero,LSB);
7121         return;
7122     }    
7123
7124     /* if more than 1 byte */
7125     else if ( shCount >= 8 ) {
7126         /* lower order three bytes goes to higher order  three bytes */
7127         shCount -= 8;
7128         if(size == 2){
7129             if(shCount)
7130                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7131             else
7132                 movLeft2Result(left, LSB, result, MSB16);
7133         }
7134         else{   /* size = 4 */
7135             if(shCount == 0){
7136                 movLeft2Result(left, MSB24, result, MSB32);
7137                 movLeft2Result(left, MSB16, result, MSB24);
7138                 movLeft2Result(left, LSB, result, MSB16);
7139                 pic16_aopPut(AOP(result),zero,LSB);
7140             }
7141             else if(shCount == 1)
7142                 shiftLLong(left, result, MSB16);
7143             else{
7144                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7145                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7146                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7147                 pic16_aopPut(AOP(result),zero,LSB);
7148             }
7149         }
7150     }
7151
7152     /* 1 <= shCount <= 7 */
7153     else if(shCount <= 2){
7154         shiftLLong(left, result, LSB);
7155         if(shCount == 2)
7156             shiftLLong(result, result, LSB);
7157     }
7158     /* 3 <= shCount <= 7, optimize */
7159     else{
7160         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7161         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7162         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7163     }
7164 }
7165
7166 /*-----------------------------------------------------------------*/
7167 /* genLeftShiftLiteral - left shifting by known count              */
7168 /*-----------------------------------------------------------------*/
7169 static void genLeftShiftLiteral (operand *left,
7170                                  operand *right,
7171                                  operand *result,
7172                                  iCode *ic)
7173 {    
7174     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7175     int size;
7176
7177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7178     pic16_freeAsmop(right,NULL,ic,TRUE);
7179
7180     pic16_aopOp(left,ic,FALSE);
7181     pic16_aopOp(result,ic,FALSE);
7182
7183     size = getSize(operandType(result));
7184
7185 #if VIEW_SIZE
7186     pic16_emitcode("; shift left ","result %d, left %d",size,
7187              AOP_SIZE(left));
7188 #endif
7189
7190     /* I suppose that the left size >= result size */
7191     if(shCount == 0){
7192         while(size--){
7193             movLeft2Result(left, size, result, size);
7194         }
7195     }
7196
7197     else if(shCount >= (size * 8))
7198         while(size--)
7199             pic16_aopPut(AOP(result),zero,size);
7200     else{
7201         switch (size) {
7202             case 1:
7203                 genlshOne (result,left,shCount);
7204                 break;
7205
7206             case 2:
7207             case 3:
7208                 genlshTwo (result,left,shCount);
7209                 break;
7210
7211             case 4:
7212                 genlshFour (result,left,shCount);
7213                 break;
7214         }
7215     }
7216     pic16_freeAsmop(left,NULL,ic,TRUE);
7217     pic16_freeAsmop(result,NULL,ic,TRUE);
7218 }
7219
7220 /*-----------------------------------------------------------------*
7221  * genMultiAsm - repeat assembly instruction for size of register.
7222  * if endian == 1, then the high byte (i.e base address + size of 
7223  * register) is used first else the low byte is used first;
7224  *-----------------------------------------------------------------*/
7225 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7226 {
7227
7228   int offset = 0;
7229
7230   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7231
7232   if(!reg)
7233     return;
7234
7235   if(!endian) {
7236     endian = 1;
7237   } else {
7238     endian = -1;
7239     offset = size-1;
7240   }
7241
7242   while(size--) {
7243     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7244     offset += endian;
7245   }
7246
7247 }
7248 /*-----------------------------------------------------------------*/
7249 /* genLeftShift - generates code for left shifting                 */
7250 /*-----------------------------------------------------------------*/
7251 static void genLeftShift (iCode *ic)
7252 {
7253   operand *left,*right, *result;
7254   int size, offset;
7255   char *l;
7256   symbol *tlbl , *tlbl1;
7257   pCodeOp *pctemp;
7258
7259   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7260
7261   right = IC_RIGHT(ic);
7262   left  = IC_LEFT(ic);
7263   result = IC_RESULT(ic);
7264
7265   pic16_aopOp(right,ic,FALSE);
7266
7267   /* if the shift count is known then do it 
7268      as efficiently as possible */
7269   if (AOP_TYPE(right) == AOP_LIT) {
7270     genLeftShiftLiteral (left,right,result,ic);
7271     return ;
7272   }
7273
7274   /* shift count is unknown then we have to form 
7275      a loop get the loop count in B : Note: we take
7276      only the lower order byte since shifting
7277      more that 32 bits make no sense anyway, ( the
7278      largest size of an object can be only 32 bits ) */  
7279
7280     
7281   pic16_aopOp(left,ic,FALSE);
7282   pic16_aopOp(result,ic,FALSE);
7283
7284   /* now move the left to the result if they are not the
7285      same */
7286   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7287       AOP_SIZE(result) > 1) {
7288
7289     size = AOP_SIZE(result);
7290     offset=0;
7291     while (size--) {
7292       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7293       if (*l == '@' && (IS_AOP_PREG(result))) {
7294
7295         pic16_emitcode("mov","a,%s",l);
7296         pic16_aopPut(AOP(result),"a",offset);
7297       } else {
7298         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7299         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7300         //pic16_aopPut(AOP(result),l,offset);
7301       }
7302       offset++;
7303     }
7304   }
7305
7306   size = AOP_SIZE(result);
7307
7308   /* if it is only one byte then */
7309   if (size == 1) {
7310     if(optimized_for_speed) {
7311       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7312       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7313       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7314       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7315       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7316       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7317       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7318       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7319       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7320       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7321       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7322       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7323     } else {
7324
7325       tlbl = newiTempLabel(NULL);
7326       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7327         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7328         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7329       }
7330
7331       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7332       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7333       pic16_emitpLabel(tlbl->key);
7334       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7335       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7336       emitSKPC;
7337       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7338     }
7339     goto release ;
7340   }
7341     
7342   if (pic16_sameRegs(AOP(left),AOP(result))) {
7343
7344     tlbl = newiTempLabel(NULL);
7345     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7346     genMultiAsm(POC_RRCF, result, size,1);
7347     pic16_emitpLabel(tlbl->key);
7348     genMultiAsm(POC_RLCF, result, size,0);
7349     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7350     emitSKPC;
7351     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7352     goto release;
7353   }
7354
7355   //tlbl = newiTempLabel(NULL);
7356   //offset = 0 ;   
7357   //tlbl1 = newiTempLabel(NULL);
7358
7359   //reAdjustPreg(AOP(result));    
7360     
7361   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7362   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7363   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7364   //MOVA(l);
7365   //pic16_emitcode("add","a,acc");         
7366   //pic16_aopPut(AOP(result),"a",offset++);
7367   //while (--size) {
7368   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7369   //  MOVA(l);
7370   //  pic16_emitcode("rlc","a");         
7371   //  pic16_aopPut(AOP(result),"a",offset++);
7372   //}
7373   //reAdjustPreg(AOP(result));
7374
7375   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7376   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7377
7378
7379   tlbl = newiTempLabel(NULL);
7380   tlbl1= newiTempLabel(NULL);
7381
7382   size = AOP_SIZE(result);
7383   offset = 1;
7384
7385   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7386
7387   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7388
7389   /* offset should be 0, 1 or 3 */
7390   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7391   emitSKPNZ;
7392   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7393
7394   pic16_emitpcode(POC_MOVWF, pctemp);
7395
7396
7397   pic16_emitpLabel(tlbl->key);
7398
7399   emitCLRC;
7400   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7401   while(--size)
7402     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7403
7404   pic16_emitpcode(POC_DECFSZ,  pctemp);
7405   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7406   pic16_emitpLabel(tlbl1->key);
7407
7408   pic16_popReleaseTempReg(pctemp);
7409
7410
7411  release:
7412   pic16_freeAsmop (right,NULL,ic,TRUE);
7413   pic16_freeAsmop(left,NULL,ic,TRUE);
7414   pic16_freeAsmop(result,NULL,ic,TRUE);
7415 }
7416
7417 /*-----------------------------------------------------------------*/
7418 /* genrshOne - right shift a one byte quantity by known count      */
7419 /*-----------------------------------------------------------------*/
7420 static void genrshOne (operand *result, operand *left,
7421                        int shCount, int sign)
7422 {
7423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7424     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7425 }
7426
7427 /*-----------------------------------------------------------------*/
7428 /* genrshTwo - right shift two bytes by known amount != 0          */
7429 /*-----------------------------------------------------------------*/
7430 static void genrshTwo (operand *result,operand *left,
7431                        int shCount, int sign)
7432 {
7433   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7434   /* if shCount >= 8 */
7435   if (shCount >= 8) {
7436     shCount -= 8 ;
7437     if (shCount)
7438       shiftR1Left2Result(left, MSB16, result, LSB,
7439                          shCount, sign);
7440     else
7441       movLeft2Result(left, MSB16, result, LSB);
7442
7443     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7444
7445     if(sign) {
7446       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7447       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7448     }
7449   }
7450
7451   /*  1 <= shCount <= 7 */
7452   else
7453     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7454 }
7455
7456 /*-----------------------------------------------------------------*/
7457 /* shiftRLong - shift right one long from left to result           */
7458 /* offl = LSB or MSB16                                             */
7459 /*-----------------------------------------------------------------*/
7460 static void shiftRLong (operand *left, int offl,
7461                         operand *result, int sign)
7462 {
7463     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7464     if(!sign)
7465         pic16_emitcode("clr","c");
7466     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7467     if(sign)
7468         pic16_emitcode("mov","c,acc.7");
7469     pic16_emitcode("rrc","a");
7470     pic16_aopPut(AOP(result),"a",MSB32-offl);
7471     if(offl == MSB16)
7472         /* add sign of "a" */
7473         pic16_addSign(result, MSB32, sign);
7474
7475     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7476     pic16_emitcode("rrc","a");
7477     pic16_aopPut(AOP(result),"a",MSB24-offl);
7478
7479     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7480     pic16_emitcode("rrc","a");
7481     pic16_aopPut(AOP(result),"a",MSB16-offl);
7482
7483     if(offl == LSB){
7484         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7485         pic16_emitcode("rrc","a");
7486         pic16_aopPut(AOP(result),"a",LSB);
7487     }
7488 }
7489
7490 /*-----------------------------------------------------------------*/
7491 /* genrshFour - shift four byte by a known amount != 0             */
7492 /*-----------------------------------------------------------------*/
7493 static void genrshFour (operand *result, operand *left,
7494                         int shCount, int sign)
7495 {
7496   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7497   /* if shifting more that 3 bytes */
7498   if(shCount >= 24 ) {
7499     shCount -= 24;
7500     if(shCount)
7501       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7502     else
7503       movLeft2Result(left, MSB32, result, LSB);
7504
7505     pic16_addSign(result, MSB16, sign);
7506   }
7507   else if(shCount >= 16){
7508     shCount -= 16;
7509     if(shCount)
7510       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7511     else{
7512       movLeft2Result(left, MSB24, result, LSB);
7513       movLeft2Result(left, MSB32, result, MSB16);
7514     }
7515     pic16_addSign(result, MSB24, sign);
7516   }
7517   else if(shCount >= 8){
7518     shCount -= 8;
7519     if(shCount == 1)
7520       shiftRLong(left, MSB16, result, sign);
7521     else if(shCount == 0){
7522       movLeft2Result(left, MSB16, result, LSB);
7523       movLeft2Result(left, MSB24, result, MSB16);
7524       movLeft2Result(left, MSB32, result, MSB24);
7525       pic16_addSign(result, MSB32, sign);
7526     }
7527     else{
7528       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7529       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7530       /* the last shift is signed */
7531       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7532       pic16_addSign(result, MSB32, sign);
7533     }
7534   }
7535   else{   /* 1 <= shCount <= 7 */
7536     if(shCount <= 2){
7537       shiftRLong(left, LSB, result, sign);
7538       if(shCount == 2)
7539         shiftRLong(result, LSB, result, sign);
7540     }
7541     else{
7542       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7543       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7544       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7545     }
7546   }
7547 }
7548
7549 /*-----------------------------------------------------------------*/
7550 /* genRightShiftLiteral - right shifting by known count            */
7551 /*-----------------------------------------------------------------*/
7552 static void genRightShiftLiteral (operand *left,
7553                                   operand *right,
7554                                   operand *result,
7555                                   iCode *ic,
7556                                   int sign)
7557 {    
7558   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7559   int lsize,res_size;
7560
7561   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7562   pic16_freeAsmop(right,NULL,ic,TRUE);
7563
7564   pic16_aopOp(left,ic,FALSE);
7565   pic16_aopOp(result,ic,FALSE);
7566
7567 #if VIEW_SIZE
7568   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7569                  AOP_SIZE(left));
7570 #endif
7571
7572   lsize = pic16_getDataSize(left);
7573   res_size = pic16_getDataSize(result);
7574   /* test the LEFT size !!! */
7575
7576   /* I suppose that the left size >= result size */
7577   if(shCount == 0){
7578     while(res_size--)
7579       movLeft2Result(left, lsize, result, res_size);
7580   }
7581
7582   else if(shCount >= (lsize * 8)){
7583
7584     if(res_size == 1) {
7585       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7586       if(sign) {
7587         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7588         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7589       }
7590     } else {
7591
7592       if(sign) {
7593         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7594         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7595         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7596         while(res_size--)
7597           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7598
7599       } else {
7600
7601         while(res_size--)
7602           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7603       }
7604     }
7605   } else {
7606
7607     switch (res_size) {
7608     case 1:
7609       genrshOne (result,left,shCount,sign);
7610       break;
7611
7612     case 2:
7613       genrshTwo (result,left,shCount,sign);
7614       break;
7615
7616     case 4:
7617       genrshFour (result,left,shCount,sign);
7618       break;
7619     default :
7620       break;
7621     }
7622
7623   }
7624
7625   pic16_freeAsmop(left,NULL,ic,TRUE);
7626   pic16_freeAsmop(result,NULL,ic,TRUE);
7627 }
7628
7629 /*-----------------------------------------------------------------*/
7630 /* genSignedRightShift - right shift of signed number              */
7631 /*-----------------------------------------------------------------*/
7632 static void genSignedRightShift (iCode *ic)
7633 {
7634   operand *right, *left, *result;
7635   int size, offset;
7636   //  char *l;
7637   symbol *tlbl, *tlbl1 ;
7638   pCodeOp *pctemp;
7639
7640   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7641
7642   /* we do it the hard way put the shift count in b
7643      and loop thru preserving the sign */
7644   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7645
7646   right = IC_RIGHT(ic);
7647   left  = IC_LEFT(ic);
7648   result = IC_RESULT(ic);
7649
7650   pic16_aopOp(right,ic,FALSE);  
7651   pic16_aopOp(left,ic,FALSE);
7652   pic16_aopOp(result,ic,FALSE);
7653
7654
7655   if ( AOP_TYPE(right) == AOP_LIT) {
7656     genRightShiftLiteral (left,right,result,ic,1);
7657     return ;
7658   }
7659   /* shift count is unknown then we have to form 
7660      a loop get the loop count in B : Note: we take
7661      only the lower order byte since shifting
7662      more that 32 bits make no sense anyway, ( the
7663      largest size of an object can be only 32 bits ) */  
7664
7665   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7666   //pic16_emitcode("inc","b");
7667   //pic16_freeAsmop (right,NULL,ic,TRUE);
7668   //pic16_aopOp(left,ic,FALSE);
7669   //pic16_aopOp(result,ic,FALSE);
7670
7671   /* now move the left to the result if they are not the
7672      same */
7673   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7674       AOP_SIZE(result) > 1) {
7675
7676     size = AOP_SIZE(result);
7677     offset=0;
7678     while (size--) { 
7679       /*
7680         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7681         if (*l == '@' && IS_AOP_PREG(result)) {
7682
7683         pic16_emitcode("mov","a,%s",l);
7684         pic16_aopPut(AOP(result),"a",offset);
7685         } else
7686         pic16_aopPut(AOP(result),l,offset);
7687       */
7688       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7689       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7690
7691       offset++;
7692     }
7693   }
7694
7695   /* mov the highest order bit to OVR */    
7696   tlbl = newiTempLabel(NULL);
7697   tlbl1= newiTempLabel(NULL);
7698
7699   size = AOP_SIZE(result);
7700   offset = size - 1;
7701
7702   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7703
7704   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7705
7706   /* offset should be 0, 1 or 3 */
7707   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7708   emitSKPNZ;
7709   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7710
7711   pic16_emitpcode(POC_MOVWF, pctemp);
7712
7713
7714   pic16_emitpLabel(tlbl->key);
7715
7716   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7717   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7718
7719   while(--size) {
7720     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7721   }
7722
7723   pic16_emitpcode(POC_DECFSZ,  pctemp);
7724   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7725   pic16_emitpLabel(tlbl1->key);
7726
7727   pic16_popReleaseTempReg(pctemp);
7728 #if 0
7729   size = AOP_SIZE(result);
7730   offset = size - 1;
7731   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7732   pic16_emitcode("rlc","a");
7733   pic16_emitcode("mov","ov,c");
7734   /* if it is only one byte then */
7735   if (size == 1) {
7736     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7737     MOVA(l);
7738     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7739     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7740     pic16_emitcode("mov","c,ov");
7741     pic16_emitcode("rrc","a");
7742     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7743     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7744     pic16_aopPut(AOP(result),"a",0);
7745     goto release ;
7746   }
7747
7748   reAdjustPreg(AOP(result));
7749   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7750   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7751   pic16_emitcode("mov","c,ov");
7752   while (size--) {
7753     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7754     MOVA(l);
7755     pic16_emitcode("rrc","a");         
7756     pic16_aopPut(AOP(result),"a",offset--);
7757   }
7758   reAdjustPreg(AOP(result));
7759   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7760   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7761
7762  release:
7763 #endif
7764
7765   pic16_freeAsmop(left,NULL,ic,TRUE);
7766   pic16_freeAsmop(result,NULL,ic,TRUE);
7767   pic16_freeAsmop(right,NULL,ic,TRUE);
7768 }
7769
7770 /*-----------------------------------------------------------------*/
7771 /* genRightShift - generate code for right shifting                */
7772 /*-----------------------------------------------------------------*/
7773 static void genRightShift (iCode *ic)
7774 {
7775     operand *right, *left, *result;
7776     sym_link *retype ;
7777     int size, offset;
7778     char *l;
7779     symbol *tlbl, *tlbl1 ;
7780
7781     /* if signed then we do it the hard way preserve the
7782     sign bit moving it inwards */
7783     retype = getSpec(operandType(IC_RESULT(ic)));
7784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7785
7786     if (!SPEC_USIGN(retype)) {
7787         genSignedRightShift (ic);
7788         return ;
7789     }
7790
7791     /* signed & unsigned types are treated the same : i.e. the
7792     signed is NOT propagated inwards : quoting from the
7793     ANSI - standard : "for E1 >> E2, is equivalent to division
7794     by 2**E2 if unsigned or if it has a non-negative value,
7795     otherwise the result is implementation defined ", MY definition
7796     is that the sign does not get propagated */
7797
7798     right = IC_RIGHT(ic);
7799     left  = IC_LEFT(ic);
7800     result = IC_RESULT(ic);
7801
7802     pic16_aopOp(right,ic,FALSE);
7803
7804     /* if the shift count is known then do it 
7805     as efficiently as possible */
7806     if (AOP_TYPE(right) == AOP_LIT) {
7807         genRightShiftLiteral (left,right,result,ic, 0);
7808         return ;
7809     }
7810
7811     /* shift count is unknown then we have to form 
7812     a loop get the loop count in B : Note: we take
7813     only the lower order byte since shifting
7814     more that 32 bits make no sense anyway, ( the
7815     largest size of an object can be only 32 bits ) */  
7816
7817     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7818     pic16_emitcode("inc","b");
7819     pic16_aopOp(left,ic,FALSE);
7820     pic16_aopOp(result,ic,FALSE);
7821
7822     /* now move the left to the result if they are not the
7823     same */
7824     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7825         AOP_SIZE(result) > 1) {
7826
7827         size = AOP_SIZE(result);
7828         offset=0;
7829         while (size--) {
7830             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7831             if (*l == '@' && IS_AOP_PREG(result)) {
7832
7833                 pic16_emitcode("mov","a,%s",l);
7834                 pic16_aopPut(AOP(result),"a",offset);
7835             } else
7836                 pic16_aopPut(AOP(result),l,offset);
7837             offset++;
7838         }
7839     }
7840
7841     tlbl = newiTempLabel(NULL);
7842     tlbl1= newiTempLabel(NULL);
7843     size = AOP_SIZE(result);
7844     offset = size - 1;
7845
7846     /* if it is only one byte then */
7847     if (size == 1) {
7848
7849       tlbl = newiTempLabel(NULL);
7850       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7851         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7852         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7853       }
7854
7855       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7856       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7857       pic16_emitpLabel(tlbl->key);
7858       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7859       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7860       emitSKPC;
7861       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7862
7863       goto release ;
7864     }
7865
7866     reAdjustPreg(AOP(result));
7867     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7868     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7869     CLRC;
7870     while (size--) {
7871         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7872         MOVA(l);
7873         pic16_emitcode("rrc","a");         
7874         pic16_aopPut(AOP(result),"a",offset--);
7875     }
7876     reAdjustPreg(AOP(result));
7877
7878     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7879     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7880
7881 release:
7882     pic16_freeAsmop(left,NULL,ic,TRUE);
7883     pic16_freeAsmop (right,NULL,ic,TRUE);
7884     pic16_freeAsmop(result,NULL,ic,TRUE);
7885 }
7886
7887 /*-----------------------------------------------------------------*/
7888 /* genUnpackBits - generates code for unpacking bits               */
7889 /*-----------------------------------------------------------------*/
7890 static void genUnpackBits (operand *result, char *rname, int ptype)
7891 {    
7892     int shCnt ;
7893     int rlen = 0 ;
7894     sym_link *etype;
7895     int offset = 0 ;
7896
7897     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7898     etype = getSpec(operandType(result));
7899
7900     /* read the first byte  */
7901     switch (ptype) {
7902
7903     case POINTER:
7904     case IPOINTER:
7905         pic16_emitcode("mov","a,@%s",rname);
7906         break;
7907         
7908     case PPOINTER:
7909         pic16_emitcode("movx","a,@%s",rname);
7910         break;
7911         
7912     case FPOINTER:
7913         pic16_emitcode("movx","a,@dptr");
7914         break;
7915
7916     case CPOINTER:
7917         pic16_emitcode("clr","a");
7918         pic16_emitcode("movc","a","@a+dptr");
7919         break;
7920
7921     case GPOINTER:
7922         pic16_emitcode("lcall","__gptrget");
7923         break;
7924     }
7925
7926     /* if we have bitdisplacement then it fits   */
7927     /* into this byte completely or if length is */
7928     /* less than a byte                          */
7929     if ((shCnt = SPEC_BSTR(etype)) || 
7930         (SPEC_BLEN(etype) <= 8))  {
7931
7932         /* shift right acc */
7933         AccRsh(shCnt);
7934
7935         pic16_emitcode("anl","a,#0x%02x",
7936                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7937         pic16_aopPut(AOP(result),"a",offset);
7938         return ;
7939     }
7940
7941     /* bit field did not fit in a byte  */
7942     rlen = SPEC_BLEN(etype) - 8;
7943     pic16_aopPut(AOP(result),"a",offset++);
7944
7945     while (1)  {
7946
7947         switch (ptype) {
7948         case POINTER:
7949         case IPOINTER:
7950             pic16_emitcode("inc","%s",rname);
7951             pic16_emitcode("mov","a,@%s",rname);
7952             break;
7953             
7954         case PPOINTER:
7955             pic16_emitcode("inc","%s",rname);
7956             pic16_emitcode("movx","a,@%s",rname);
7957             break;
7958
7959         case FPOINTER:
7960             pic16_emitcode("inc","dptr");
7961             pic16_emitcode("movx","a,@dptr");
7962             break;
7963             
7964         case CPOINTER:
7965             pic16_emitcode("clr","a");
7966             pic16_emitcode("inc","dptr");
7967             pic16_emitcode("movc","a","@a+dptr");
7968             break;
7969             
7970         case GPOINTER:
7971             pic16_emitcode("inc","dptr");
7972             pic16_emitcode("lcall","__gptrget");
7973             break;
7974         }
7975
7976         rlen -= 8;            
7977         /* if we are done */
7978         if ( rlen <= 0 )
7979             break ;
7980         
7981         pic16_aopPut(AOP(result),"a",offset++);
7982                               
7983     }
7984     
7985     if (rlen) {
7986         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7987         pic16_aopPut(AOP(result),"a",offset);          
7988     }
7989     
7990     return ;
7991 }
7992
7993 #if 0
7994 /*-----------------------------------------------------------------*/
7995 /* genDataPointerGet - generates code when ptr offset is known     */
7996 /*-----------------------------------------------------------------*/
7997 static void genDataPointerGet (operand *left, 
7998                                operand *result, 
7999                                iCode *ic)
8000 {
8001   int size , offset = 0;
8002
8003
8004   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8005
8006
8007   /* optimization - most of the time, left and result are the same
8008    * address, but different types. for the pic code, we could omit
8009    * the following
8010    */
8011
8012   pic16_aopOp(result,ic,TRUE);
8013
8014   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8015
8016   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8017
8018   size = AOP_SIZE(result);
8019
8020   while (size--) {
8021     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8022     offset++;
8023   }
8024
8025   pic16_freeAsmop(left,NULL,ic,TRUE);
8026   pic16_freeAsmop(result,NULL,ic,TRUE);
8027 }
8028 #endif
8029 /*-----------------------------------------------------------------*/
8030 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8031 /*-----------------------------------------------------------------*/
8032 static void genNearPointerGet (operand *left, 
8033                                operand *result, 
8034                                iCode *ic)
8035 {
8036     asmop *aop = NULL;
8037     //regs *preg = NULL ;
8038     char *rname ;
8039     sym_link *rtype, *retype;
8040     sym_link *ltype = operandType(left);    
8041     //char buffer[80];
8042
8043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8044
8045     rtype = operandType(result);
8046     retype= getSpec(rtype);
8047     
8048     pic16_aopOp(left,ic,FALSE);
8049     
8050     /* if left is rematerialisable and
8051        result is not bit variable type and
8052        the left is pointer to data space i.e
8053        lower 128 bytes of space */
8054     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8055         !IS_BITVAR(retype)         &&
8056         DCL_TYPE(ltype) == POINTER) {
8057       //genDataPointerGet (left,result,ic);
8058         return ;
8059     }
8060     
8061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8062
8063         /* if the value is already in a pointer register
8064        then don't need anything more */
8065     if (!AOP_INPREG(AOP(left))) {
8066         /* otherwise get a free pointer register */
8067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8068 /*
8069         aop = newAsmop(0);
8070         preg = getFreePtr(ic,&aop,FALSE);
8071         pic16_emitcode("mov","%s,%s",
8072                 preg->name,
8073                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8074         rname = preg->name ;
8075 */
8076     rname ="BAD";
8077     } else
8078         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8079     
8080     pic16_aopOp (result,ic,FALSE);
8081     
8082       /* if bitfield then unpack the bits */
8083     if (IS_BITVAR(retype)) 
8084         genUnpackBits (result,rname,POINTER);
8085     else {
8086         /* we have can just get the values */
8087       int size = AOP_SIZE(result);
8088       int offset = 0 ;  
8089         
8090       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8091
8092       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8093       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8094       while(size--) {
8095         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8096         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8097         if(size)
8098           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8099       }
8100 /*
8101         while (size--) {
8102             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8103
8104                 pic16_emitcode("mov","a,@%s",rname);
8105                 pic16_aopPut(AOP(result),"a",offset);
8106             } else {
8107                 sprintf(buffer,"@%s",rname);
8108                 pic16_aopPut(AOP(result),buffer,offset);
8109             }
8110             offset++ ;
8111             if (size)
8112                 pic16_emitcode("inc","%s",rname);
8113         }
8114 */
8115     }
8116
8117     /* now some housekeeping stuff */
8118     if (aop) {
8119         /* we had to allocate for this iCode */
8120     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8121         pic16_freeAsmop(NULL,aop,ic,TRUE);
8122     } else { 
8123         /* we did not allocate which means left
8124            already in a pointer register, then
8125            if size > 0 && this could be used again
8126            we have to point it back to where it 
8127            belongs */
8128     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8129         if (AOP_SIZE(result) > 1 &&
8130             !OP_SYMBOL(left)->remat &&
8131             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8132               ic->depth )) {
8133             int size = AOP_SIZE(result) - 1;
8134             while (size--)
8135                 pic16_emitcode("dec","%s",rname);
8136         }
8137     }
8138
8139     /* done */
8140     pic16_freeAsmop(left,NULL,ic,TRUE);
8141     pic16_freeAsmop(result,NULL,ic,TRUE);
8142      
8143 }
8144
8145 /*-----------------------------------------------------------------*/
8146 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8147 /*-----------------------------------------------------------------*/
8148 static void genPagedPointerGet (operand *left, 
8149                                operand *result, 
8150                                iCode *ic)
8151 {
8152     asmop *aop = NULL;
8153     regs *preg = NULL ;
8154     char *rname ;
8155     sym_link *rtype, *retype;    
8156
8157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8158
8159     rtype = operandType(result);
8160     retype= getSpec(rtype);
8161     
8162     pic16_aopOp(left,ic,FALSE);
8163
8164   /* if the value is already in a pointer register
8165        then don't need anything more */
8166     if (!AOP_INPREG(AOP(left))) {
8167         /* otherwise get a free pointer register */
8168         aop = newAsmop(0);
8169         preg = getFreePtr(ic,&aop,FALSE);
8170         pic16_emitcode("mov","%s,%s",
8171                 preg->name,
8172                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8173         rname = preg->name ;
8174     } else
8175         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8176     
8177     pic16_freeAsmop(left,NULL,ic,TRUE);
8178     pic16_aopOp (result,ic,FALSE);
8179
8180     /* if bitfield then unpack the bits */
8181     if (IS_BITVAR(retype)) 
8182         genUnpackBits (result,rname,PPOINTER);
8183     else {
8184         /* we have can just get the values */
8185         int size = AOP_SIZE(result);
8186         int offset = 0 ;        
8187         
8188         while (size--) {
8189             
8190             pic16_emitcode("movx","a,@%s",rname);
8191             pic16_aopPut(AOP(result),"a",offset);
8192             
8193             offset++ ;
8194             
8195             if (size)
8196                 pic16_emitcode("inc","%s",rname);
8197         }
8198     }
8199
8200     /* now some housekeeping stuff */
8201     if (aop) {
8202         /* we had to allocate for this iCode */
8203         pic16_freeAsmop(NULL,aop,ic,TRUE);
8204     } else { 
8205         /* we did not allocate which means left
8206            already in a pointer register, then
8207            if size > 0 && this could be used again
8208            we have to point it back to where it 
8209            belongs */
8210         if (AOP_SIZE(result) > 1 &&
8211             !OP_SYMBOL(left)->remat &&
8212             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8213               ic->depth )) {
8214             int size = AOP_SIZE(result) - 1;
8215             while (size--)
8216                 pic16_emitcode("dec","%s",rname);
8217         }
8218     }
8219
8220     /* done */
8221     pic16_freeAsmop(result,NULL,ic,TRUE);
8222     
8223         
8224 }
8225
8226 /*-----------------------------------------------------------------*/
8227 /* genFarPointerGet - gget value from far space                    */
8228 /*-----------------------------------------------------------------*/
8229 static void genFarPointerGet (operand *left,
8230                               operand *result, iCode *ic)
8231 {
8232     int size, offset ;
8233     sym_link *retype = getSpec(operandType(result));
8234
8235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8236
8237     pic16_aopOp(left,ic,FALSE);
8238
8239     /* if the operand is already in dptr 
8240     then we do nothing else we move the value to dptr */
8241     if (AOP_TYPE(left) != AOP_STR) {
8242         /* if this is remateriazable */
8243         if (AOP_TYPE(left) == AOP_IMMD)
8244             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8245         else { /* we need to get it byte by byte */
8246             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8247             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8248             if (options.model == MODEL_FLAT24)
8249             {
8250                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8251             }
8252         }
8253     }
8254     /* so dptr know contains the address */
8255     pic16_freeAsmop(left,NULL,ic,TRUE);
8256     pic16_aopOp(result,ic,FALSE);
8257
8258     /* if bit then unpack */
8259     if (IS_BITVAR(retype)) 
8260         genUnpackBits(result,"dptr",FPOINTER);
8261     else {
8262         size = AOP_SIZE(result);
8263         offset = 0 ;
8264
8265         while (size--) {
8266             pic16_emitcode("movx","a,@dptr");
8267             pic16_aopPut(AOP(result),"a",offset++);
8268             if (size)
8269                 pic16_emitcode("inc","dptr");
8270         }
8271     }
8272
8273     pic16_freeAsmop(result,NULL,ic,TRUE);
8274 }
8275 #if 0
8276 /*-----------------------------------------------------------------*/
8277 /* genCodePointerGet - get value from code space                  */
8278 /*-----------------------------------------------------------------*/
8279 static void genCodePointerGet (operand *left,
8280                                 operand *result, iCode *ic)
8281 {
8282     int size, offset ;
8283     sym_link *retype = getSpec(operandType(result));
8284
8285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8286
8287     pic16_aopOp(left,ic,FALSE);
8288
8289     /* if the operand is already in dptr 
8290     then we do nothing else we move the value to dptr */
8291     if (AOP_TYPE(left) != AOP_STR) {
8292         /* if this is remateriazable */
8293         if (AOP_TYPE(left) == AOP_IMMD)
8294             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8295         else { /* we need to get it byte by byte */
8296             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8297             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8298             if (options.model == MODEL_FLAT24)
8299             {
8300                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8301             }
8302         }
8303     }
8304     /* so dptr know contains the address */
8305     pic16_freeAsmop(left,NULL,ic,TRUE);
8306     pic16_aopOp(result,ic,FALSE);
8307
8308     /* if bit then unpack */
8309     if (IS_BITVAR(retype)) 
8310         genUnpackBits(result,"dptr",CPOINTER);
8311     else {
8312         size = AOP_SIZE(result);
8313         offset = 0 ;
8314
8315         while (size--) {
8316             pic16_emitcode("clr","a");
8317             pic16_emitcode("movc","a,@a+dptr");
8318             pic16_aopPut(AOP(result),"a",offset++);
8319             if (size)
8320                 pic16_emitcode("inc","dptr");
8321         }
8322     }
8323
8324     pic16_freeAsmop(result,NULL,ic,TRUE);
8325 }
8326 #endif
8327 /*-----------------------------------------------------------------*/
8328 /* genGenPointerGet - gget value from generic pointer space        */
8329 /*-----------------------------------------------------------------*/
8330 static void genGenPointerGet (operand *left,
8331                               operand *result, iCode *ic)
8332 {
8333   int size, offset ;
8334   sym_link *retype = getSpec(operandType(result));
8335
8336   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8337   pic16_aopOp(left,ic,FALSE);
8338   pic16_aopOp(result,ic,FALSE);
8339
8340
8341   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8342
8343   /* if the operand is already in dptr 
8344      then we do nothing else we move the value to dptr */
8345   //  if (AOP_TYPE(left) != AOP_STR) {
8346     /* if this is remateriazable */
8347     if (AOP_TYPE(left) == AOP_IMMD) {
8348       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8349       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8350     }
8351     else { /* we need to get it byte by byte */
8352
8353       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8354       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8355
8356       size = AOP_SIZE(result);
8357       offset = 0 ;
8358
8359       while(size--) {
8360         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8361         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8362         if(size)
8363           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8364       }
8365       goto release;
8366     }
8367     //}
8368   /* so dptr know contains the address */
8369
8370   /* if bit then unpack */
8371   //if (IS_BITVAR(retype)) 
8372   //  genUnpackBits(result,"dptr",GPOINTER);
8373
8374  release:
8375   pic16_freeAsmop(left,NULL,ic,TRUE);
8376   pic16_freeAsmop(result,NULL,ic,TRUE);
8377
8378 }
8379
8380 /*-----------------------------------------------------------------*/
8381 /* genConstPointerGet - get value from const generic pointer space */
8382 /*-----------------------------------------------------------------*/
8383 static void genConstPointerGet (operand *left,
8384                                 operand *result, iCode *ic)
8385 {
8386   //sym_link *retype = getSpec(operandType(result));
8387   symbol *albl = newiTempLabel(NULL);
8388   symbol *blbl = newiTempLabel(NULL);
8389   PIC_OPCODE poc;
8390
8391   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8392   pic16_aopOp(left,ic,FALSE);
8393   pic16_aopOp(result,ic,FALSE);
8394
8395
8396   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8397
8398   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8399
8400   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8401   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8402   pic16_emitpLabel(albl->key);
8403
8404   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8405     
8406   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8407   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8408   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8409   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8410
8411   pic16_emitpLabel(blbl->key);
8412
8413   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8414
8415
8416   pic16_freeAsmop(left,NULL,ic,TRUE);
8417   pic16_freeAsmop(result,NULL,ic,TRUE);
8418
8419 }
8420 /*-----------------------------------------------------------------*/
8421 /* genPointerGet - generate code for pointer get                   */
8422 /*-----------------------------------------------------------------*/
8423 static void genPointerGet (iCode *ic)
8424 {
8425     operand *left, *result ;
8426     sym_link *type, *etype;
8427     int p_type;
8428
8429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8430
8431     left = IC_LEFT(ic);
8432     result = IC_RESULT(ic) ;
8433
8434     /* depending on the type of pointer we need to
8435     move it to the correct pointer register */
8436     type = operandType(left);
8437     etype = getSpec(type);
8438
8439     if (IS_PTR_CONST(type))
8440       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8441
8442     /* if left is of type of pointer then it is simple */
8443     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8444         p_type = DCL_TYPE(type);
8445     else {
8446         /* we have to go by the storage class */
8447         p_type = PTR_TYPE(SPEC_OCLS(etype));
8448
8449         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8450
8451         if (SPEC_OCLS(etype)->codesp ) {
8452           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8453           //p_type = CPOINTER ; 
8454         }
8455         else
8456             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8457               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8458                /*p_type = FPOINTER ;*/ 
8459             else
8460                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8461                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8462 /*                  p_type = PPOINTER; */
8463                 else
8464                     if (SPEC_OCLS(etype) == idata )
8465                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8466 /*                      p_type = IPOINTER; */
8467                     else
8468                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8469 /*                      p_type = POINTER ; */
8470     }
8471
8472     /* now that we have the pointer type we assign
8473     the pointer values */
8474     switch (p_type) {
8475
8476     case POINTER:       
8477     case IPOINTER:
8478         genNearPointerGet (left,result,ic);
8479         break;
8480
8481     case PPOINTER:
8482         genPagedPointerGet(left,result,ic);
8483         break;
8484
8485     case FPOINTER:
8486         genFarPointerGet (left,result,ic);
8487         break;
8488
8489     case CPOINTER:
8490         genConstPointerGet (left,result,ic);
8491         //pic16_emitcodePointerGet (left,result,ic);
8492         break;
8493
8494     case GPOINTER:
8495       if (IS_PTR_CONST(type))
8496         genConstPointerGet (left,result,ic);
8497       else
8498         genGenPointerGet (left,result,ic);
8499       break;
8500     }
8501
8502 }
8503
8504 /*-----------------------------------------------------------------*/
8505 /* genPackBits - generates code for packed bit storage             */
8506 /*-----------------------------------------------------------------*/
8507 static void genPackBits (sym_link    *etype ,
8508                          operand *right ,
8509                          char *rname, int p_type)
8510 {
8511     int shCount = 0 ;
8512     int offset = 0  ;
8513     int rLen = 0 ;
8514     int blen, bstr ;   
8515     char *l ;
8516
8517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8518     blen = SPEC_BLEN(etype);
8519     bstr = SPEC_BSTR(etype);
8520
8521     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8522     MOVA(l);   
8523
8524     /* if the bit lenth is less than or    */
8525     /* it exactly fits a byte then         */
8526     if (SPEC_BLEN(etype) <= 8 )  {
8527         shCount = SPEC_BSTR(etype) ;
8528
8529         /* shift left acc */
8530         AccLsh(shCount);
8531
8532         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8533
8534
8535             switch (p_type) {
8536                 case POINTER:
8537                     pic16_emitcode ("mov","b,a");
8538                     pic16_emitcode("mov","a,@%s",rname);
8539                     break;
8540
8541                 case FPOINTER:
8542                     pic16_emitcode ("mov","b,a");
8543                     pic16_emitcode("movx","a,@dptr");
8544                     break;
8545
8546                 case GPOINTER:
8547                     pic16_emitcode ("push","b");
8548                     pic16_emitcode ("push","acc");
8549                     pic16_emitcode ("lcall","__gptrget");
8550                     pic16_emitcode ("pop","b");
8551                     break;
8552             }
8553
8554             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8555                       ((unsigned char)(0xFF << (blen+bstr)) | 
8556                        (unsigned char)(0xFF >> (8-bstr)) ) );
8557             pic16_emitcode ("orl","a,b");
8558             if (p_type == GPOINTER)
8559                 pic16_emitcode("pop","b");
8560         }
8561     }
8562
8563     switch (p_type) {
8564         case POINTER:
8565             pic16_emitcode("mov","@%s,a",rname);
8566             break;
8567
8568         case FPOINTER:
8569             pic16_emitcode("movx","@dptr,a");
8570             break;
8571
8572         case GPOINTER:
8573             DEBUGpic16_emitcode(";lcall","__gptrput");
8574             break;
8575     }
8576
8577     /* if we r done */
8578     if ( SPEC_BLEN(etype) <= 8 )
8579         return ;
8580
8581     pic16_emitcode("inc","%s",rname);
8582     rLen = SPEC_BLEN(etype) ;     
8583
8584     /* now generate for lengths greater than one byte */
8585     while (1) {
8586
8587         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8588
8589         rLen -= 8 ;
8590         if (rLen <= 0 )
8591             break ;
8592
8593         switch (p_type) {
8594             case POINTER:
8595                 if (*l == '@') {
8596                     MOVA(l);
8597                     pic16_emitcode("mov","@%s,a",rname);
8598                 } else
8599                     pic16_emitcode("mov","@%s,%s",rname,l);
8600                 break;
8601
8602             case FPOINTER:
8603                 MOVA(l);
8604                 pic16_emitcode("movx","@dptr,a");
8605                 break;
8606
8607             case GPOINTER:
8608                 MOVA(l);
8609                 DEBUGpic16_emitcode(";lcall","__gptrput");
8610                 break;  
8611         }   
8612         pic16_emitcode ("inc","%s",rname);
8613     }
8614
8615     MOVA(l);
8616
8617     /* last last was not complete */
8618     if (rLen)   {
8619         /* save the byte & read byte */
8620         switch (p_type) {
8621             case POINTER:
8622                 pic16_emitcode ("mov","b,a");
8623                 pic16_emitcode("mov","a,@%s",rname);
8624                 break;
8625
8626             case FPOINTER:
8627                 pic16_emitcode ("mov","b,a");
8628                 pic16_emitcode("movx","a,@dptr");
8629                 break;
8630
8631             case GPOINTER:
8632                 pic16_emitcode ("push","b");
8633                 pic16_emitcode ("push","acc");
8634                 pic16_emitcode ("lcall","__gptrget");
8635                 pic16_emitcode ("pop","b");
8636                 break;
8637         }
8638
8639         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8640         pic16_emitcode ("orl","a,b");
8641     }
8642
8643     if (p_type == GPOINTER)
8644         pic16_emitcode("pop","b");
8645
8646     switch (p_type) {
8647
8648     case POINTER:
8649         pic16_emitcode("mov","@%s,a",rname);
8650         break;
8651         
8652     case FPOINTER:
8653         pic16_emitcode("movx","@dptr,a");
8654         break;
8655         
8656     case GPOINTER:
8657         DEBUGpic16_emitcode(";lcall","__gptrput");
8658         break;                  
8659     }
8660 }
8661 /*-----------------------------------------------------------------*/
8662 /* genDataPointerSet - remat pointer to data space                 */
8663 /*-----------------------------------------------------------------*/
8664 static void genDataPointerSet(operand *right,
8665                               operand *result,
8666                               iCode *ic)
8667 {
8668     int size, offset = 0 ;
8669     char *l, buffer[256];
8670
8671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8672     pic16_aopOp(right,ic,FALSE);
8673     
8674     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8675     size = AOP_SIZE(right);
8676 /*
8677     if ( AOP_TYPE(result) == AOP_PCODE) {
8678       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8679               AOP(result)->aopu.pcop->name,
8680               PCOI(AOP(result)->aopu.pcop)->offset);
8681     }
8682 */
8683
8684     // tsd, was l+1 - the underline `_' prefix was being stripped
8685     while (size--) {
8686       if (offset) {
8687         sprintf(buffer,"(%s + %d)",l,offset);
8688         fprintf(stderr,"oops  %s\n",buffer);
8689       } else
8690         sprintf(buffer,"%s",l);
8691
8692         if (AOP_TYPE(right) == AOP_LIT) {
8693           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8694           lit = lit >> (8*offset);
8695           if(lit&0xff) {
8696             pic16_emitcode("movlw","%d",lit);
8697             pic16_emitcode("movwf","%s",buffer);
8698
8699             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8700             //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
8701             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8702
8703           } else {
8704             pic16_emitcode("clrf","%s",buffer);
8705             //pic16_emitpcode(POC_CLRF, popRegFromString(buffer));
8706             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8707           }
8708         }else {
8709           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8710           pic16_emitcode("movwf","%s",buffer);
8711
8712           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8713           //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
8714           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8715
8716         }
8717
8718         offset++;
8719     }
8720
8721     pic16_freeAsmop(right,NULL,ic,TRUE);
8722     pic16_freeAsmop(result,NULL,ic,TRUE);
8723 }
8724
8725 /*-----------------------------------------------------------------*/
8726 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8727 /*-----------------------------------------------------------------*/
8728 static void genNearPointerSet (operand *right,
8729                                operand *result, 
8730                                iCode *ic)
8731 {
8732   asmop *aop = NULL;
8733   char *l;
8734   sym_link *retype;
8735   sym_link *ptype = operandType(result);
8736
8737     
8738   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8739   retype= getSpec(operandType(right));
8740
8741   pic16_aopOp(result,ic,FALSE);
8742
8743     
8744   /* if the result is rematerializable &
8745      in data space & not a bit variable */
8746   //if (AOP_TYPE(result) == AOP_IMMD &&
8747   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8748       DCL_TYPE(ptype) == POINTER   &&
8749       !IS_BITVAR(retype)) {
8750     genDataPointerSet (right,result,ic);
8751     pic16_freeAsmop(result,NULL,ic,TRUE);
8752     return;
8753   }
8754
8755   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8756   pic16_aopOp(right,ic,FALSE);
8757   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8758
8759   /* if the value is already in a pointer register
8760      then don't need anything more */
8761   if (!AOP_INPREG(AOP(result))) {
8762     /* otherwise get a free pointer register */
8763     //aop = newAsmop(0);
8764     //preg = getFreePtr(ic,&aop,FALSE);
8765     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8766     //pic16_emitcode("mov","%s,%s",
8767     //         preg->name,
8768     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8769     //rname = preg->name ;
8770     //pic16_emitcode("movwf","fsr0");
8771     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8772     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8773     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8774     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8775     goto release;
8776
8777   }// else
8778   //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8779
8780
8781   /* if bitfield then unpack the bits */
8782   if (IS_BITVAR(retype)) {
8783     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8784            "The programmer is obviously confused");
8785     //genPackBits (retype,right,rname,POINTER);
8786     exit(1);
8787   }
8788   else {
8789     /* we have can just get the values */
8790     int size = AOP_SIZE(right);
8791     int offset = 0 ;    
8792
8793     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8794     while (size--) {
8795       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8796       if (*l == '@' ) {
8797         //MOVA(l);
8798         //pic16_emitcode("mov","@%s,a",rname);
8799         pic16_emitcode("movf","indf0,w ;1");
8800       } else {
8801
8802         if (AOP_TYPE(right) == AOP_LIT) {
8803           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8804           if(lit) {
8805             pic16_emitcode("movlw","%s",l);
8806             pic16_emitcode("movwf","indf0 ;2");
8807           } else 
8808             pic16_emitcode("clrf","indf0");
8809         }else {
8810           pic16_emitcode("movf","%s,w",l);
8811           pic16_emitcode("movwf","indf0 ;2");
8812         }
8813         //pic16_emitcode("mov","@%s,%s",rname,l);
8814       }
8815       if (size)
8816         pic16_emitcode("incf","fsr0,f ;3");
8817       //pic16_emitcode("inc","%s",rname);
8818       offset++;
8819     }
8820   }
8821
8822   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8823   /* now some housekeeping stuff */
8824   if (aop) {
8825     /* we had to allocate for this iCode */
8826     pic16_freeAsmop(NULL,aop,ic,TRUE);
8827   } else { 
8828     /* we did not allocate which means left
8829        already in a pointer register, then
8830        if size > 0 && this could be used again
8831        we have to point it back to where it 
8832        belongs */
8833     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8834     if (AOP_SIZE(right) > 1 &&
8835         !OP_SYMBOL(result)->remat &&
8836         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8837           ic->depth )) {
8838       int size = AOP_SIZE(right) - 1;
8839       while (size--)
8840         pic16_emitcode("decf","fsr0,f");
8841       //pic16_emitcode("dec","%s",rname);
8842     }
8843   }
8844
8845   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8846   /* done */
8847  release:
8848   pic16_freeAsmop(right,NULL,ic,TRUE);
8849   pic16_freeAsmop(result,NULL,ic,TRUE);
8850 }
8851
8852 /*-----------------------------------------------------------------*/
8853 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
8854 /*-----------------------------------------------------------------*/
8855 static void genPagedPointerSet (operand *right,
8856                                operand *result, 
8857                                iCode *ic)
8858 {
8859     asmop *aop = NULL;
8860     regs *preg = NULL ;
8861     char *rname , *l;
8862     sym_link *retype;
8863        
8864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8865
8866     retype= getSpec(operandType(right));
8867     
8868     pic16_aopOp(result,ic,FALSE);
8869     
8870     /* if the value is already in a pointer register
8871        then don't need anything more */
8872     if (!AOP_INPREG(AOP(result))) {
8873         /* otherwise get a free pointer register */
8874         aop = newAsmop(0);
8875         preg = getFreePtr(ic,&aop,FALSE);
8876         pic16_emitcode("mov","%s,%s",
8877                 preg->name,
8878                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
8879         rname = preg->name ;
8880     } else
8881         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8882     
8883     pic16_freeAsmop(result,NULL,ic,TRUE);
8884     pic16_aopOp (right,ic,FALSE);
8885
8886     /* if bitfield then unpack the bits */
8887     if (IS_BITVAR(retype)) 
8888         genPackBits (retype,right,rname,PPOINTER);
8889     else {
8890         /* we have can just get the values */
8891         int size = AOP_SIZE(right);
8892         int offset = 0 ;        
8893         
8894         while (size--) {
8895             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8896             
8897             MOVA(l);
8898             pic16_emitcode("movx","@%s,a",rname);
8899
8900             if (size)
8901                 pic16_emitcode("inc","%s",rname);
8902
8903             offset++;
8904         }
8905     }
8906     
8907     /* now some housekeeping stuff */
8908     if (aop) {
8909         /* we had to allocate for this iCode */
8910         pic16_freeAsmop(NULL,aop,ic,TRUE);
8911     } else { 
8912         /* we did not allocate which means left
8913            already in a pointer register, then
8914            if size > 0 && this could be used again
8915            we have to point it back to where it 
8916            belongs */
8917         if (AOP_SIZE(right) > 1 &&
8918             !OP_SYMBOL(result)->remat &&
8919             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8920               ic->depth )) {
8921             int size = AOP_SIZE(right) - 1;
8922             while (size--)
8923                 pic16_emitcode("dec","%s",rname);
8924         }
8925     }
8926
8927     /* done */
8928     pic16_freeAsmop(right,NULL,ic,TRUE);
8929     
8930         
8931 }
8932
8933 /*-----------------------------------------------------------------*/
8934 /* genFarPointerSet - set value from far space                     */
8935 /*-----------------------------------------------------------------*/
8936 static void genFarPointerSet (operand *right,
8937                               operand *result, iCode *ic)
8938 {
8939     int size, offset ;
8940     sym_link *retype = getSpec(operandType(right));
8941
8942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8943     pic16_aopOp(result,ic,FALSE);
8944
8945     /* if the operand is already in dptr 
8946     then we do nothing else we move the value to dptr */
8947     if (AOP_TYPE(result) != AOP_STR) {
8948         /* if this is remateriazable */
8949         if (AOP_TYPE(result) == AOP_IMMD)
8950             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8951         else { /* we need to get it byte by byte */
8952             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
8953             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
8954             if (options.model == MODEL_FLAT24)
8955             {
8956                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
8957             }
8958         }
8959     }
8960     /* so dptr know contains the address */
8961     pic16_freeAsmop(result,NULL,ic,TRUE);
8962     pic16_aopOp(right,ic,FALSE);
8963
8964     /* if bit then unpack */
8965     if (IS_BITVAR(retype)) 
8966         genPackBits(retype,right,"dptr",FPOINTER);
8967     else {
8968         size = AOP_SIZE(right);
8969         offset = 0 ;
8970
8971         while (size--) {
8972             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8973             MOVA(l);
8974             pic16_emitcode("movx","@dptr,a");
8975             if (size)
8976                 pic16_emitcode("inc","dptr");
8977         }
8978     }
8979
8980     pic16_freeAsmop(right,NULL,ic,TRUE);
8981 }
8982
8983 /*-----------------------------------------------------------------*/
8984 /* genGenPointerSet - set value from generic pointer space         */
8985 /*-----------------------------------------------------------------*/
8986 static void genGenPointerSet (operand *right,
8987                               operand *result, iCode *ic)
8988 {
8989   int size, offset ;
8990   sym_link *retype = getSpec(operandType(right));
8991
8992   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8993
8994   pic16_aopOp(result,ic,FALSE);
8995   pic16_aopOp(right,ic,FALSE);
8996   size = AOP_SIZE(right);
8997
8998   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8999
9000   /* if the operand is already in dptr 
9001      then we do nothing else we move the value to dptr */
9002   if (AOP_TYPE(result) != AOP_STR) {
9003     /* if this is remateriazable */
9004     if (AOP_TYPE(result) == AOP_IMMD) {
9005       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9006       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9007     }
9008     else { /* we need to get it byte by byte */
9009       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9010       size = AOP_SIZE(right);
9011       offset = 0 ;
9012
9013       /* hack hack! see if this the FSR. If so don't load W */
9014       if(AOP_TYPE(right) != AOP_ACC) {
9015
9016
9017         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9018         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9019
9020         if(AOP_SIZE(result) > 1) {
9021           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9022           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9023           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9024
9025         }
9026
9027         //if(size==2)
9028         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9029         //if(size==4) {
9030         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9031         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9032         //}
9033
9034         while(size--) {
9035           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9036           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9037           
9038           if(size)
9039             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9040         }
9041
9042
9043         goto release;
9044       } 
9045
9046       if(aopIdx(AOP(result),0) != 4) {
9047
9048         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9049         goto release;
9050       }
9051
9052       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9053       goto release;
9054
9055     }
9056   }
9057   /* so dptr know contains the address */
9058
9059
9060   /* if bit then unpack */
9061   if (IS_BITVAR(retype)) 
9062     genPackBits(retype,right,"dptr",GPOINTER);
9063   else {
9064     size = AOP_SIZE(right);
9065     offset = 0 ;
9066
9067   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9068
9069     while (size--) {
9070
9071       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9072       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9073
9074       if (AOP_TYPE(right) == AOP_LIT) 
9075         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9076       else
9077         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9078
9079       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9080
9081       offset++;
9082     }
9083   }
9084
9085  release:
9086   pic16_freeAsmop(right,NULL,ic,TRUE);
9087   pic16_freeAsmop(result,NULL,ic,TRUE);
9088 }
9089
9090 /*-----------------------------------------------------------------*/
9091 /* genPointerSet - stores the value into a pointer location        */
9092 /*-----------------------------------------------------------------*/
9093 static void genPointerSet (iCode *ic)
9094 {    
9095     operand *right, *result ;
9096     sym_link *type, *etype;
9097     int p_type;
9098
9099     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9100
9101     right = IC_RIGHT(ic);
9102     result = IC_RESULT(ic) ;
9103
9104     /* depending on the type of pointer we need to
9105     move it to the correct pointer register */
9106     type = operandType(result);
9107     etype = getSpec(type);
9108     /* if left is of type of pointer then it is simple */
9109     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9110         p_type = DCL_TYPE(type);
9111     }
9112     else {
9113         /* we have to go by the storage class */
9114         p_type = PTR_TYPE(SPEC_OCLS(etype));
9115
9116 /*      if (SPEC_OCLS(etype)->codesp ) { */
9117 /*          p_type = CPOINTER ;  */
9118 /*      } */
9119 /*      else */
9120 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9121 /*              p_type = FPOINTER ; */
9122 /*          else */
9123 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9124 /*                  p_type = PPOINTER ; */
9125 /*              else */
9126 /*                  if (SPEC_OCLS(etype) == idata ) */
9127 /*                      p_type = IPOINTER ; */
9128 /*                  else */
9129 /*                      p_type = POINTER ; */
9130     }
9131
9132     /* now that we have the pointer type we assign
9133     the pointer values */
9134     switch (p_type) {
9135
9136     case POINTER:
9137     case IPOINTER:
9138         genNearPointerSet (right,result,ic);
9139         break;
9140
9141     case PPOINTER:
9142         genPagedPointerSet (right,result,ic);
9143         break;
9144
9145     case FPOINTER:
9146         genFarPointerSet (right,result,ic);
9147         break;
9148
9149     case GPOINTER:
9150         genGenPointerSet (right,result,ic);
9151         break;
9152
9153     default:
9154       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9155               "genPointerSet: illegal pointer type");
9156     }
9157 }
9158
9159 /*-----------------------------------------------------------------*/
9160 /* genIfx - generate code for Ifx statement                        */
9161 /*-----------------------------------------------------------------*/
9162 static void genIfx (iCode *ic, iCode *popIc)
9163 {
9164   operand *cond = IC_COND(ic);
9165   int isbit =0;
9166
9167   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9168
9169   pic16_aopOp(cond,ic,FALSE);
9170
9171   /* get the value into acc */
9172   if (AOP_TYPE(cond) != AOP_CRY)
9173     pic16_toBoolean(cond);
9174   else
9175     isbit = 1;
9176   /* the result is now in the accumulator */
9177   pic16_freeAsmop(cond,NULL,ic,TRUE);
9178
9179   /* if there was something to be popped then do it */
9180   if (popIc)
9181     genIpop(popIc);
9182
9183   /* if the condition is  a bit variable */
9184   if (isbit && IS_ITEMP(cond) && 
9185       SPIL_LOC(cond)) {
9186     genIfxJump(ic,SPIL_LOC(cond)->rname);
9187     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9188   }
9189   else {
9190     if (isbit && !IS_ITEMP(cond))
9191       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9192     else
9193       genIfxJump(ic,"a");
9194   }
9195   ic->generated = 1;
9196
9197 }
9198
9199 /*-----------------------------------------------------------------*/
9200 /* genAddrOf - generates code for address of                       */
9201 /*-----------------------------------------------------------------*/
9202 static void genAddrOf (iCode *ic)
9203 {
9204   operand *right, *result, *left;
9205   int size, offset ;
9206
9207   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9208
9209
9210   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9211
9212   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9213   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9214   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9215
9216   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9217
9218   size = AOP_SIZE(IC_RESULT(ic));
9219   offset = 0;
9220
9221
9222   while (size--) {
9223     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9224     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9225     offset++;
9226   }
9227
9228
9229   pic16_freeAsmop(left,NULL,ic,FALSE);
9230   pic16_freeAsmop(result,NULL,ic,TRUE);
9231
9232 }
9233
9234 #if 0
9235 /*-----------------------------------------------------------------*/
9236 /* genFarFarAssign - assignment when both are in far space         */
9237 /*-----------------------------------------------------------------*/
9238 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9239 {
9240     int size = AOP_SIZE(right);
9241     int offset = 0;
9242     char *l ;
9243     /* first push the right side on to the stack */
9244     while (size--) {
9245         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9246         MOVA(l);
9247         pic16_emitcode ("push","acc");
9248     }
9249     
9250     pic16_freeAsmop(right,NULL,ic,FALSE);
9251     /* now assign DPTR to result */
9252     pic16_aopOp(result,ic,FALSE);
9253     size = AOP_SIZE(result);
9254     while (size--) {
9255         pic16_emitcode ("pop","acc");
9256         pic16_aopPut(AOP(result),"a",--offset);
9257     }
9258     pic16_freeAsmop(result,NULL,ic,FALSE);
9259         
9260 }
9261 #endif
9262
9263 /*-----------------------------------------------------------------*/
9264 /* genAssign - generate code for assignment                        */
9265 /*-----------------------------------------------------------------*/
9266 static void genAssign (iCode *ic)
9267 {
9268   operand *result, *right;
9269   int size, offset,know_W;
9270   unsigned long lit = 0L;
9271
9272   result = IC_RESULT(ic);
9273   right  = IC_RIGHT(ic) ;
9274
9275   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9276   
9277   /* if they are the same */
9278   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9279     return ;
9280
9281   pic16_aopOp(right,ic,FALSE);
9282   pic16_aopOp(result,ic,TRUE);
9283
9284   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9285
9286   /* if they are the same registers */
9287   if (pic16_sameRegs(AOP(right),AOP(result)))
9288     goto release;
9289
9290   /* if the result is a bit */
9291   if (AOP_TYPE(result) == AOP_CRY) {
9292     /* if the right size is a literal then
9293        we know what the value is */
9294     if (AOP_TYPE(right) == AOP_LIT) {
9295           
9296       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9297                   pic16_popGet(AOP(result),0));
9298
9299       if (((int) operandLitValue(right))) 
9300         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9301                        AOP(result)->aopu.aop_dir,
9302                        AOP(result)->aopu.aop_dir);
9303       else
9304         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9305                        AOP(result)->aopu.aop_dir,
9306                        AOP(result)->aopu.aop_dir);
9307       goto release;
9308     }
9309
9310     /* the right is also a bit variable */
9311     if (AOP_TYPE(right) == AOP_CRY) {
9312       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9313       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9314       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9315
9316       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9317                      AOP(result)->aopu.aop_dir,
9318                      AOP(result)->aopu.aop_dir);
9319       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9320                      AOP(right)->aopu.aop_dir,
9321                      AOP(right)->aopu.aop_dir);
9322       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9323                      AOP(result)->aopu.aop_dir,
9324                      AOP(result)->aopu.aop_dir);
9325       goto release ;
9326     }
9327
9328     /* we need to or */
9329     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9330     pic16_toBoolean(right);
9331     emitSKPZ;
9332     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9333     //pic16_aopPut(AOP(result),"a",0);
9334     goto release ;
9335   }
9336
9337   /* bit variables done */
9338   /* general case */
9339   size = AOP_SIZE(result);
9340   offset = 0 ;
9341   if(AOP_TYPE(right) == AOP_LIT)
9342     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9343
9344 /* VR - What is this?! */
9345   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9346   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9347     if(aopIdx(AOP(result),0) == 4) {
9348   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9349       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9350       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9351       goto release;
9352     } else
9353       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9354   }
9355
9356   know_W=-1;
9357   while (size--) {
9358   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9359     if(AOP_TYPE(right) == AOP_LIT) {
9360       if(lit&0xff) {
9361         if(know_W != (lit&0xff))
9362           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9363         know_W = lit&0xff;
9364         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9365       } else
9366         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9367
9368       lit >>= 8;
9369
9370     } else if (AOP_TYPE(right) == AOP_CRY) {
9371       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9372       if(offset == 0) {
9373         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9374         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9375       }
9376     } else {
9377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9378
9379         if(!options_no_movff) {
9380
9381         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9382            normally should work, but mind that thw W register live range
9383            is not checked, so if the code generator assumes that the W
9384            is already loaded after such a pair, wrong code will be generated.
9385            
9386            Checking the live range is the next step.
9387            This is experimental code yet and has not been fully tested yet.
9388            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9389            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9390            
9391         
9392                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9393         } else {
9394         /* This is the old code, which is assumed(?!) that works fine(!?) */
9395
9396                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9397                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9398         }
9399     }
9400             
9401     offset++;
9402   }
9403
9404     
9405  release:
9406   pic16_freeAsmop (right,NULL,ic,FALSE);
9407   pic16_freeAsmop (result,NULL,ic,TRUE);
9408 }   
9409
9410 /*-----------------------------------------------------------------*/
9411 /* genJumpTab - generates code for jump table                       */
9412 /*-----------------------------------------------------------------*/
9413 static void genJumpTab (iCode *ic)
9414 {
9415     symbol *jtab;
9416     char *l;
9417
9418     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9419
9420     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9421     /* get the condition into accumulator */
9422     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9423     MOVA(l);
9424     /* multiply by three */
9425     pic16_emitcode("add","a,acc");
9426     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9427
9428     jtab = newiTempLabel(NULL);
9429     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9430     pic16_emitcode("jmp","@a+dptr");
9431     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9432
9433     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9434     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9435     emitSKPNC;
9436     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9437     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9438     pic16_emitpLabel(jtab->key);
9439
9440     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9441
9442     /* now generate the jump labels */
9443     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9444          jtab = setNextItem(IC_JTLABELS(ic))) {
9445         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9446         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9447         
9448     }
9449
9450 }
9451
9452 /*-----------------------------------------------------------------*/
9453 /* genMixedOperation - gen code for operators between mixed types  */
9454 /*-----------------------------------------------------------------*/
9455 /*
9456   TSD - Written for the PIC port - but this unfortunately is buggy.
9457   This routine is good in that it is able to efficiently promote 
9458   types to different (larger) sizes. Unfortunately, the temporary
9459   variables that are optimized out by this routine are sometimes
9460   used in other places. So until I know how to really parse the 
9461   iCode tree, I'm going to not be using this routine :(.
9462 */
9463 static int genMixedOperation (iCode *ic)
9464 {
9465 #if 0
9466   operand *result = IC_RESULT(ic);
9467   sym_link *ctype = operandType(IC_LEFT(ic));
9468   operand *right = IC_RIGHT(ic);
9469   int ret = 0;
9470   int big,small;
9471   int offset;
9472
9473   iCode *nextic;
9474   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9475
9476   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9477
9478   nextic = ic->next;
9479   if(!nextic)
9480     return 0;
9481
9482   nextright = IC_RIGHT(nextic);
9483   nextleft  = IC_LEFT(nextic);
9484   nextresult = IC_RESULT(nextic);
9485
9486   pic16_aopOp(right,ic,FALSE);
9487   pic16_aopOp(result,ic,FALSE);
9488   pic16_aopOp(nextright,  nextic, FALSE);
9489   pic16_aopOp(nextleft,   nextic, FALSE);
9490   pic16_aopOp(nextresult, nextic, FALSE);
9491
9492   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9493
9494     operand *t = right;
9495     right = nextright;
9496     nextright = t; 
9497
9498     pic16_emitcode(";remove right +","");
9499
9500   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9501 /*
9502     operand *t = right;
9503     right = nextleft;
9504     nextleft = t; 
9505 */
9506     pic16_emitcode(";remove left +","");
9507   } else
9508     return 0;
9509
9510   big = AOP_SIZE(nextleft);
9511   small = AOP_SIZE(nextright);
9512
9513   switch(nextic->op) {
9514
9515   case '+':
9516     pic16_emitcode(";optimize a +","");
9517     /* if unsigned or not an integral type */
9518     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9519       pic16_emitcode(";add a bit to something","");
9520     } else {
9521
9522       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9523
9524       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9525         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9526         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9527       } else
9528         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9529
9530       offset = 0;
9531       while(--big) {
9532
9533         offset++;
9534
9535         if(--small) {
9536           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9537             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9538             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9539           }
9540
9541           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9542           emitSKPNC;
9543           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9544                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9545                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9546           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9547           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9548
9549         } else {
9550           pic16_emitcode("rlf","known_zero,w");
9551
9552           /*
9553             if right is signed
9554               btfsc  right,7
9555                addlw ff
9556           */
9557           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9558             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9559             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9560           } else {
9561             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9562           }
9563         }
9564       }
9565       ret = 1;
9566     }
9567   }
9568   ret = 1;
9569
9570 release:
9571   pic16_freeAsmop(right,NULL,ic,TRUE);
9572   pic16_freeAsmop(result,NULL,ic,TRUE);
9573   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9574   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9575   if(ret)
9576     nextic->generated = 1;
9577
9578   return ret;
9579 #else
9580   return 0;
9581 #endif
9582 }
9583 /*-----------------------------------------------------------------*/
9584 /* genCast - gen code for casting                                  */
9585 /*-----------------------------------------------------------------*/
9586 static void genCast (iCode *ic)
9587 {
9588     operand *result = IC_RESULT(ic);
9589     sym_link *ctype = operandType(IC_LEFT(ic));
9590     sym_link *rtype = operandType(IC_RIGHT(ic));
9591     operand *right = IC_RIGHT(ic);
9592     int size, offset ;
9593
9594     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9595     /* if they are equivalent then do nothing */
9596     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9597         return ;
9598
9599     pic16_aopOp(right,ic,FALSE) ;
9600     pic16_aopOp(result,ic,FALSE);
9601
9602     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9603
9604     /* if the result is a bit */
9605     if (AOP_TYPE(result) == AOP_CRY) {
9606         /* if the right size is a literal then
9607         we know what the value is */
9608       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9609         if (AOP_TYPE(right) == AOP_LIT) {
9610
9611           pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9612                       pic16_popGet(AOP(result),0));
9613
9614             if (((int) operandLitValue(right))) 
9615               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9616                        AOP(result)->aopu.aop_dir,
9617                        AOP(result)->aopu.aop_dir);
9618             else
9619               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9620                        AOP(result)->aopu.aop_dir,
9621                        AOP(result)->aopu.aop_dir);
9622
9623             goto release;
9624         }
9625
9626         /* the right is also a bit variable */
9627         if (AOP_TYPE(right) == AOP_CRY) {
9628
9629           emitCLRC;
9630           pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9631
9632           pic16_emitcode("clrc","");
9633           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9634                    AOP(right)->aopu.aop_dir,
9635                    AOP(right)->aopu.aop_dir);
9636             pic16_aopPut(AOP(result),"c",0);
9637             goto release ;
9638         }
9639
9640         /* we need to or */
9641         if (AOP_TYPE(right) == AOP_REG) {
9642           pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9643           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9644           pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9645         }
9646         pic16_toBoolean(right);
9647         pic16_aopPut(AOP(result),"a",0);
9648         goto release ;
9649     }
9650
9651     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9652       int offset = 1;
9653       size = AOP_SIZE(result);
9654
9655       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9656
9657       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9658       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9659       pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9660
9661       while (size--)
9662         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9663
9664       goto release;
9665     }
9666
9667     /* if they are the same size : or less */
9668     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9669
9670         /* if they are in the same place */
9671       if (pic16_sameRegs(AOP(right),AOP(result)))
9672         goto release;
9673
9674       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9675       if (IS_PTR_CONST(rtype))
9676         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9677       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9678         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9679
9680       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9681         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9682         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9683         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9684         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9685         if(AOP_SIZE(result) <2)
9686           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9687
9688       } else {
9689
9690         /* if they in different places then copy */
9691         size = AOP_SIZE(result);
9692         offset = 0 ;
9693         while (size--) {
9694           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9695           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9696
9697           //pic16_aopPut(AOP(result),
9698           // pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9699           // offset);
9700
9701           offset++;
9702         }
9703       }
9704       goto release;
9705     }
9706
9707
9708     /* if the result is of type pointer */
9709     if (IS_PTR(ctype)) {
9710
9711         int p_type;
9712         sym_link *type = operandType(right);
9713         sym_link *etype = getSpec(type);
9714       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9715
9716         /* pointer to generic pointer */
9717         if (IS_GENPTR(ctype)) {
9718             char *l = zero;
9719             
9720             if (IS_PTR(type)) 
9721                 p_type = DCL_TYPE(type);
9722             else {
9723                 /* we have to go by the storage class */
9724                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9725
9726 /*              if (SPEC_OCLS(etype)->codesp )  */
9727 /*                  p_type = CPOINTER ;  */
9728 /*              else */
9729 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9730 /*                      p_type = FPOINTER ; */
9731 /*                  else */
9732 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9733 /*                          p_type = PPOINTER; */
9734 /*                      else */
9735 /*                          if (SPEC_OCLS(etype) == idata ) */
9736 /*                              p_type = IPOINTER ; */
9737 /*                          else */
9738 /*                              p_type = POINTER ; */
9739             }
9740                 
9741             /* the first two bytes are known */
9742       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9743             size = GPTRSIZE - 1; 
9744             offset = 0 ;
9745             while (size--) {
9746               if(offset < AOP_SIZE(right)) {
9747       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9748                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9749                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9750                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9751                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9752                 } else { 
9753                   pic16_aopPut(AOP(result),
9754                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9755                          offset);
9756                 }
9757               } else 
9758                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9759               offset++;
9760             }
9761             /* the last byte depending on type */
9762             switch (p_type) {
9763             case IPOINTER:
9764             case POINTER:
9765                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
9766                 break;
9767             case FPOINTER:
9768               pic16_emitcode(";BUG!? ","%d",__LINE__);
9769                 l = one;
9770                 break;
9771             case CPOINTER:
9772               pic16_emitcode(";BUG!? ","%d",__LINE__);
9773                 l = "#0x02";
9774                 break;                          
9775             case PPOINTER:
9776               pic16_emitcode(";BUG!? ","%d",__LINE__);
9777                 l = "#0x03";
9778                 break;
9779                 
9780             default:
9781                 /* this should never happen */
9782                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9783                        "got unknown pointer type");
9784                 exit(1);
9785             }
9786             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
9787             goto release ;
9788         }
9789         
9790         /* just copy the pointers */
9791         size = AOP_SIZE(result);
9792         offset = 0 ;
9793         while (size--) {
9794             pic16_aopPut(AOP(result),
9795                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9796                    offset);
9797             offset++;
9798         }
9799         goto release ;
9800     }
9801     
9802
9803
9804     /* so we now know that the size of destination is greater
9805     than the size of the source.
9806     Now, if the next iCode is an operator then we might be
9807     able to optimize the operation without performing a cast.
9808     */
9809     if(genMixedOperation(ic))
9810       goto release;
9811
9812     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9813     
9814     /* we move to result for the size of source */
9815     size = AOP_SIZE(right);
9816     offset = 0 ;
9817     while (size--) {
9818       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
9819       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
9820       offset++;
9821     }
9822
9823     /* now depending on the sign of the destination */
9824     size = AOP_SIZE(result) - AOP_SIZE(right);
9825     /* if unsigned or not an integral type */
9826     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9827       while (size--)
9828         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9829     } else {
9830       /* we need to extend the sign :{ */
9831
9832       if(size == 1) {
9833         /* Save one instruction of casting char to int */
9834         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9835         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9836         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
9837       } else {
9838         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9839
9840         if(offset)
9841           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9842         else
9843           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9844         
9845         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9846
9847         while (size--)
9848           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9849       }
9850     }
9851
9852 release:
9853     pic16_freeAsmop(right,NULL,ic,TRUE);
9854     pic16_freeAsmop(result,NULL,ic,TRUE);
9855
9856 }
9857
9858 /*-----------------------------------------------------------------*/
9859 /* genDjnz - generate decrement & jump if not zero instrucion      */
9860 /*-----------------------------------------------------------------*/
9861 static int genDjnz (iCode *ic, iCode *ifx)
9862 {
9863     symbol *lbl, *lbl1;
9864     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9865
9866     if (!ifx)
9867         return 0;
9868     
9869     /* if the if condition has a false label
9870        then we cannot save */
9871     if (IC_FALSE(ifx))
9872         return 0;
9873
9874     /* if the minus is not of the form 
9875        a = a - 1 */
9876     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9877         !IS_OP_LITERAL(IC_RIGHT(ic)))
9878         return 0;
9879
9880     if (operandLitValue(IC_RIGHT(ic)) != 1)
9881         return 0;
9882
9883     /* if the size of this greater than one then no
9884        saving */
9885     if (getSize(operandType(IC_RESULT(ic))) > 1)
9886         return 0;
9887
9888     /* otherwise we can save BIG */
9889     lbl = newiTempLabel(NULL);
9890     lbl1= newiTempLabel(NULL);
9891
9892     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9893     
9894     if (IS_AOP_PREG(IC_RESULT(ic))) {
9895         pic16_emitcode("dec","%s",
9896                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9897         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9898         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
9899     } else {    
9900
9901
9902       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9903       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9904
9905       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9906       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9907
9908     }
9909 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9910 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
9911 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9912 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
9913
9914     
9915     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9916     ifx->generated = 1;
9917     return 1;
9918 }
9919
9920 /*-----------------------------------------------------------------*/
9921 /* genReceive - generate code for a receive iCode                  */
9922 /*-----------------------------------------------------------------*/
9923 static void genReceive (iCode *ic)
9924 {    
9925   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9926
9927   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9928       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9929         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9930
9931     int size = getSize(operandType(IC_RESULT(ic)));
9932     int offset =  pic16_fReturnSizePic - size;
9933     while (size--) {
9934       pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9935                                     fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9936       offset++;
9937     }
9938     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9939     size = AOP_SIZE(IC_RESULT(ic));
9940     offset = 0;
9941     while (size--) {
9942       pic16_emitcode ("pop","acc");
9943       pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9944     }
9945         
9946   } else {
9947     _G.accInUse++;
9948     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9949     _G.accInUse--;
9950     assignResultValue(IC_RESULT(ic));   
9951   }
9952
9953   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9954 }
9955
9956 /*-----------------------------------------------------------------*/
9957 /* genpic16Code - generate code for pic16 based controllers        */
9958 /*-----------------------------------------------------------------*/
9959 /*
9960  * At this point, ralloc.c has gone through the iCode and attempted
9961  * to optimize in a way suitable for a PIC. Now we've got to generate
9962  * PIC instructions that correspond to the iCode.
9963  *
9964  * Once the instructions are generated, we'll pass through both the
9965  * peep hole optimizer and the pCode optimizer.
9966  *-----------------------------------------------------------------*/
9967
9968 void genpic16Code (iCode *lic)
9969 {
9970     iCode *ic;
9971     int cln = 0;
9972
9973     lineHead = lineCurr = NULL;
9974
9975     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
9976     pic16_addpBlock(pb);
9977
9978 #if 0
9979     /* if debug information required */
9980     if (options.debug && currFunc) { 
9981       if (currFunc) {
9982         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9983         _G.debugLine = 1;
9984         if (IS_STATIC(currFunc->etype)) {
9985           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9986           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
9987         } else {
9988           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9989           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
9990         }
9991         _G.debugLine = 0;
9992       }
9993     }
9994 #endif
9995
9996     for (ic = lic ; ic ; ic = ic->next ) {
9997
9998 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
9999 //      DEBUGpic16_emitcode("; VR", "");
10000       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10001         if ( cln != ic->lineno ) {
10002             if ( options.debug ) {
10003                 _G.debugLine = 1;
10004                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10005                          FileBaseName(ic->filename),ic->lineno,
10006                          ic->level,ic->block);
10007                 _G.debugLine = 0;
10008             }
10009             /*
10010               pic16_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
10011               pic16_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
10012               printCLine(ic->filename, ic->lineno));
10013             */
10014             pic16_addpCode2pBlock(pb,
10015                             pic16_newpCodeCSource(ic->lineno, 
10016                                             ic->filename, 
10017                                             printCLine(ic->filename, ic->lineno)));
10018
10019             cln = ic->lineno ;
10020         }
10021         /* if the result is marked as
10022            spilt and rematerializable or code for
10023            this has already been generated then
10024            do nothing */
10025         if (resultRemat(ic) || ic->generated ) 
10026             continue ;
10027         
10028         /* depending on the operation */
10029         switch (ic->op) {
10030         case '!' :
10031             genNot(ic);
10032             break;
10033             
10034         case '~' :
10035             genCpl(ic);
10036             break;
10037             
10038         case UNARYMINUS:
10039             genUminus (ic);
10040             break;
10041             
10042         case IPUSH:
10043             genIpush (ic);
10044             break;
10045             
10046         case IPOP:
10047             /* IPOP happens only when trying to restore a 
10048                spilt live range, if there is an ifx statement
10049                following this pop then the if statement might
10050                be using some of the registers being popped which
10051                would destroy the contents of the register so
10052                we need to check for this condition and handle it */
10053             if (ic->next            && 
10054                 ic->next->op == IFX &&
10055                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10056                 genIfx (ic->next,ic);
10057             else
10058                 genIpop (ic);
10059             break; 
10060             
10061         case CALL:
10062             genCall (ic);
10063             break;
10064             
10065         case PCALL:
10066             genPcall (ic);
10067             break;
10068             
10069         case FUNCTION:
10070             genFunction (ic);
10071             break;
10072             
10073         case ENDFUNCTION:
10074             genEndFunction (ic);
10075             break;
10076             
10077         case RETURN:
10078             genRet (ic);
10079             break;
10080             
10081         case LABEL:
10082             genLabel (ic);
10083             break;
10084             
10085         case GOTO:
10086             genGoto (ic);
10087             break;
10088             
10089         case '+' :
10090             pic16_genPlus (ic) ;
10091             break;
10092             
10093         case '-' :
10094             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10095                 pic16_genMinus (ic);
10096             break;
10097             
10098         case '*' :
10099             genMult (ic);
10100             break;
10101             
10102         case '/' :
10103             genDiv (ic) ;
10104             break;
10105             
10106         case '%' :
10107             genMod (ic);
10108             break;
10109             
10110         case '>' :
10111             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10112             break;
10113             
10114         case '<' :
10115             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10116             break;
10117             
10118         case LE_OP:
10119         case GE_OP:
10120         case NE_OP:
10121             
10122             /* note these two are xlated by algebraic equivalence
10123                during parsing SDCC.y */
10124             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10125                    "got '>=' or '<=' shouldn't have come here");
10126             break;      
10127             
10128         case EQ_OP:
10129             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10130             break;          
10131             
10132         case AND_OP:
10133             genAndOp (ic);
10134             break;
10135             
10136         case OR_OP:
10137             genOrOp (ic);
10138             break;
10139             
10140         case '^' :
10141             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10142             break;
10143             
10144         case '|' :
10145                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10146             break;
10147             
10148         case BITWISEAND:
10149             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10150             break;
10151             
10152         case INLINEASM:
10153             genInline (ic);
10154             break;
10155             
10156         case RRC:
10157             genRRC (ic);
10158             break;
10159             
10160         case RLC:
10161             genRLC (ic);
10162             break;
10163             
10164         case GETHBIT:
10165             genGetHbit (ic);
10166             break;
10167             
10168         case LEFT_OP:
10169             genLeftShift (ic);
10170             break;
10171             
10172         case RIGHT_OP:
10173             genRightShift (ic);
10174             break;
10175             
10176         case GET_VALUE_AT_ADDRESS:
10177             genPointerGet(ic);
10178             break;
10179             
10180         case '=' :
10181             if (POINTER_SET(ic))
10182                 genPointerSet(ic);
10183             else
10184                 genAssign(ic);
10185             break;
10186             
10187         case IFX:
10188             genIfx (ic,NULL);
10189             break;
10190             
10191         case ADDRESS_OF:
10192             genAddrOf (ic);
10193             break;
10194             
10195         case JUMPTABLE:
10196             genJumpTab (ic);
10197             break;
10198             
10199         case CAST:
10200             genCast (ic);
10201             break;
10202             
10203         case RECEIVE:
10204             genReceive(ic);
10205             break;
10206             
10207         case SEND:
10208             addSet(&_G.sendSet,ic);
10209             break;
10210
10211         default :
10212             ic = ic;
10213         }
10214     }
10215     
10216
10217     /* now we are ready to call the 
10218        peep hole optimizer */
10219     if (!options.nopeep) {
10220       peepHole (&lineHead);
10221     }
10222     /* now do the actual printing */
10223     printLine (lineHead,codeOutFile);
10224
10225 #ifdef PCODE_DEBUG
10226     DFPRINTF((stderr,"printing pBlock\n\n"));
10227     pic16_printpBlock(stdout,pb);
10228 #endif
10229
10230     return;
10231 }
10232