Fixed bug #621531 (const & volatile confusion in the type chain).
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9   
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         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
293
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 #if 0
616   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
617 #else
618   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
619 #endif
620   PCOI(aop->aopu.pcop)->index = val;
621
622   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
623                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
624 #if 0
625                       val, IS_PTR_CONST(operandType(op)));
626 #else
627                       val, IS_CODEPTR(operandType(op)));
628 #endif
629
630   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
631
632   pic16_allocDirReg (IC_LEFT(ic));
633
634   return aop;        
635 }
636
637 static int aopIdx (asmop *aop, int offset)
638 {
639   if(!aop)
640     return -1;
641
642   if(aop->type !=  AOP_REG)
643     return -2;
644         
645   return aop->aopu.aop_reg[offset]->rIdx;
646
647 }
648 /*-----------------------------------------------------------------*/
649 /* regsInCommon - two operands have some registers in common       */
650 /*-----------------------------------------------------------------*/
651 static bool regsInCommon (operand *op1, operand *op2)
652 {
653     symbol *sym1, *sym2;
654     int i;
655
656     /* if they have registers in common */
657     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
658         return FALSE ;
659
660     sym1 = OP_SYMBOL(op1);
661     sym2 = OP_SYMBOL(op2);
662
663     if (sym1->nRegs == 0 || sym2->nRegs == 0)
664         return FALSE ;
665
666     for (i = 0 ; i < sym1->nRegs ; i++) {
667         int j;
668         if (!sym1->regs[i])
669             continue ;
670
671         for (j = 0 ; j < sym2->nRegs ;j++ ) {
672             if (!sym2->regs[j])
673                 continue ;
674
675             if (sym2->regs[j] == sym1->regs[i])
676                 return TRUE ;
677         }
678     }
679
680     return FALSE ;
681 }
682
683 /*-----------------------------------------------------------------*/
684 /* operandsEqu - equivalent                                        */
685 /*-----------------------------------------------------------------*/
686 static bool operandsEqu ( operand *op1, operand *op2)
687 {
688     symbol *sym1, *sym2;
689
690     /* if they not symbols */
691     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
692         return FALSE;
693
694     sym1 = OP_SYMBOL(op1);
695     sym2 = OP_SYMBOL(op2);
696
697     /* if both are itemps & one is spilt
698        and the other is not then false */
699     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
700         sym1->isspilt != sym2->isspilt )
701         return FALSE ;
702
703     /* if they are the same */
704     if (sym1 == sym2)
705         return TRUE ;
706
707     if (strcmp(sym1->rname,sym2->rname) == 0)
708         return TRUE;
709
710
711     /* if left is a tmp & right is not */
712     if (IS_ITEMP(op1)  && 
713         !IS_ITEMP(op2) &&
714         sym1->isspilt  &&
715         (sym1->usl.spillLoc == sym2))
716         return TRUE;
717
718     if (IS_ITEMP(op2)  && 
719         !IS_ITEMP(op1) &&
720         sym2->isspilt  &&
721         sym1->level > 0 &&
722         (sym2->usl.spillLoc == sym1))
723         return TRUE ;
724
725     return FALSE ;
726 }
727
728 /*-----------------------------------------------------------------*/
729 /* pic16_sameRegs - two asmops have the same registers                   */
730 /*-----------------------------------------------------------------*/
731 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
732 {
733     int i;
734
735     if (aop1 == aop2)
736         return TRUE ;
737
738     if (aop1->type != AOP_REG ||
739         aop2->type != AOP_REG )
740         return FALSE ;
741
742     if (aop1->size != aop2->size )
743         return FALSE ;
744
745     for (i = 0 ; i < aop1->size ; i++ )
746         if (aop1->aopu.aop_reg[i] !=
747             aop2->aopu.aop_reg[i] )
748             return FALSE ;
749
750     return TRUE ;
751 }
752
753 /*-----------------------------------------------------------------*/
754 /* pic16_aopOp - allocates an asmop for an operand  :                    */
755 /*-----------------------------------------------------------------*/
756 void pic16_aopOp (operand *op, iCode *ic, bool result)
757 {
758     asmop *aop;
759     symbol *sym;
760     int i;
761
762     if (!op)
763         return ;
764
765         DEBUGpic16_emitcode(";","%d",__LINE__);
766     /* if this a literal */
767     if (IS_OP_LITERAL(op)) {
768         op->aop = aop = newAsmop(AOP_LIT);
769         aop->aopu.aop_lit = op->operand.valOperand;
770         aop->size = getSize(operandType(op));
771         return;
772     }
773
774     {
775       sym_link *type = operandType(op);
776 #if 0
777       if(IS_PTR_CONST(type))
778 #else
779       if(IS_CODEPTR(type))
780 #endif
781         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
782     }
783
784     /* if already has a asmop then continue */
785     if (op->aop)
786         return ;
787
788     /* if the underlying symbol has a aop */
789     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
790       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
791         op->aop = OP_SYMBOL(op)->aop;
792         return;
793     }
794
795     /* if this is a true symbol */
796     if (IS_TRUE_SYMOP(op)) {    
797         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
798       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
799       return ;
800     }
801
802     /* this is a temporary : this has
803     only four choices :
804     a) register
805     b) spillocation
806     c) rematerialize 
807     d) conditional   
808     e) can be a return use only */
809
810     sym = OP_SYMBOL(op);
811
812         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
813     /* if the type is a conditional */
814     if (sym->regType == REG_CND) {
815         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
816         aop->size = 0;
817         return;
818     }
819
820     /* if it is spilt then two situations
821     a) is rematerialize 
822     b) has a spill location */
823     if (sym->isspilt || sym->nRegs == 0) {
824
825       DEBUGpic16_emitcode(";","%d",__LINE__);
826         /* rematerialize it NOW */
827         if (sym->remat) {
828
829             sym->aop = op->aop = aop =
830                                       aopForRemat (op);
831             aop->size = getSize(sym->type);
832             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
833             return;
834         }
835
836         if (sym->accuse) {
837             int i;
838             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
839             aop->size = getSize(sym->type);
840             for ( i = 0 ; i < 2 ; i++ )
841                 aop->aopu.aop_str[i] = accUse[i];
842             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
843             return;  
844         }
845
846         if (sym->ruonly ) {
847           /*
848           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
849           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
850           //pic16_allocDirReg (IC_LEFT(ic));
851           aop->size = getSize(sym->type);
852           */
853
854           unsigned i;
855
856           aop = op->aop = sym->aop = newAsmop(AOP_STR);
857           aop->size = getSize(sym->type);
858           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
859             aop->aopu.aop_str[i] = fReturn[i];
860
861           DEBUGpic16_emitcode(";","%d",__LINE__);
862           return;
863         }
864
865         /* else spill location  */
866         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
867             /* force a new aop if sizes differ */
868             sym->usl.spillLoc->aop = NULL;
869         }
870         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
871                             __FUNCTION__,__LINE__,
872                             sym->usl.spillLoc->rname,
873                             sym->rname, sym->usl.spillLoc->offset);
874
875         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
876         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
877         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
878                                           getSize(sym->type), 
879                                           sym->usl.spillLoc->offset);
880         aop->size = getSize(sym->type);
881
882         return;
883     }
884
885     {
886       sym_link *type = operandType(op);
887 #if 0
888       if(IS_PTR_CONST(type)) 
889 #else
890       if(IS_CODEPTR(type)) 
891 #endif
892         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
893     }
894
895     /* must be in a register */
896     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
897     sym->aop = op->aop = aop = newAsmop(AOP_REG);
898     aop->size = sym->nRegs;
899     for ( i = 0 ; i < sym->nRegs ;i++)
900         aop->aopu.aop_reg[i] = sym->regs[i];
901 }
902
903 /*-----------------------------------------------------------------*/
904 /* pic16_freeAsmop - free up the asmop given to an operand               */
905 /*----------------------------------------------------------------*/
906 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
907 {   
908     asmop *aop ;
909
910     if (!op)
911         aop = aaop;
912     else 
913         aop = op->aop;
914
915     if (!aop)
916         return ;
917
918     if (aop->freed)
919         goto dealloc; 
920
921     aop->freed = 1;
922
923     /* depending on the asmop type only three cases need work AOP_RO
924        , AOP_R1 && AOP_STK */
925 #if 0
926     switch (aop->type) {
927         case AOP_R0 :
928             if (_G.r0Pushed ) {
929                 if (pop) {
930                     pic16_emitcode ("pop","ar0");     
931                     _G.r0Pushed--;
932                 }
933             }
934             bitVectUnSetBit(ic->rUsed,R0_IDX);
935             break;
936
937         case AOP_R1 :
938             if (_G.r1Pushed ) {
939                 if (pop) {
940                     pic16_emitcode ("pop","ar1");
941                     _G.r1Pushed--;
942                 }
943             }
944             bitVectUnSetBit(ic->rUsed,R1_IDX);          
945             break;
946
947         case AOP_STK :
948         {
949             int sz = aop->size;    
950             int stk = aop->aopu.aop_stk + aop->size;
951             bitVectUnSetBit(ic->rUsed,R0_IDX);
952             bitVectUnSetBit(ic->rUsed,R1_IDX);          
953
954             getFreePtr(ic,&aop,FALSE);
955             
956             if (options.stack10bit)
957             {
958                 /* I'm not sure what to do here yet... */
959                 /* #STUB */
960                 fprintf(stderr, 
961                         "*** Warning: probably generating bad code for "
962                         "10 bit stack mode.\n");
963             }
964             
965             if (stk) {
966                 pic16_emitcode ("mov","a,_bp");
967                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
968                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
969             } else {
970                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
971             }
972
973             while (sz--) {
974                 pic16_emitcode("pop","acc");
975                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
976                 if (!sz) break;
977                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
978             }
979             op->aop = aop;
980             pic16_freeAsmop(op,NULL,ic,TRUE);
981             if (_G.r0Pushed) {
982                 pic16_emitcode("pop","ar0");
983                 _G.r0Pushed--;
984             }
985
986             if (_G.r1Pushed) {
987                 pic16_emitcode("pop","ar1");
988                 _G.r1Pushed--;
989             }       
990         }
991     }
992 #endif
993
994 dealloc:
995     /* all other cases just dealloc */
996     if (op ) {
997         op->aop = NULL;
998         if (IS_SYMOP(op)) {
999             OP_SYMBOL(op)->aop = NULL;    
1000             /* if the symbol has a spill */
1001             if (SPIL_LOC(op))
1002                 SPIL_LOC(op)->aop = NULL;
1003         }
1004     }
1005 }
1006
1007 /*-----------------------------------------------------------------*/
1008 /* pic16_aopGet - for fetching value of the aop                          */
1009 /*-----------------------------------------------------------------*/
1010 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1011 {
1012     char *s = buffer ;
1013     char *rs;
1014
1015     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1016     /* offset is greater than
1017     size then zero */
1018     if (offset > (aop->size - 1) &&
1019         aop->type != AOP_LIT)
1020         return zero;
1021
1022     /* depending on type */
1023     switch (aop->type) {
1024         
1025     case AOP_R0:
1026     case AOP_R1:
1027         DEBUGpic16_emitcode(";","%d",__LINE__);
1028         /* if we need to increment it */       
1029         while (offset > aop->coff) {        
1030             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1031             aop->coff++;
1032         }
1033         
1034         while (offset < aop->coff) {
1035             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1036             aop->coff--;
1037         }
1038         
1039         aop->coff = offset ;
1040         if (aop->paged) {
1041             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1042             return (dname ? "acc" : "a");
1043         }       
1044         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1045         rs = Safe_calloc(1,strlen(s)+1);
1046         strcpy(rs,s);   
1047         return rs;
1048         
1049     case AOP_DPTR:
1050     case AOP_DPTR2:
1051         DEBUGpic16_emitcode(";","%d",__LINE__);
1052     if (aop->type == AOP_DPTR2)
1053     {
1054         genSetDPTR(1);
1055     }
1056     
1057         while (offset > aop->coff) {
1058             pic16_emitcode ("inc","dptr");
1059             aop->coff++;
1060         }
1061         
1062         while (offset < aop->coff) {        
1063             pic16_emitcode("lcall","__decdptr");
1064             aop->coff--;
1065         }
1066         
1067         aop->coff = offset;
1068         if (aop->code) {
1069             pic16_emitcode("clr","a");
1070             pic16_emitcode("movc","a,@a+dptr");
1071         }
1072     else {
1073             pic16_emitcode("movx","a,@dptr");
1074     }
1075             
1076     if (aop->type == AOP_DPTR2)
1077     {
1078         genSetDPTR(0);
1079     }
1080             
1081     return (dname ? "acc" : "a");
1082         
1083         
1084     case AOP_IMMD:
1085         if (bit16) 
1086             sprintf (s,"%s",aop->aopu.aop_immd);
1087         else
1088             if (offset) 
1089                 sprintf(s,"(%s >> %d)",
1090                         aop->aopu.aop_immd,
1091                         offset*8);
1092             else
1093                 sprintf(s,"%s",
1094                         aop->aopu.aop_immd);
1095         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1096         rs = Safe_calloc(1,strlen(s)+1);
1097         strcpy(rs,s);   
1098         return rs;
1099         
1100     case AOP_DIR:
1101       if (offset) {
1102         sprintf(s,"(%s + %d)",
1103                 aop->aopu.aop_dir,
1104                 offset);
1105         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1106       } else
1107             sprintf(s,"%s",aop->aopu.aop_dir);
1108         rs = Safe_calloc(1,strlen(s)+1);
1109         strcpy(rs,s);   
1110         return rs;
1111         
1112     case AOP_REG:
1113       //if (dname) 
1114       //    return aop->aopu.aop_reg[offset]->dname;
1115       //else
1116             return aop->aopu.aop_reg[offset]->name;
1117         
1118     case AOP_CRY:
1119       //pic16_emitcode(";","%d",__LINE__);
1120       return aop->aopu.aop_dir;
1121         
1122     case AOP_ACC:
1123         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1124         return "AOP_accumulator_bug";
1125
1126     case AOP_LIT:
1127         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1128         rs = Safe_calloc(1,strlen(s)+1);
1129         strcpy(rs,s);   
1130         return rs;
1131         
1132     case AOP_STR:
1133         aop->coff = offset ;
1134         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1135             dname)
1136             return "acc";
1137         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1138         
1139         return aop->aopu.aop_str[offset];
1140         
1141     case AOP_PCODE:
1142       {
1143         pCodeOp *pcop = aop->aopu.pcop;
1144         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1145         if(pcop->name) {
1146           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1147           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1148           sprintf(s,"%s", pcop->name);
1149         } else
1150           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1151
1152       }
1153       rs = Safe_calloc(1,strlen(s)+1);
1154       strcpy(rs,s);   
1155       return rs;
1156
1157     }
1158
1159     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1160            "aopget got unsupported aop->type");
1161     exit(0);
1162 }
1163
1164
1165 /*-----------------------------------------------------------------*/
1166 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1167 /*-----------------------------------------------------------------*/
1168 pCodeOp *pic16_popGetTempReg(void)
1169 {
1170
1171   pCodeOp *pcop;
1172
1173   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1174   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1175     PCOR(pcop)->r->wasUsed=1;
1176     PCOR(pcop)->r->isFree=0;
1177   }
1178
1179   return pcop;
1180 }
1181
1182 /*-----------------------------------------------------------------*/
1183 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1184 /*-----------------------------------------------------------------*/
1185 void pic16_popReleaseTempReg(pCodeOp *pcop)
1186 {
1187
1188   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1189     PCOR(pcop)->r->isFree = 1;
1190
1191 }
1192 /*-----------------------------------------------------------------*/
1193 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1194 /*-----------------------------------------------------------------*/
1195 pCodeOp *pic16_popGetLabel(unsigned int key)
1196 {
1197
1198   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1199
1200   if(key>max_key)
1201     max_key = key;
1202
1203   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1204 }
1205
1206 /*-----------------------------------------------------------------*/
1207 /* pic16_popCopyReg - copy a pcode operator                              */
1208 /*-----------------------------------------------------------------*/
1209 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1210 {
1211   pCodeOpReg *pcor;
1212
1213   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1214   pcor->pcop.type = pc->pcop.type;
1215   if(pc->pcop.name) {
1216     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1217       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1218   } else
1219     pcor->pcop.name = NULL;
1220
1221   pcor->r = pc->r;
1222   pcor->rIdx = pc->rIdx;
1223   pcor->r->wasUsed=1;
1224
1225   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1226
1227   return PCOP(pcor);
1228 }
1229 /*-----------------------------------------------------------------*/
1230 /* pic16_popGet - asm operator to pcode operator conversion              */
1231 /*-----------------------------------------------------------------*/
1232 pCodeOp *pic16_popGetLit(unsigned int lit)
1233 {
1234
1235   return pic16_newpCodeOpLit(lit);
1236 }
1237
1238
1239 /*-----------------------------------------------------------------*/
1240 /* pic16_popGetImmd - asm operator to pcode immediate conversion         */
1241 /*-----------------------------------------------------------------*/
1242 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1243 {
1244
1245   return pic16_newpCodeOpImmd(name, offset,index, 0);
1246 }
1247
1248
1249 /*-----------------------------------------------------------------*/
1250 /* pic16_popGet - asm operator to pcode operator conversion              */
1251 /*-----------------------------------------------------------------*/
1252 pCodeOp *pic16_popGetWithString(char *str)
1253 {
1254   pCodeOp *pcop;
1255
1256
1257   if(!str) {
1258     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1259     exit (1);
1260   }
1261
1262   pcop = pic16_newpCodeOp(str,PO_STR);
1263
1264   return pcop;
1265 }
1266
1267 /*-----------------------------------------------------------------*/
1268 /* popRegFromString -                                              */
1269 /*-----------------------------------------------------------------*/
1270 static pCodeOp *popRegFromString(char *str, int size, int offset)
1271 {
1272
1273   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1274   pcop->type = PO_DIR;
1275
1276   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1277 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1278
1279   if(!str)
1280     str = "BAD_STRING";
1281
1282   pcop->name = Safe_calloc(1,strlen(str)+1);
1283   strcpy(pcop->name,str);
1284
1285   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1286
1287   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1288   if(PCOR(pcop)->r == NULL) {
1289     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1290     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1291
1292         //fprintf(stderr, "allocating new register -> %s\n", str);
1293
1294     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1295   } else {
1296     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1297   }
1298   PCOR(pcop)->instance = offset;
1299
1300   return pcop;
1301 }
1302
1303 static pCodeOp *popRegFromIdx(int rIdx)
1304 {
1305   pCodeOp *pcop;
1306
1307   DEBUGpic16_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1308                        __FUNCTION__,__LINE__,rIdx);
1309
1310   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1311
1312   PCOR(pcop)->rIdx = rIdx;
1313   PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1314   PCOR(pcop)->r->isFree = 0;
1315   PCOR(pcop)->r->wasUsed = 1;
1316
1317   pcop->type = PCOR(pcop)->r->pc_type;
1318
1319
1320   return pcop;
1321 }
1322
1323 /*---------------------------------------------------------------------------------*/
1324 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1325 /*                 VR 030601                                                       */
1326 /*---------------------------------------------------------------------------------*/
1327 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1328 {
1329   pCodeOpReg2 *pcop2;
1330   pCodeOp *temp;
1331   
1332         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1333         temp = pic16_popGet(aop_dst, offset);
1334         pcop2->pcop2 = temp;
1335         
1336   return PCOP(pcop2);
1337 }
1338
1339
1340 /*-----------------------------------------------------------------*/
1341 /* pic16_popGet - asm operator to pcode operator conversion              */
1342 /*-----------------------------------------------------------------*/
1343 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1344 {
1345   //char *s = buffer ;
1346     //char *rs;
1347
1348     pCodeOp *pcop;
1349
1350     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1351     /* offset is greater than
1352     size then zero */
1353
1354     if (offset > (aop->size - 1) &&
1355         aop->type != AOP_LIT)
1356       return NULL;  //zero;
1357
1358     /* depending on type */
1359     switch (aop->type) {
1360         
1361     case AOP_R0:
1362     case AOP_R1:
1363     case AOP_DPTR:
1364     case AOP_DPTR2:
1365     case AOP_ACC:
1366         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1367         return NULL;
1368         
1369     case AOP_IMMD:
1370       DEBUGpic16_emitcode(";","%d",__LINE__);
1371       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1372
1373     case AOP_DIR:
1374       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1375
1376 #if 0
1377         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1378         pcop->type = PO_DIR;
1379
1380         /*
1381         if (offset)
1382             sprintf(s,"(%s + %d)",
1383                     aop->aopu.aop_dir,
1384                     offset);
1385         else
1386             sprintf(s,"%s",aop->aopu.aop_dir);
1387         pcop->name = Safe_calloc(1,strlen(s)+1);
1388         strcpy(pcop->name,s);   
1389         */
1390         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1391         strcpy(pcop->name,aop->aopu.aop_dir);   
1392         PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1393         if(PCOR(pcop)->r == NULL) {
1394           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1395           PCOR(pcop)->r = pic16_allocRegByName (aop->aopu.aop_dir,aop->size);
1396           DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1397         } else {
1398           DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1399         }
1400         PCOR(pcop)->instance = offset;
1401
1402         return pcop;
1403 #endif
1404         
1405     case AOP_REG:
1406       {
1407         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1408
1409         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1410         PCOR(pcop)->rIdx = rIdx;
1411         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1412         PCOR(pcop)->r->wasUsed=1;
1413         PCOR(pcop)->r->isFree=0;
1414
1415         PCOR(pcop)->instance = offset;
1416         pcop->type = PCOR(pcop)->r->pc_type;
1417         //rs = aop->aopu.aop_reg[offset]->name;
1418         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1419         return pcop;
1420       }
1421
1422     case AOP_CRY:
1423       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1424       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1425       //if(PCOR(pcop)->r == NULL)
1426       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1427       return pcop;
1428         
1429     case AOP_LIT:
1430       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1431
1432     case AOP_STR:
1433       DEBUGpic16_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1434       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1435       /*
1436       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1437       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1438       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1439       pcop->type = PCOR(pcop)->r->pc_type;
1440       pcop->name = PCOR(pcop)->r->name;
1441
1442       return pcop;
1443       */
1444
1445     case AOP_PCODE:
1446       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1447                           __LINE__, 
1448                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1449       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1450       PCOI(pcop)->offset = offset;
1451       return pcop;
1452     }
1453
1454     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1455            "pic16_popGet got unsupported aop->type");
1456     exit(0);
1457 }
1458 /*-----------------------------------------------------------------*/
1459 /* pic16_aopPut - puts a string for a aop                                */
1460 /*-----------------------------------------------------------------*/
1461 void pic16_aopPut (asmop *aop, char *s, int offset)
1462 {
1463     char *d = buffer ;
1464     symbol *lbl ;
1465
1466     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1467
1468     if (aop->size && offset > ( aop->size - 1)) {
1469         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1470                "pic16_aopPut got offset > aop->size");
1471         exit(0);
1472     }
1473
1474     /* will assign value to value */
1475     /* depending on where it is ofcourse */
1476     switch (aop->type) {
1477     case AOP_DIR:
1478       if (offset) {
1479         sprintf(d,"(%s + %d)",
1480                 aop->aopu.aop_dir,offset);
1481         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1482
1483       } else
1484             sprintf(d,"%s",aop->aopu.aop_dir);
1485         
1486         if (strcmp(d,s)) {
1487           DEBUGpic16_emitcode(";","%d",__LINE__);
1488           if(strcmp(s,"W"))
1489             pic16_emitcode("movf","%s,w",s);
1490           pic16_emitcode("movwf","%s",d);
1491
1492           if(strcmp(s,"W")) {
1493             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1494             if(offset >= aop->size) {
1495               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1496               break;
1497             } else
1498               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1499           }
1500
1501           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1502
1503
1504         }
1505         break;
1506         
1507     case AOP_REG:
1508       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1509         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1510           /*
1511             if (*s == '@'           ||
1512                 strcmp(s,"r0") == 0 ||
1513                 strcmp(s,"r1") == 0 ||
1514                 strcmp(s,"r2") == 0 ||
1515                 strcmp(s,"r3") == 0 ||
1516                 strcmp(s,"r4") == 0 ||
1517                 strcmp(s,"r5") == 0 ||
1518                 strcmp(s,"r6") == 0 || 
1519                 strcmp(s,"r7") == 0 )
1520                 pic16_emitcode("mov","%s,%s  ; %d",
1521                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1522             else
1523           */
1524
1525           if(strcmp(s,"W")==0 )
1526             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1527
1528           pic16_emitcode("movwf","%s",
1529                    aop->aopu.aop_reg[offset]->name);
1530
1531           if(strcmp(s,zero)==0) {
1532             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1533
1534           } else if(strcmp(s,"W")==0) {
1535             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1536             pcop->type = PO_GPR_REGISTER;
1537
1538             PCOR(pcop)->rIdx = -1;
1539             PCOR(pcop)->r = NULL;
1540
1541             DEBUGpic16_emitcode(";","%d",__LINE__);
1542             pcop->name = Safe_strdup(s);
1543             pic16_emitpcode(POC_MOVFW,pcop);
1544             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1545           } else if(strcmp(s,one)==0) {
1546             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1547             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1548           } else {
1549             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1550           }
1551         }
1552         break;
1553         
1554     case AOP_DPTR:
1555     case AOP_DPTR2:
1556     
1557     if (aop->type == AOP_DPTR2)
1558     {
1559         genSetDPTR(1);
1560     }
1561     
1562         if (aop->code) {
1563             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1564                    "pic16_aopPut writting to code space");
1565             exit(0);
1566         }
1567         
1568         while (offset > aop->coff) {
1569             aop->coff++;
1570             pic16_emitcode ("inc","dptr");
1571         }
1572         
1573         while (offset < aop->coff) {
1574             aop->coff-- ;
1575             pic16_emitcode("lcall","__decdptr");
1576         }
1577         
1578         aop->coff = offset;
1579         
1580         /* if not in accumulater */
1581         MOVA(s);        
1582         
1583         pic16_emitcode ("movx","@dptr,a");
1584         
1585     if (aop->type == AOP_DPTR2)
1586     {
1587         genSetDPTR(0);
1588     }
1589         break;
1590         
1591     case AOP_R0:
1592     case AOP_R1:
1593         while (offset > aop->coff) {
1594             aop->coff++;
1595             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1596         }
1597         while (offset < aop->coff) {
1598             aop->coff-- ;
1599             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1600         }
1601         aop->coff = offset;
1602         
1603         if (aop->paged) {
1604             MOVA(s);           
1605             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1606             
1607         } else
1608             if (*s == '@') {
1609                 MOVA(s);
1610                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1611             } else
1612                 if (strcmp(s,"r0") == 0 ||
1613                     strcmp(s,"r1") == 0 ||
1614                     strcmp(s,"r2") == 0 ||
1615                     strcmp(s,"r3") == 0 ||
1616                     strcmp(s,"r4") == 0 ||
1617                     strcmp(s,"r5") == 0 ||
1618                     strcmp(s,"r6") == 0 || 
1619                     strcmp(s,"r7") == 0 ) {
1620                     char buffer[10];
1621                     sprintf(buffer,"a%s",s);
1622                     pic16_emitcode("mov","@%s,%s",
1623                              aop->aopu.aop_ptr->name,buffer);
1624                 } else
1625                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1626         
1627         break;
1628         
1629     case AOP_STK:
1630         if (strcmp(s,"a") == 0)
1631             pic16_emitcode("push","acc");
1632         else
1633             pic16_emitcode("push","%s",s);
1634         
1635         break;
1636         
1637     case AOP_CRY:
1638         /* if bit variable */
1639         if (!aop->aopu.aop_dir) {
1640             pic16_emitcode("clr","a");
1641             pic16_emitcode("rlc","a");
1642         } else {
1643             if (s == zero) 
1644                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1645             else
1646                 if (s == one)
1647                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1648                 else
1649                     if (!strcmp(s,"c"))
1650                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1651                     else {
1652                         lbl = newiTempLabel(NULL);
1653                         
1654                         if (strcmp(s,"a")) {
1655                             MOVA(s);
1656                         }
1657                         pic16_emitcode("clr","c");
1658                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1659                         pic16_emitcode("cpl","c");
1660                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1661                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1662                     }
1663         }
1664         break;
1665         
1666     case AOP_STR:
1667         aop->coff = offset;
1668         if (strcmp(aop->aopu.aop_str[offset],s))
1669             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1670         break;
1671         
1672     case AOP_ACC:
1673         aop->coff = offset;
1674         if (!offset && (strcmp(s,"acc") == 0))
1675             break;
1676         
1677         if (strcmp(aop->aopu.aop_str[offset],s))
1678             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1679         break;
1680
1681     default :
1682         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1683                "pic16_aopPut got unsupported aop->type");
1684         exit(0);    
1685     }    
1686
1687 }
1688
1689 /*-----------------------------------------------------------------*/
1690 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1691 /*-----------------------------------------------------------------*/
1692 static void mov2w (asmop *aop, int offset)
1693 {
1694
1695   if(!aop)
1696     return;
1697
1698   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1699
1700   if ( aop->type == AOP_PCODE ||
1701        aop->type == AOP_LIT )
1702     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1703   else
1704     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1705
1706 }
1707
1708 /*-----------------------------------------------------------------*/
1709 /* reAdjustPreg - points a register back to where it should        */
1710 /*-----------------------------------------------------------------*/
1711 static void reAdjustPreg (asmop *aop)
1712 {
1713     int size ;
1714
1715     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1716     aop->coff = 0;
1717     if ((size = aop->size) <= 1)
1718         return ;
1719     size-- ;
1720     switch (aop->type) {
1721         case AOP_R0 :
1722         case AOP_R1 :
1723             while (size--)
1724                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1725             break;          
1726         case AOP_DPTR :
1727         case AOP_DPTR2:
1728             if (aop->type == AOP_DPTR2)
1729             {
1730                 genSetDPTR(1);
1731             } 
1732             while (size--)
1733             {
1734                 pic16_emitcode("lcall","__decdptr");
1735             }
1736                 
1737             if (aop->type == AOP_DPTR2)
1738             {
1739                 genSetDPTR(0);
1740             }                
1741             break;  
1742
1743     }   
1744
1745 }
1746
1747
1748 #if 0
1749 /*-----------------------------------------------------------------*/
1750 /* opIsGptr: returns non-zero if the passed operand is             */   
1751 /* a generic pointer type.                                         */
1752 /*-----------------------------------------------------------------*/ 
1753 static int opIsGptr(operand *op)
1754 {
1755     sym_link *type = operandType(op);
1756     
1757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1758     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1759     {
1760         return 1;
1761     }
1762     return 0;        
1763 }
1764 #endif
1765
1766 /*-----------------------------------------------------------------*/
1767 /* pic16_getDataSize - get the operand data size                         */
1768 /*-----------------------------------------------------------------*/
1769 int pic16_getDataSize(operand *op)
1770 {
1771     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1772
1773
1774     return AOP_SIZE(op);
1775
1776     // tsd- in the pic port, the genptr size is 1, so this code here
1777     // fails. ( in the 8051 port, the size was 4).
1778 #if 0
1779     int size;
1780     size = AOP_SIZE(op);
1781     if (size == GPTRSIZE)
1782     {
1783         sym_link *type = operandType(op);
1784         if (IS_GENPTR(type))
1785         {
1786             /* generic pointer; arithmetic operations
1787              * should ignore the high byte (pointer type).
1788              */
1789             size--;
1790     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1791         }
1792     }
1793     return size;
1794 #endif
1795 }
1796
1797 /*-----------------------------------------------------------------*/
1798 /* pic16_outAcc - output Acc                                             */
1799 /*-----------------------------------------------------------------*/
1800 void pic16_outAcc(operand *result)
1801 {
1802   int size,offset;
1803   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1804   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1805
1806
1807   size = pic16_getDataSize(result);
1808   if(size){
1809     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1810     size--;
1811     offset = 1;
1812     /* unsigned or positive */
1813     while(size--)
1814       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1815   }
1816
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_outBitC - output a bit C                                        */
1821 /*-----------------------------------------------------------------*/
1822 void pic16_outBitC(operand *result)
1823 {
1824
1825     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1826     /* if the result is bit */
1827     if (AOP_TYPE(result) == AOP_CRY) 
1828         pic16_aopPut(AOP(result),"c",0);
1829     else {
1830         pic16_emitcode("clr","a  ; %d", __LINE__);
1831         pic16_emitcode("rlc","a");
1832         pic16_outAcc(result);
1833     }
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1838 /*-----------------------------------------------------------------*/
1839 void pic16_toBoolean(operand *oper)
1840 {
1841     int size = AOP_SIZE(oper) - 1;
1842     int offset = 1;
1843
1844     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1845
1846     if ( AOP_TYPE(oper) != AOP_ACC) {
1847       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1848     }
1849     while (size--) {
1850       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1851     }
1852 }
1853
1854
1855 /*-----------------------------------------------------------------*/
1856 /* genNot - generate code for ! operation                          */
1857 /*-----------------------------------------------------------------*/
1858 static void genNot (iCode *ic)
1859 {
1860   symbol *tlbl;
1861   int size;
1862
1863   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1864   /* assign asmOps to operand & result */
1865   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1866   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1867
1868   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1869   /* if in bit space then a special case */
1870   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1871     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1872       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1873       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1874     } else {
1875       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1876       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1877       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1878     }
1879     goto release;
1880   }
1881
1882   size = AOP_SIZE(IC_LEFT(ic));
1883   if(size == 1) {
1884     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1885     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1886     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1887     goto release;
1888   }
1889   pic16_toBoolean(IC_LEFT(ic));
1890
1891   tlbl = newiTempLabel(NULL);
1892   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1893   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1894   pic16_outBitC(IC_RESULT(ic));
1895
1896  release:    
1897   /* release the aops */
1898   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1899   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1900 }
1901
1902
1903 /*-----------------------------------------------------------------*/
1904 /* genCpl - generate code for complement                           */
1905 /*-----------------------------------------------------------------*/
1906 static void genCpl (iCode *ic)
1907 {
1908     int offset = 0;
1909     int size ;
1910
1911
1912     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1913     /* assign asmOps to operand & result */
1914     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1915     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1916
1917     /* if both are in bit space then 
1918     a special case */
1919     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1920         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1921
1922         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1923         pic16_emitcode("cpl","c"); 
1924         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1925         goto release; 
1926     } 
1927
1928     size = AOP_SIZE(IC_RESULT(ic));
1929     while (size--) {
1930 /*
1931         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1932         MOVA(l);       
1933         pic16_emitcode("cpl","a");
1934         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1935 */
1936         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1937               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
1938         } else {
1939                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
1940                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1941         }
1942         offset++;
1943
1944     }
1945
1946
1947 release:
1948     /* release the aops */
1949     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1950     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1951 }
1952
1953 /*-----------------------------------------------------------------*/
1954 /* genUminusFloat - unary minus for floating points                */
1955 /*-----------------------------------------------------------------*/
1956 static void genUminusFloat(operand *op,operand *result)
1957 {
1958     int size ,offset =0 ;
1959     char *l;
1960
1961     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1962     /* for this we just need to flip the 
1963     first it then copy the rest in place */
1964     size = AOP_SIZE(op) - 1;
1965     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
1966
1967     MOVA(l);    
1968
1969     pic16_emitcode("cpl","acc.7");
1970     pic16_aopPut(AOP(result),"a",3);    
1971
1972     while(size--) {
1973         pic16_aopPut(AOP(result),
1974                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
1975                offset);
1976         offset++;
1977     }          
1978 }
1979
1980 /*-----------------------------------------------------------------*/
1981 /* genUminus - unary minus code generation                         */
1982 /*-----------------------------------------------------------------*/
1983 static void genUminus (iCode *ic)
1984 {
1985   int size, i;
1986   sym_link *optype, *rtype;
1987
1988
1989   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1990   /* assign asmops */
1991   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
1992   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
1993
1994   /* if both in bit space then special
1995      case */
1996   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1997       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1998
1999     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2000     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2001     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2002
2003     goto release; 
2004   } 
2005
2006   optype = operandType(IC_LEFT(ic));
2007   rtype = operandType(IC_RESULT(ic));
2008
2009   /* if float then do float stuff */
2010   if (IS_FLOAT(optype)) {
2011     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2012     goto release;
2013   }
2014
2015   /* otherwise subtract from zero by taking the 2's complement */
2016   size = AOP_SIZE(IC_LEFT(ic));
2017
2018   for(i=0; i<size; i++) {
2019     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2020       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2021     else {
2022       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2023       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2024     }
2025   }
2026
2027   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2028   for(i=1; i<size; i++) {
2029     emitSKPNZ;
2030     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2031   }
2032
2033  release:
2034   /* release the aops */
2035   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2036   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2037 }
2038
2039 /*-----------------------------------------------------------------*/
2040 /* saveRegisters - will look for a call and save the registers     */
2041 /*-----------------------------------------------------------------*/
2042 static void saveRegisters(iCode *lic) 
2043 {
2044     int i;
2045     iCode *ic;
2046     bitVect *rsave;
2047     sym_link *dtype;
2048
2049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2050     /* look for call */
2051     for (ic = lic ; ic ; ic = ic->next) 
2052         if (ic->op == CALL || ic->op == PCALL)
2053             break;
2054
2055     if (!ic) {
2056         fprintf(stderr,"found parameter push with no function call\n");
2057         return ;
2058     }
2059
2060     /* if the registers have been saved already then
2061     do nothing */
2062     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2063         return ;
2064
2065     /* find the registers in use at this time 
2066     and push them away to safety */
2067     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2068                           ic->rUsed);
2069
2070     ic->regsSaved = 1;
2071     if (options.useXstack) {
2072         if (bitVectBitValue(rsave,R0_IDX))
2073             pic16_emitcode("mov","b,r0");
2074         pic16_emitcode("mov","r0,%s",spname);
2075         for (i = 0 ; i < pic16_nRegs ; i++) {
2076             if (bitVectBitValue(rsave,i)) {
2077                 if (i == R0_IDX)
2078                     pic16_emitcode("mov","a,b");
2079                 else
2080                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2081                 pic16_emitcode("movx","@r0,a");
2082                 pic16_emitcode("inc","r0");
2083             }
2084         }
2085         pic16_emitcode("mov","%s,r0",spname);
2086         if (bitVectBitValue(rsave,R0_IDX))
2087             pic16_emitcode("mov","r0,b");           
2088     }// else
2089     //for (i = 0 ; i < pic16_nRegs ; i++) {
2090     //    if (bitVectBitValue(rsave,i))
2091     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2092     //}
2093
2094     dtype = operandType(IC_LEFT(ic));
2095     if (currFunc && dtype && 
2096         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2097         IFFUNC_ISISR(currFunc->type) &&
2098         !ic->bankSaved) 
2099
2100         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2101
2102 }
2103 /*-----------------------------------------------------------------*/
2104 /* unsaveRegisters - pop the pushed registers                      */
2105 /*-----------------------------------------------------------------*/
2106 static void unsaveRegisters (iCode *ic)
2107 {
2108     int i;
2109     bitVect *rsave;
2110
2111     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2112     /* find the registers in use at this time 
2113     and push them away to safety */
2114     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2115                           ic->rUsed);
2116     
2117     if (options.useXstack) {
2118         pic16_emitcode("mov","r0,%s",spname);   
2119         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2120             if (bitVectBitValue(rsave,i)) {
2121                 pic16_emitcode("dec","r0");
2122                 pic16_emitcode("movx","a,@r0");
2123                 if (i == R0_IDX)
2124                     pic16_emitcode("mov","b,a");
2125                 else
2126                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2127             }       
2128
2129         }
2130         pic16_emitcode("mov","%s,r0",spname);
2131         if (bitVectBitValue(rsave,R0_IDX))
2132             pic16_emitcode("mov","r0,b");
2133     } //else
2134     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2135     //    if (bitVectBitValue(rsave,i))
2136     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2137     //}
2138
2139 }  
2140
2141
2142 /*-----------------------------------------------------------------*/
2143 /* pushSide -                                                      */
2144 /*-----------------------------------------------------------------*/
2145 static void pushSide(operand * oper, int size)
2146 {
2147 #if 0
2148         int offset = 0;
2149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2150         while (size--) {
2151                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2152                 if (AOP_TYPE(oper) != AOP_REG &&
2153                     AOP_TYPE(oper) != AOP_DIR &&
2154                     strcmp(l,"a") ) {
2155                         pic16_emitcode("mov","a,%s",l);
2156                         pic16_emitcode("push","acc");
2157                 } else
2158                         pic16_emitcode("push","%s",l);
2159         }
2160 #endif
2161 }
2162
2163 /*-----------------------------------------------------------------*/
2164 /* assignResultValue -                                             */
2165 /*-----------------------------------------------------------------*/
2166 static void assignResultValue(operand * oper)
2167 {
2168   int size = AOP_SIZE(oper);
2169
2170   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2171
2172   DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2173
2174   if(!GpsuedoStkPtr) {
2175     /* The last byte in the assignment is in W */
2176     size--;
2177     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2178     GpsuedoStkPtr++;
2179   }
2180
2181   while (size--) {
2182     pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2183     GpsuedoStkPtr++;
2184     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2185   }
2186 }
2187
2188
2189 /*-----------------------------------------------------------------*/
2190 /* genIpush - genrate code for pushing this gets a little complex  */
2191 /*-----------------------------------------------------------------*/
2192 static void genIpush (iCode *ic)
2193 {
2194
2195   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2196 #if 0
2197     int size, offset = 0 ;
2198     char *l;
2199
2200
2201     /* if this is not a parm push : ie. it is spill push 
2202     and spill push is always done on the local stack */
2203     if (!ic->parmPush) {
2204
2205         /* and the item is spilt then do nothing */
2206         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2207             return ;
2208
2209         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2210         size = AOP_SIZE(IC_LEFT(ic));
2211         /* push it on the stack */
2212         while(size--) {
2213             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2214             if (*l == '#') {
2215                 MOVA(l);
2216                 l = "acc";
2217             }
2218             pic16_emitcode("push","%s",l);
2219         }
2220         return ;        
2221     }
2222
2223     /* this is a paramter push: in this case we call
2224     the routine to find the call and save those
2225     registers that need to be saved */   
2226     saveRegisters(ic);
2227
2228     /* then do the push */
2229     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2230
2231
2232         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2233     size = AOP_SIZE(IC_LEFT(ic));
2234
2235     while (size--) {
2236         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2237         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2238             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2239             strcmp(l,"a") ) {
2240             pic16_emitcode("mov","a,%s",l);
2241             pic16_emitcode("push","acc");
2242         } else
2243             pic16_emitcode("push","%s",l);
2244     }       
2245
2246     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2247 #endif
2248 }
2249
2250 /*-----------------------------------------------------------------*/
2251 /* genIpop - recover the registers: can happen only for spilling   */
2252 /*-----------------------------------------------------------------*/
2253 static void genIpop (iCode *ic)
2254 {
2255   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2256 #if 0
2257     int size,offset ;
2258
2259
2260     /* if the temp was not pushed then */
2261     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2262         return ;
2263
2264     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2265     size = AOP_SIZE(IC_LEFT(ic));
2266     offset = (size-1);
2267     while (size--) 
2268         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2269                                    FALSE,TRUE));
2270
2271     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2272 #endif
2273 }
2274
2275 /*-----------------------------------------------------------------*/
2276 /* unsaverbank - restores the resgister bank from stack            */
2277 /*-----------------------------------------------------------------*/
2278 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2279 {
2280   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2281 #if 0
2282     int i;
2283     asmop *aop ;
2284     regs *r = NULL;
2285
2286     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2287     if (popPsw) {
2288         if (options.useXstack) {
2289             aop = newAsmop(0);
2290             r = getFreePtr(ic,&aop,FALSE);
2291             
2292             
2293             pic16_emitcode("mov","%s,_spx",r->name);
2294             pic16_emitcode("movx","a,@%s",r->name);
2295             pic16_emitcode("mov","psw,a");
2296             pic16_emitcode("dec","%s",r->name);
2297             
2298         }else
2299             pic16_emitcode ("pop","psw");
2300     }
2301
2302     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2303         if (options.useXstack) {       
2304             pic16_emitcode("movx","a,@%s",r->name);
2305             //pic16_emitcode("mov","(%s+%d),a",
2306             //       regspic16[i].base,8*bank+regspic16[i].offset);
2307             pic16_emitcode("dec","%s",r->name);
2308
2309         } else 
2310           pic16_emitcode("pop",""); //"(%s+%d)",
2311         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2312     }
2313
2314     if (options.useXstack) {
2315
2316         pic16_emitcode("mov","_spx,%s",r->name);
2317         pic16_freeAsmop(NULL,aop,ic,TRUE);
2318
2319     }
2320 #endif 
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /* saverbank - saves an entire register bank on the stack          */
2325 /*-----------------------------------------------------------------*/
2326 static void saverbank (int bank, iCode *ic, bool pushPsw)
2327 {
2328   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2329 #if 0
2330     int i;
2331     asmop *aop ;
2332     regs *r = NULL;
2333
2334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2335     if (options.useXstack) {
2336
2337         aop = newAsmop(0);
2338         r = getFreePtr(ic,&aop,FALSE);  
2339         pic16_emitcode("mov","%s,_spx",r->name);
2340
2341     }
2342
2343     for (i = 0 ; i < pic16_nRegs ;i++) {
2344         if (options.useXstack) {
2345             pic16_emitcode("inc","%s",r->name);
2346             //pic16_emitcode("mov","a,(%s+%d)",
2347             //         regspic16[i].base,8*bank+regspic16[i].offset);
2348             pic16_emitcode("movx","@%s,a",r->name);           
2349         } else 
2350           pic16_emitcode("push","");// "(%s+%d)",
2351                      //regspic16[i].base,8*bank+regspic16[i].offset);
2352     }
2353     
2354     if (pushPsw) {
2355         if (options.useXstack) {
2356             pic16_emitcode("mov","a,psw");
2357             pic16_emitcode("movx","@%s,a",r->name);     
2358             pic16_emitcode("inc","%s",r->name);
2359             pic16_emitcode("mov","_spx,%s",r->name);       
2360             pic16_freeAsmop (NULL,aop,ic,TRUE);
2361             
2362         } else
2363             pic16_emitcode("push","psw");
2364         
2365         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2366     }
2367     ic->bankSaved = 1;
2368 #endif
2369 }
2370
2371 /*-----------------------------------------------------------------*/
2372 /* genCall - generates a call statement                            */
2373 /*-----------------------------------------------------------------*/
2374 static void genCall (iCode *ic)
2375 {
2376   sym_link *dtype;   
2377
2378   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2379
2380   /* if caller saves & we have not saved then */
2381   if (!ic->regsSaved)
2382     saveRegisters(ic);
2383
2384   /* if we are calling a function that is not using
2385      the same register bank then we need to save the
2386      destination registers on the stack */
2387   dtype = operandType(IC_LEFT(ic));
2388   if (currFunc && dtype && 
2389       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2390       IFFUNC_ISISR(currFunc->type) &&
2391       !ic->bankSaved) 
2392
2393     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2394
2395   /* if send set is not empty the assign */
2396   if (_G.sendSet) {
2397     iCode *sic;
2398     /* For the Pic port, there is no data stack.
2399      * So parameters passed to functions are stored
2400      * in registers. (The pCode optimizer will get
2401      * rid of most of these :).
2402      */
2403     int psuedoStkPtr=-1; 
2404     int firstTimeThruLoop = 1;
2405
2406     _G.sendSet = reverseSet(_G.sendSet);
2407
2408     /* First figure how many parameters are getting passed */
2409     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2410          sic = setNextItem(_G.sendSet)) {
2411
2412       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2413       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2414       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2415     }
2416
2417     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2418          sic = setNextItem(_G.sendSet)) {
2419       int size, offset = 0;
2420
2421       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2422       size = AOP_SIZE(IC_LEFT(sic));
2423
2424       while (size--) {
2425         DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2426                              pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2427
2428         if(!firstTimeThruLoop) {
2429           /* If this is not the first time we've been through the loop
2430            * then we need to save the parameter in a temporary
2431            * register. The last byte of the last parameter is
2432            * passed in W. */
2433           pic16_emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2434
2435         }
2436         firstTimeThruLoop=0;
2437
2438         //if (strcmp(l,fReturn[offset])) {
2439         mov2w (AOP(IC_LEFT(sic)),  offset);
2440 /*
2441         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2442              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2443           pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2444         else
2445           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2446 */
2447         //}
2448         offset++;
2449       }
2450       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2451     }
2452     _G.sendSet = NULL;
2453   }
2454   /* make the call */
2455   pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2456                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2457                                       OP_SYMBOL(IC_LEFT(ic))->name));
2458
2459   GpsuedoStkPtr=0;
2460   /* if we need assign a result value */
2461   if ((IS_ITEMP(IC_RESULT(ic)) && 
2462        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2463         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2464       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2465
2466     _G.accInUse++;
2467     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2468     _G.accInUse--;
2469
2470     assignResultValue(IC_RESULT(ic));
2471
2472     DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2473                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2474                 
2475     pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2476   }
2477
2478   /* adjust the stack for parameters if 
2479      required */
2480   if (ic->parmBytes) {
2481     int i;
2482     if (ic->parmBytes > 3) {
2483       pic16_emitcode("mov","a,%s",spname);
2484       pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2485       pic16_emitcode("mov","%s,a",spname);
2486     } else 
2487       for ( i = 0 ; i <  ic->parmBytes ;i++)
2488         pic16_emitcode("dec","%s",spname);
2489
2490   }
2491
2492   /* if register bank was saved then pop them */
2493   if (ic->bankSaved)
2494     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2495
2496   /* if we hade saved some registers then unsave them */
2497   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2498     unsaveRegisters (ic);
2499
2500
2501 }
2502
2503 /*-----------------------------------------------------------------*/
2504 /* genPcall - generates a call by pointer statement                */
2505 /*-----------------------------------------------------------------*/
2506 static void genPcall (iCode *ic)
2507 {
2508     sym_link *dtype;
2509     symbol *rlbl = newiTempLabel(NULL);
2510
2511
2512     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2513     /* if caller saves & we have not saved then */
2514     if (!ic->regsSaved)
2515         saveRegisters(ic);
2516
2517     /* if we are calling a function that is not using
2518     the same register bank then we need to save the
2519     destination registers on the stack */
2520     dtype = operandType(IC_LEFT(ic));
2521     if (currFunc && dtype && 
2522         IFFUNC_ISISR(currFunc->type) &&
2523         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2524         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2525
2526
2527     /* push the return address on to the stack */
2528     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2529     pic16_emitcode("push","acc");    
2530     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2531     pic16_emitcode("push","acc");
2532     
2533     if (options.model == MODEL_FLAT24)
2534     {
2535         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2536         pic16_emitcode("push","acc");    
2537     }
2538
2539     /* now push the calling address */
2540     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2541
2542     pushSide(IC_LEFT(ic), FPTRSIZE);
2543
2544     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2545
2546     /* if send set is not empty the assign */
2547     if (_G.sendSet) {
2548         iCode *sic ;
2549
2550         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2551              sic = setNextItem(_G.sendSet)) {
2552             int size, offset = 0;
2553             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2554             size = AOP_SIZE(IC_LEFT(sic));
2555             while (size--) {
2556                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2557                                 FALSE,FALSE);
2558                 if (strcmp(l,fReturn[offset]))
2559                     pic16_emitcode("mov","%s,%s",
2560                              fReturn[offset],
2561                              l);
2562                 offset++;
2563             }
2564             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2565         }
2566         _G.sendSet = NULL;
2567     }
2568
2569     pic16_emitcode("ret","");
2570     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2571
2572
2573     /* if we need assign a result value */
2574     if ((IS_ITEMP(IC_RESULT(ic)) &&
2575          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2576           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2577         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2578
2579         _G.accInUse++;
2580         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2581         _G.accInUse--;
2582         
2583         assignResultValue(IC_RESULT(ic));
2584
2585         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2586     }
2587
2588     /* adjust the stack for parameters if 
2589     required */
2590     if (ic->parmBytes) {
2591         int i;
2592         if (ic->parmBytes > 3) {
2593             pic16_emitcode("mov","a,%s",spname);
2594             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2595             pic16_emitcode("mov","%s,a",spname);
2596         } else 
2597             for ( i = 0 ; i <  ic->parmBytes ;i++)
2598                 pic16_emitcode("dec","%s",spname);
2599
2600     }
2601
2602     /* if register bank was saved then unsave them */
2603     if (currFunc && dtype && 
2604         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2605         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2606
2607     /* if we hade saved some registers then
2608     unsave them */
2609     if (ic->regsSaved)
2610         unsaveRegisters (ic);
2611
2612 }
2613
2614 /*-----------------------------------------------------------------*/
2615 /* resultRemat - result  is rematerializable                       */
2616 /*-----------------------------------------------------------------*/
2617 static int resultRemat (iCode *ic)
2618 {
2619   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2620   if (SKIP_IC(ic) || ic->op == IFX)
2621     return 0;
2622
2623   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2624     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2625     if (sym->remat && !POINTER_SET(ic)) 
2626       return 1;
2627   }
2628
2629   return 0;
2630 }
2631
2632 #if defined(__BORLANDC__) || defined(_MSC_VER)
2633 #define STRCASECMP stricmp
2634 #else
2635 #define STRCASECMP strcasecmp
2636 #endif
2637
2638 #if 0
2639 /*-----------------------------------------------------------------*/
2640 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2641 /*-----------------------------------------------------------------*/
2642 static bool inExcludeList(char *s)
2643 {
2644   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2645     int i =0;
2646     
2647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2648     if (options.excludeRegs[i] &&
2649     STRCASECMP(options.excludeRegs[i],"none") == 0)
2650         return FALSE ;
2651
2652     for ( i = 0 ; options.excludeRegs[i]; i++) {
2653         if (options.excludeRegs[i] &&
2654         STRCASECMP(s,options.excludeRegs[i]) == 0)
2655             return TRUE;
2656     }
2657     return FALSE ;
2658 }
2659 #endif
2660
2661 /*-----------------------------------------------------------------*/
2662 /* genFunction - generated code for function entry                 */
2663 /*-----------------------------------------------------------------*/
2664 static void genFunction (iCode *ic)
2665 {
2666     symbol *sym;
2667     sym_link *ftype;
2668
2669     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2670
2671     labelOffset += (max_key+4);
2672     max_key=0;
2673     GpsuedoStkPtr=0;
2674     _G.nRegsSaved = 0;
2675     /* create the function header */
2676     pic16_emitcode(";","-----------------------------------------");
2677     pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2678     pic16_emitcode(";","-----------------------------------------");
2679
2680     pic16_emitcode("","%s:",sym->rname);
2681     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,sym->rname));
2682
2683     ftype = operandType(IC_LEFT(ic));
2684
2685     /* if critical function then turn interrupts off */
2686     if (IFFUNC_ISCRITICAL(ftype))
2687         pic16_emitcode("clr","ea");
2688
2689     /* here we need to generate the equates for the
2690        register bank if required */
2691 #if 0
2692     if (FUNC_REGBANK(ftype) != rbank) {
2693         int i ;
2694
2695         rbank = FUNC_REGBANK(ftype);
2696         for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2697             if (strcmp(regspic16[i].base,"0") == 0)
2698                 pic16_emitcode("","%s = 0x%02x",
2699                          regspic16[i].dname,
2700                          8*rbank+regspic16[i].offset);
2701             else
2702                 pic16_emitcode ("","%s = %s + 0x%02x",
2703                           regspic16[i].dname,
2704                           regspic16[i].base,
2705                           8*rbank+regspic16[i].offset);
2706         }
2707     }
2708 #endif
2709
2710     /* if this is an interrupt service routine then
2711     save acc, b, dpl, dph  */
2712     if (IFFUNC_ISISR(sym->type)) {
2713
2714 #if 0
2715         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_BRA,pic16_newpCodeOp("END_OF_INTERRUPT+2",PO_STR)));
2716         
2717         /* what is the reason of having these 3 NOPS? VR - 030701 */
2718         pic16_emitpcodeNULLop(POC_NOP);
2719         pic16_emitpcodeNULLop(POC_NOP);
2720         pic16_emitpcodeNULLop(POC_NOP);
2721 #endif
2722
2723       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2724       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2725       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2726       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2727
2728       pic16_pBlockConvert2ISR(pb);
2729 #if 0  
2730         if (!inExcludeList("acc"))          
2731             pic16_emitcode ("push","acc");      
2732         if (!inExcludeList("b"))
2733             pic16_emitcode ("push","b");
2734         if (!inExcludeList("dpl"))
2735             pic16_emitcode ("push","dpl");
2736         if (!inExcludeList("dph"))
2737             pic16_emitcode ("push","dph");
2738         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2739         {
2740             pic16_emitcode ("push", "dpx");
2741             /* Make sure we're using standard DPTR */
2742             pic16_emitcode ("push", "dps");
2743             pic16_emitcode ("mov", "dps, #0x00");
2744             if (options.stack10bit)
2745             {   
2746                 /* This ISR could conceivably use DPTR2. Better save it. */
2747                 pic16_emitcode ("push", "dpl1");
2748                 pic16_emitcode ("push", "dph1");
2749                 pic16_emitcode ("push", "dpx1");
2750             }
2751         }
2752         /* if this isr has no bank i.e. is going to
2753            run with bank 0 , then we need to save more
2754            registers :-) */
2755         if (!FUNC_REGBANK(sym->type)) {
2756
2757             /* if this function does not call any other
2758                function then we can be economical and
2759                save only those registers that are used */
2760             if (! IFFUNC_HASFCALL(sym->type)) {
2761                 int i;
2762
2763                 /* if any registers used */
2764                 if (sym->regsUsed) {
2765                     /* save the registers used */
2766                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2767                         if (bitVectBitValue(sym->regsUsed,i) ||
2768                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2769                           pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                         
2770                     }
2771                 }
2772                 
2773             } else {
2774                 /* this function has  a function call cannot
2775                    determines register usage so we will have the
2776                    entire bank */
2777                 saverbank(0,ic,FALSE);
2778             }       
2779         }
2780 #endif
2781     } else {
2782         /* if callee-save to be used for this function
2783            then save the registers being used in this function */
2784         if (IFFUNC_CALLEESAVES(sym->type)) {
2785             int i;
2786             
2787             /* if any registers used */
2788             if (sym->regsUsed) {
2789                 /* save the registers used */
2790                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2791                     if (bitVectBitValue(sym->regsUsed,i) ||
2792                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2793                       //pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2794                         _G.nRegsSaved++;
2795                     }
2796                 }
2797             }
2798         }
2799     }
2800
2801     /* set the register bank to the desired value */
2802     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2803         pic16_emitcode("push","psw");
2804         pic16_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2805     }
2806
2807     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2808
2809         if (options.useXstack) {
2810             pic16_emitcode("mov","r0,%s",spname);
2811             pic16_emitcode("mov","a,_bp");
2812             pic16_emitcode("movx","@r0,a");
2813             pic16_emitcode("inc","%s",spname);
2814         }
2815         else
2816         {
2817             /* set up the stack */
2818             pic16_emitcode ("push","_bp");     /* save the callers stack  */
2819         }
2820         pic16_emitcode ("mov","_bp,%s",spname);
2821     }
2822
2823     /* adjust the stack for the function */
2824     if (sym->stack) {
2825
2826         int i = sym->stack;
2827         if (i > 256 ) 
2828             werror(W_STACK_OVERFLOW,sym->name);
2829
2830         if (i > 3 && sym->recvSize < 4) {              
2831
2832             pic16_emitcode ("mov","a,sp");
2833             pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2834             pic16_emitcode ("mov","sp,a");
2835            
2836         }
2837         else
2838             while(i--)
2839                 pic16_emitcode("inc","sp");
2840     }
2841
2842      if (sym->xstack) {
2843
2844         pic16_emitcode ("mov","a,_spx");
2845         pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2846         pic16_emitcode ("mov","_spx,a");
2847     }    
2848
2849 }
2850
2851 /*-----------------------------------------------------------------*/
2852 /* genEndFunction - generates epilogue for functions               */
2853 /*-----------------------------------------------------------------*/
2854 static void genEndFunction (iCode *ic)
2855 {
2856     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2857
2858     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2859
2860     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2861     {
2862         pic16_emitcode ("mov","%s,_bp",spname);
2863     }
2864
2865     /* if use external stack but some variables were
2866     added to the local stack then decrement the
2867     local stack */
2868     if (options.useXstack && sym->stack) {      
2869         pic16_emitcode("mov","a,sp");
2870         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2871         pic16_emitcode("mov","sp,a");
2872     }
2873
2874
2875     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2876         if (options.useXstack) {
2877             pic16_emitcode("mov","r0,%s",spname);
2878             pic16_emitcode("movx","a,@r0");
2879             pic16_emitcode("mov","_bp,a");
2880             pic16_emitcode("dec","%s",spname);
2881         }
2882         else
2883         {
2884             pic16_emitcode ("pop","_bp");
2885         }
2886     }
2887
2888     /* restore the register bank  */    
2889     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2890         pic16_emitcode ("pop","psw");
2891
2892     if (IFFUNC_ISISR(sym->type)) {
2893
2894         /* now we need to restore the registers */
2895         /* if this isr has no bank i.e. is going to
2896            run with bank 0 , then we need to save more
2897            registers :-) */
2898         if (!FUNC_REGBANK(sym->type)) {
2899             
2900             /* if this function does not call any other
2901                function then we can be economical and
2902                save only those registers that are used */
2903             if (! IFFUNC_HASFCALL(sym->type)) {
2904                 int i;
2905                 
2906                 /* if any registers used */
2907                 if (sym->regsUsed) {
2908                     /* save the registers used */
2909                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2910                         if (bitVectBitValue(sym->regsUsed,i) ||
2911                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2912                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2913                     }
2914                 }
2915                 
2916             } else {
2917                 /* this function has  a function call cannot
2918                    determines register usage so we will have the
2919                    entire bank */
2920                 unsaverbank(0,ic,FALSE);
2921             }       
2922         }
2923 #if 0
2924         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2925         {
2926             if (options.stack10bit)
2927             {
2928                 pic16_emitcode ("pop", "dpx1");
2929                 pic16_emitcode ("pop", "dph1");
2930                 pic16_emitcode ("pop", "dpl1");
2931             }   
2932             pic16_emitcode ("pop", "dps");
2933             pic16_emitcode ("pop", "dpx");
2934         }
2935         if (!inExcludeList("dph"))
2936             pic16_emitcode ("pop","dph");
2937         if (!inExcludeList("dpl"))
2938             pic16_emitcode ("pop","dpl");
2939         if (!inExcludeList("b"))
2940             pic16_emitcode ("pop","b");
2941         if (!inExcludeList("acc"))
2942             pic16_emitcode ("pop","acc");
2943
2944         if (IFFUNC_ISCRITICAL(sym->type))
2945             pic16_emitcode("setb","ea");
2946 #endif
2947
2948         /* if debug then send end of function */
2949 /*      if (options.debug && currFunc) { */
2950         if (currFunc) {
2951             _G.debugLine = 1;
2952             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
2953                      FileBaseName(ic->filename),currFunc->lastLine,
2954                      ic->level,ic->block); 
2955             if (IS_STATIC(currFunc->etype))         
2956                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2957             else
2958                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2959             _G.debugLine = 0;
2960         }
2961         
2962 //      pic16_emitcode ("reti","");
2963
2964         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2965         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
2966         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
2967         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
2968         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
2969
2970 #if 0
2971         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
2972 #endif
2973
2974         pic16_emitpcodeNULLop(POC_RETFIE);
2975
2976     }
2977     else {
2978         if (IFFUNC_ISCRITICAL(sym->type))
2979             pic16_emitcode("setb","ea");
2980         
2981         if (IFFUNC_CALLEESAVES(sym->type)) {
2982             int i;
2983             
2984             /* if any registers used */
2985             if (sym->regsUsed) {
2986                 /* save the registers used */
2987                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2988                     if (bitVectBitValue(sym->regsUsed,i) ||
2989                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2990                       pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2991                 }
2992             }
2993             
2994         }
2995
2996         /* if debug then send end of function */
2997         if (currFunc) {
2998             _G.debugLine = 1;
2999             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3000                      FileBaseName(ic->filename),currFunc->lastLine,
3001                      ic->level,ic->block); 
3002             if (IS_STATIC(currFunc->etype))         
3003                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3004             else
3005                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3006             _G.debugLine = 0;
3007         }
3008
3009         pic16_emitcode ("return","");
3010         pic16_emitpcodeNULLop(POC_RETURN);
3011
3012         /* Mark the end of a function */
3013         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3014     }
3015
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genRet - generate code for return statement                     */
3020 /*-----------------------------------------------------------------*/
3021 static void genRet (iCode *ic)
3022 {
3023   int size,offset = 0 , pushed = 0;
3024     
3025   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3026   /* if we have no return value then
3027      just generate the "ret" */
3028   if (!IC_LEFT(ic)) 
3029     goto jumpret;       
3030     
3031   /* we have something to return then
3032      move the return value into place */
3033   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3034   size = AOP_SIZE(IC_LEFT(ic));
3035     
3036   while (size--) {
3037     char *l ;
3038     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3039       /* #NOCHANGE */
3040       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3041                  FALSE,TRUE);
3042       pic16_emitcode("push","%s",l);
3043       pushed++;
3044     } else {
3045       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3046                  FALSE,FALSE);
3047       if (strcmp(fReturn[offset],l)) {
3048         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3049             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3050           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3051         }else {
3052           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3053         }
3054         if(size) {
3055           pic16_emitpcode(POC_MOVWF,popRegFromIdx(offset + pic16_Gstack_base_addr));
3056         }
3057         offset++;
3058       }
3059     }
3060   }    
3061
3062   if (pushed) {
3063     while(pushed) {
3064       pushed--;
3065       if (strcmp(fReturn[pushed],"a"))
3066         pic16_emitcode("pop",fReturn[pushed]);
3067       else
3068         pic16_emitcode("pop","acc");
3069     }
3070   }
3071   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3072     
3073  jumpret:
3074   /* generate a jump to the return label
3075      if the next is not the return statement */
3076   if (!(ic->next && ic->next->op == LABEL &&
3077         IC_LABEL(ic->next) == returnLabel)) {
3078         
3079     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3080     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3081   }
3082     
3083 }
3084
3085 /*-----------------------------------------------------------------*/
3086 /* genLabel - generates a label                                    */
3087 /*-----------------------------------------------------------------*/
3088 static void genLabel (iCode *ic)
3089 {
3090     /* special case never generate */
3091     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3092     if (IC_LABEL(ic) == entryLabel)
3093         return ;
3094
3095     pic16_emitpLabel(IC_LABEL(ic)->key);
3096     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3097 }
3098
3099 /*-----------------------------------------------------------------*/
3100 /* genGoto - generates a goto                                      */
3101 /*-----------------------------------------------------------------*/
3102 //tsd
3103 static void genGoto (iCode *ic)
3104 {
3105   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3106   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3107 }
3108
3109
3110 /*-----------------------------------------------------------------*/
3111 /* genMultbits :- multiplication of bits                           */
3112 /*-----------------------------------------------------------------*/
3113 static void genMultbits (operand *left, 
3114                          operand *right, 
3115                          operand *result)
3116 {
3117   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3118
3119   if(!pic16_sameRegs(AOP(result),AOP(right)))
3120     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3121
3122   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3123   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3124   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3125
3126 }
3127
3128
3129 /*-----------------------------------------------------------------*/
3130 /* genMultOneByte : 8 bit multiplication & division                */
3131 /*-----------------------------------------------------------------*/
3132 static void genMultOneByte (operand *left,
3133                             operand *right,
3134                             operand *result)
3135 {
3136   sym_link *opetype = operandType(result);
3137
3138   // symbol *lbl ;
3139   int size,offset;
3140
3141   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3142   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3143   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3144
3145   /* (if two literals, the value is computed before) */
3146   /* if one literal, literal on the right */
3147   if (AOP_TYPE(left) == AOP_LIT){
3148     operand *t = right;
3149     right = left;
3150     left = t;
3151   }
3152
3153   size = AOP_SIZE(result);
3154   if(size == 1) {
3155
3156     if (AOP_TYPE(right) == AOP_LIT){
3157       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3158                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3159                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3160                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3161       pic16_emitcode("call","genMultLit");
3162     } else {
3163       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3164                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3165                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3166                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3167       pic16_emitcode("call","pic16_genMult8X8_8");
3168
3169     }
3170     pic16_genMult8X8_8 (left, right,result);
3171
3172
3173     /* signed or unsigned */
3174     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3175     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3176     //MOVA(l);       
3177     //pic16_emitcode("mul","ab");
3178     /* if result size = 1, mul signed = mul unsigned */
3179     //pic16_aopPut(AOP(result),"a",0);
3180
3181   } else {  // (size > 1)
3182
3183     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3184                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3185                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3186                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3187
3188     if (SPEC_USIGN(opetype)){
3189       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3190       pic16_genUMult8X8_16 (left, right, result, NULL);
3191
3192       if (size > 2) {
3193         /* for filling the MSBs */
3194         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3195         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3196       }
3197     }
3198     else{
3199       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3200
3201       pic16_emitcode("mov","a,b");
3202
3203       /* adjust the MSB if left or right neg */
3204
3205       /* if one literal */
3206       if (AOP_TYPE(right) == AOP_LIT){
3207         pic16_emitcode("multiply ","right is a lit");
3208         /* AND literal negative */
3209         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3210           /* adjust MSB (c==0 after mul) */
3211           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3212         }
3213       }
3214       else{
3215         pic16_genSMult8X8_16 (left, right, result, NULL);
3216       }
3217
3218       if(size > 2){
3219         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3220         /* get the sign */
3221         pic16_emitcode("rlc","a");
3222         pic16_emitcode("subb","a,acc");
3223       }
3224     }
3225
3226     size -= 2;   
3227     offset = 2;
3228     if (size > 0)
3229       while (size--)
3230         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3231     //pic16_aopPut(AOP(result),"a",offset++);
3232   }
3233 }
3234
3235 /*-----------------------------------------------------------------*/
3236 /* genMult - generates code for multiplication                     */
3237 /*-----------------------------------------------------------------*/
3238 static void genMult (iCode *ic)
3239 {
3240     operand *left = IC_LEFT(ic);
3241     operand *right = IC_RIGHT(ic);
3242     operand *result= IC_RESULT(ic);   
3243
3244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3245     /* assign the amsops */
3246     pic16_aopOp (left,ic,FALSE);
3247     pic16_aopOp (right,ic,FALSE);
3248     pic16_aopOp (result,ic,TRUE);
3249
3250   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3251
3252     /* special cases first */
3253     /* both are bits */
3254     if (AOP_TYPE(left) == AOP_CRY &&
3255         AOP_TYPE(right)== AOP_CRY) {
3256         genMultbits(left,right,result);
3257         goto release ;
3258     }
3259
3260     /* if both are of size == 1 */
3261     if (AOP_SIZE(left) == 1 &&
3262         AOP_SIZE(right) == 1 ) {
3263         genMultOneByte(left,right,result);
3264         goto release ;
3265     }
3266
3267     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3268
3269     /* should have been converted to function call */
3270     //assert(0) ;
3271
3272 release :
3273     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3274     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3275     pic16_freeAsmop(result,NULL,ic,TRUE); 
3276 }
3277
3278 /*-----------------------------------------------------------------*/
3279 /* genDivbits :- division of bits                                  */
3280 /*-----------------------------------------------------------------*/
3281 static void genDivbits (operand *left, 
3282                         operand *right, 
3283                         operand *result)
3284 {
3285
3286     char *l;
3287
3288     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3289     /* the result must be bit */    
3290     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3291     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3292
3293     MOVA(l);    
3294
3295     pic16_emitcode("div","ab");
3296     pic16_emitcode("rrc","a");
3297     pic16_aopPut(AOP(result),"c",0);
3298 }
3299
3300 /*-----------------------------------------------------------------*/
3301 /* genDivOneByte : 8 bit division                                  */
3302 /*-----------------------------------------------------------------*/
3303 static void genDivOneByte (operand *left,
3304                            operand *right,
3305                            operand *result)
3306 {
3307     sym_link *opetype = operandType(result);
3308     char *l ;
3309     symbol *lbl ;
3310     int size,offset;
3311
3312     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3313     size = AOP_SIZE(result) - 1;
3314     offset = 1;
3315     /* signed or unsigned */
3316     if (SPEC_USIGN(opetype)) {
3317         /* unsigned is easy */
3318         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3319         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3320         MOVA(l);        
3321         pic16_emitcode("div","ab");
3322         pic16_aopPut(AOP(result),"a",0);
3323         while (size--)
3324             pic16_aopPut(AOP(result),zero,offset++);
3325         return ;
3326     }
3327
3328     /* signed is a little bit more difficult */
3329
3330     /* save the signs of the operands */
3331     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3332     MOVA(l);    
3333     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3334     pic16_emitcode("push","acc"); /* save it on the stack */
3335
3336     /* now sign adjust for both left & right */
3337     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3338     MOVA(l);       
3339     lbl = newiTempLabel(NULL);
3340     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3341     pic16_emitcode("cpl","a");   
3342     pic16_emitcode("inc","a");
3343     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3344     pic16_emitcode("mov","b,a");
3345
3346     /* sign adjust left side */
3347     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3348     MOVA(l);
3349
3350     lbl = newiTempLabel(NULL);
3351     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3352     pic16_emitcode("cpl","a");
3353     pic16_emitcode("inc","a");
3354     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3355
3356     /* now the division */
3357     pic16_emitcode("div","ab");
3358     /* we are interested in the lower order
3359     only */
3360     pic16_emitcode("mov","b,a");
3361     lbl = newiTempLabel(NULL);
3362     pic16_emitcode("pop","acc");   
3363     /* if there was an over flow we don't 
3364     adjust the sign of the result */
3365     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3366     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3367     CLRC;
3368     pic16_emitcode("clr","a");
3369     pic16_emitcode("subb","a,b");
3370     pic16_emitcode("mov","b,a");
3371     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3372
3373     /* now we are done */
3374     pic16_aopPut(AOP(result),"b",0);
3375     if(size > 0){
3376         pic16_emitcode("mov","c,b.7");
3377         pic16_emitcode("subb","a,acc");   
3378     }
3379     while (size--)
3380         pic16_aopPut(AOP(result),"a",offset++);
3381
3382 }
3383
3384 /*-----------------------------------------------------------------*/
3385 /* genDiv - generates code for division                            */
3386 /*-----------------------------------------------------------------*/
3387 static void genDiv (iCode *ic)
3388 {
3389     operand *left = IC_LEFT(ic);
3390     operand *right = IC_RIGHT(ic);
3391     operand *result= IC_RESULT(ic);   
3392
3393     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3394     /* assign the amsops */
3395     pic16_aopOp (left,ic,FALSE);
3396     pic16_aopOp (right,ic,FALSE);
3397     pic16_aopOp (result,ic,TRUE);
3398
3399     /* special cases first */
3400     /* both are bits */
3401     if (AOP_TYPE(left) == AOP_CRY &&
3402         AOP_TYPE(right)== AOP_CRY) {
3403         genDivbits(left,right,result);
3404         goto release ;
3405     }
3406
3407     /* if both are of size == 1 */
3408     if (AOP_SIZE(left) == 1 &&
3409         AOP_SIZE(right) == 1 ) {
3410         genDivOneByte(left,right,result);
3411         goto release ;
3412     }
3413
3414     /* should have been converted to function call */
3415     assert(0);
3416 release :
3417     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3418     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3419     pic16_freeAsmop(result,NULL,ic,TRUE); 
3420 }
3421
3422 /*-----------------------------------------------------------------*/
3423 /* genModbits :- modulus of bits                                   */
3424 /*-----------------------------------------------------------------*/
3425 static void genModbits (operand *left, 
3426                         operand *right, 
3427                         operand *result)
3428 {
3429
3430     char *l;
3431
3432     /* the result must be bit */    
3433     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3434     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3435
3436     MOVA(l);       
3437
3438     pic16_emitcode("div","ab");
3439     pic16_emitcode("mov","a,b");
3440     pic16_emitcode("rrc","a");
3441     pic16_aopPut(AOP(result),"c",0);
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* genModOneByte : 8 bit modulus                                   */
3446 /*-----------------------------------------------------------------*/
3447 static void genModOneByte (operand *left,
3448                            operand *right,
3449                            operand *result)
3450 {
3451     sym_link *opetype = operandType(result);
3452     char *l ;
3453     symbol *lbl ;
3454
3455     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3456     /* signed or unsigned */
3457     if (SPEC_USIGN(opetype)) {
3458         /* unsigned is easy */
3459         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3460         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3461         MOVA(l);    
3462         pic16_emitcode("div","ab");
3463         pic16_aopPut(AOP(result),"b",0);
3464         return ;
3465     }
3466
3467     /* signed is a little bit more difficult */
3468
3469     /* save the signs of the operands */
3470     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3471     MOVA(l);
3472
3473     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3474     pic16_emitcode("push","acc"); /* save it on the stack */
3475
3476     /* now sign adjust for both left & right */
3477     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3478     MOVA(l);
3479
3480     lbl = newiTempLabel(NULL);
3481     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3482     pic16_emitcode("cpl","a");   
3483     pic16_emitcode("inc","a");
3484     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3485     pic16_emitcode("mov","b,a"); 
3486
3487     /* sign adjust left side */
3488     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3489     MOVA(l);
3490
3491     lbl = newiTempLabel(NULL);
3492     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3493     pic16_emitcode("cpl","a");   
3494     pic16_emitcode("inc","a");
3495     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3496
3497     /* now the multiplication */
3498     pic16_emitcode("div","ab");
3499     /* we are interested in the lower order
3500     only */
3501     lbl = newiTempLabel(NULL);
3502     pic16_emitcode("pop","acc");   
3503     /* if there was an over flow we don't 
3504     adjust the sign of the result */
3505     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3506     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3507     CLRC ;
3508     pic16_emitcode("clr","a");
3509     pic16_emitcode("subb","a,b");
3510     pic16_emitcode("mov","b,a");
3511     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3512
3513     /* now we are done */
3514     pic16_aopPut(AOP(result),"b",0);
3515
3516 }
3517
3518 /*-----------------------------------------------------------------*/
3519 /* genMod - generates code for division                            */
3520 /*-----------------------------------------------------------------*/
3521 static void genMod (iCode *ic)
3522 {
3523     operand *left = IC_LEFT(ic);
3524     operand *right = IC_RIGHT(ic);
3525     operand *result= IC_RESULT(ic);  
3526
3527     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3528     /* assign the amsops */
3529     pic16_aopOp (left,ic,FALSE);
3530     pic16_aopOp (right,ic,FALSE);
3531     pic16_aopOp (result,ic,TRUE);
3532
3533     /* special cases first */
3534     /* both are bits */
3535     if (AOP_TYPE(left) == AOP_CRY &&
3536         AOP_TYPE(right)== AOP_CRY) {
3537         genModbits(left,right,result);
3538         goto release ;
3539     }
3540
3541     /* if both are of size == 1 */
3542     if (AOP_SIZE(left) == 1 &&
3543         AOP_SIZE(right) == 1 ) {
3544         genModOneByte(left,right,result);
3545         goto release ;
3546     }
3547
3548     /* should have been converted to function call */
3549     assert(0);
3550
3551 release :
3552     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554     pic16_freeAsmop(result,NULL,ic,TRUE); 
3555 }
3556
3557 /*-----------------------------------------------------------------*/
3558 /* genIfxJump :- will create a jump depending on the ifx           */
3559 /*-----------------------------------------------------------------*/
3560 /*
3561   note: May need to add parameter to indicate when a variable is in bit space.
3562 */
3563 static void genIfxJump (iCode *ic, char *jval)
3564 {
3565
3566     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3567     /* if true label then we jump if condition
3568     supplied is true */
3569     if ( IC_TRUE(ic) ) {
3570
3571         if(strcmp(jval,"a") == 0)
3572           emitSKPZ;
3573         else if (strcmp(jval,"c") == 0)
3574           emitSKPC;
3575         else {
3576           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3577           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3578         }
3579
3580         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3581         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3582
3583     }
3584     else {
3585         /* false label is present */
3586         if(strcmp(jval,"a") == 0)
3587           emitSKPNZ;
3588         else if (strcmp(jval,"c") == 0)
3589           emitSKPNC;
3590         else {
3591           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3592           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3593         }
3594
3595         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3596         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3597
3598     }
3599
3600
3601     /* mark the icode as generated */
3602     ic->generated = 1;
3603 }
3604
3605 /*-----------------------------------------------------------------*/
3606 /* genSkip                                                         */
3607 /*-----------------------------------------------------------------*/
3608 static void genSkip(iCode *ifx,int status_bit)
3609 {
3610   if(!ifx)
3611     return;
3612
3613   if ( IC_TRUE(ifx) ) {
3614     switch(status_bit) {
3615     case 'z':
3616       emitSKPNZ;
3617       break;
3618
3619     case 'c':
3620       emitSKPNC;
3621       break;
3622
3623     case 'd':
3624       emitSKPDC;
3625       break;
3626
3627     }
3628
3629     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3630     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3631
3632   } else {
3633
3634     switch(status_bit) {
3635
3636     case 'z':
3637       emitSKPZ;
3638       break;
3639
3640     case 'c':
3641       emitSKPC;
3642       break;
3643
3644     case 'd':
3645       emitSKPDC;
3646       break;
3647     }
3648     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3649     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3650
3651   }
3652
3653 }
3654
3655 /*-----------------------------------------------------------------*/
3656 /* genSkipc                                                        */
3657 /*-----------------------------------------------------------------*/
3658 static void genSkipc(resolvedIfx *rifx)
3659 {
3660   if(!rifx)
3661     return;
3662
3663   if(rifx->condition)
3664     emitSKPC;
3665   else
3666     emitSKPNC;
3667
3668   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3669   rifx->generated = 1;
3670 }
3671
3672 /*-----------------------------------------------------------------*/
3673 /* genSkipz2                                                       */
3674 /*-----------------------------------------------------------------*/
3675 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3676 {
3677   if(!rifx)
3678     return;
3679
3680   if( (rifx->condition ^ invert_condition) & 1)
3681     emitSKPZ;
3682   else
3683     emitSKPNZ;
3684
3685   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3686   rifx->generated = 1;
3687 }
3688
3689 /*-----------------------------------------------------------------*/
3690 /* genSkipz                                                        */
3691 /*-----------------------------------------------------------------*/
3692 static void genSkipz(iCode *ifx, int condition)
3693 {
3694   if(!ifx)
3695     return;
3696
3697   if(condition)
3698     emitSKPNZ;
3699   else
3700     emitSKPZ;
3701
3702   if ( IC_TRUE(ifx) )
3703     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3704   else
3705     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3706
3707   if ( IC_TRUE(ifx) )
3708     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3709   else
3710     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3711
3712 }
3713 /*-----------------------------------------------------------------*/
3714 /* genSkipCond                                                     */
3715 /*-----------------------------------------------------------------*/
3716 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3717 {
3718   if(!rifx)
3719     return;
3720
3721   if(rifx->condition)
3722     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3723   else
3724     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3725
3726
3727   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3728   rifx->generated = 1;
3729 }
3730
3731 #if 0
3732 /*-----------------------------------------------------------------*/
3733 /* genChkZeroes :- greater or less than comparison                 */
3734 /*     For each byte in a literal that is zero, inclusive or the   */
3735 /*     the corresponding byte in the operand with W                */
3736 /*     returns true if any of the bytes are zero                   */
3737 /*-----------------------------------------------------------------*/
3738 static int genChkZeroes(operand *op, int lit,  int size)
3739 {
3740
3741   int i;
3742   int flag =1;
3743
3744   while(size--) {
3745     i = (lit >> (size*8)) & 0xff;
3746
3747     if(i==0) {
3748       if(flag) 
3749         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3750       else
3751         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3752       flag = 0;
3753     }
3754   }
3755
3756   return (flag==0);
3757 }
3758 #endif
3759
3760 /*-----------------------------------------------------------------*/
3761 /* genCmp :- greater or less than comparison                       */
3762 /*-----------------------------------------------------------------*/
3763 static void genCmp (operand *left,operand *right,
3764                     operand *result, iCode *ifx, int sign)
3765 {
3766   int size; //, offset = 0 ;
3767   unsigned long lit = 0L,i = 0;
3768   resolvedIfx rFalseIfx;
3769   //  resolvedIfx rTrueIfx;
3770   symbol *truelbl;
3771   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3772 /*
3773   if(ifx) {
3774     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3775     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3776   }
3777 */
3778
3779   resolveIfx(&rFalseIfx,ifx);
3780   truelbl  = newiTempLabel(NULL);
3781   size = max(AOP_SIZE(left),AOP_SIZE(right));
3782
3783   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3784
3785 #define _swapp
3786
3787   /* if literal is on the right then swap with left */
3788   if ((AOP_TYPE(right) == AOP_LIT)) {
3789     operand *tmp = right ;
3790     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3791     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3792 #ifdef _swapp
3793
3794     lit = (lit - 1) & mask;
3795     right = left;
3796     left = tmp;
3797     rFalseIfx.condition ^= 1;
3798 #endif
3799
3800   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3801     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3802   }
3803
3804
3805   //if(IC_TRUE(ifx) == NULL)
3806   /* if left & right are bit variables */
3807   if (AOP_TYPE(left) == AOP_CRY &&
3808       AOP_TYPE(right) == AOP_CRY ) {
3809     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3810     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3811   } else {
3812     /* subtract right from left if at the
3813        end the carry flag is set then we know that
3814        left is greater than right */
3815
3816     //    {
3817
3818     symbol *lbl  = newiTempLabel(NULL);
3819
3820 #ifndef _swapp
3821     if(AOP_TYPE(right) == AOP_LIT) {
3822
3823       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3824
3825       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3826
3827       /* special cases */
3828
3829       if(lit == 0) {
3830
3831         if(sign != 0) 
3832           genSkipCond(&rFalseIfx,left,size-1,7);
3833         else 
3834           /* no need to compare to 0...*/
3835           /* NOTE: this is a de-generate compare that most certainly 
3836            *       creates some dead code. */
3837           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
3838
3839         if(ifx) ifx->generated = 1;
3840         return;
3841
3842       }
3843       size--;
3844
3845       if(size == 0) {
3846         //i = (lit >> (size*8)) & 0xff;
3847         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3848         
3849         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3850
3851         i = ((0-lit) & 0xff);
3852         if(sign) {
3853           if( i == 0x81) { 
3854             /* lit is 0x7f, all signed chars are less than
3855              * this except for 0x7f itself */
3856             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
3857             genSkipz2(&rFalseIfx,0);
3858           } else {
3859             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
3860             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
3861             genSkipc(&rFalseIfx);
3862           }
3863
3864         } else {
3865           if(lit == 1) {
3866             genSkipz2(&rFalseIfx,1);
3867           } else {
3868             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
3869             genSkipc(&rFalseIfx);
3870           }
3871         }
3872
3873         if(ifx) ifx->generated = 1;
3874         return;
3875       }
3876
3877       /* chars are out of the way. now do ints and longs */
3878
3879
3880       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3881         
3882       /* special cases */
3883
3884       if(sign) {
3885
3886         if(lit == 0) {
3887           genSkipCond(&rFalseIfx,left,size,7);
3888           if(ifx) ifx->generated = 1;
3889           return;
3890         }
3891
3892         if(lit <0x100) {
3893           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3894
3895           //rFalseIfx.condition ^= 1;
3896           //genSkipCond(&rFalseIfx,left,size,7);
3897           //rFalseIfx.condition ^= 1;
3898
3899           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3900           if(rFalseIfx.condition)
3901             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3902           else
3903             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3904
3905           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
3906           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3907           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
3908
3909           while(size > 1)
3910             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
3911
3912           if(rFalseIfx.condition) {
3913             emitSKPZ;
3914             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3915
3916           } else {
3917             emitSKPNZ;
3918           }
3919
3920           genSkipc(&rFalseIfx);
3921           pic16_emitpLabel(truelbl->key);
3922           if(ifx) ifx->generated = 1;
3923           return;
3924
3925         }
3926
3927         if(size == 1) {
3928
3929           if( (lit & 0xff) == 0) {
3930             /* lower byte is zero */
3931             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3932             i = ((lit >> 8) & 0xff) ^0x80;
3933             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3934             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3935             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3936             genSkipc(&rFalseIfx);
3937
3938
3939             if(ifx) ifx->generated = 1;
3940             return;
3941
3942           }
3943         } else {
3944           /* Special cases for signed longs */
3945           if( (lit & 0xffffff) == 0) {
3946             /* lower byte is zero */
3947             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3948             i = ((lit >> 8*3) & 0xff) ^0x80;
3949             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3950             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3951             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3952             genSkipc(&rFalseIfx);
3953
3954
3955             if(ifx) ifx->generated = 1;
3956             return;
3957
3958           }
3959
3960         }
3961
3962
3963         if(lit & (0x80 << (size*8))) {
3964           /* lit is negative */
3965           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3966
3967           //genSkipCond(&rFalseIfx,left,size,7);
3968
3969           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3970
3971           if(rFalseIfx.condition)
3972             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3973           else
3974             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3975
3976
3977         } else {
3978           /* lit is positive */
3979           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3980           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3981           if(rFalseIfx.condition)
3982             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3983           else
3984             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3985
3986         }
3987
3988         /*
3989           This works, but is only good for ints.
3990           It also requires a "known zero" register.
3991           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
3992           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3993           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
3994           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
3995           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
3996           genSkipc(&rFalseIfx);
3997
3998           pic16_emitpLabel(truelbl->key);
3999           if(ifx) ifx->generated = 1;
4000           return;
4001         **/
4002           
4003         /* There are no more special cases, so perform a general compare */
4004   
4005         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4006         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4007
4008         while(size--) {
4009
4010           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4011           emitSKPNZ;
4012           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4013         }
4014         //rFalseIfx.condition ^= 1;
4015         genSkipc(&rFalseIfx);
4016
4017         pic16_emitpLabel(truelbl->key);
4018
4019         if(ifx) ifx->generated = 1;
4020         return;
4021
4022
4023       }
4024
4025
4026       /* sign is out of the way. So now do an unsigned compare */
4027       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4028
4029
4030       /* General case - compare to an unsigned literal on the right.*/
4031
4032       i = (lit >> (size*8)) & 0xff;
4033       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4034       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4035       while(size--) {
4036         i = (lit >> (size*8)) & 0xff;
4037
4038         if(i) {
4039           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4040           emitSKPNZ;
4041           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4042         } else {
4043           /* this byte of the lit is zero, 
4044            *if it's not the last then OR in the variable */
4045           if(size)
4046             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4047         }
4048       }
4049
4050
4051       pic16_emitpLabel(lbl->key);
4052       //if(emitFinalCheck)
4053       genSkipc(&rFalseIfx);
4054       if(sign)
4055         pic16_emitpLabel(truelbl->key);
4056
4057       if(ifx) ifx->generated = 1;
4058       return;
4059
4060
4061     }
4062 #endif  // _swapp
4063
4064     if(AOP_TYPE(left) == AOP_LIT) {
4065       //symbol *lbl = newiTempLabel(NULL);
4066
4067       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4068
4069
4070       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4071
4072       /* Special cases */
4073       if((lit == 0) && (sign == 0)){
4074
4075         size--;
4076         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4077         while(size) 
4078           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4079
4080         genSkipz2(&rFalseIfx,0);
4081         if(ifx) ifx->generated = 1;
4082         return;
4083       }
4084
4085       if(size==1) {
4086         /* Special cases */
4087         lit &= 0xff;
4088         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4089           /* degenerate compare can never be true */
4090           if(rFalseIfx.condition == 0)
4091             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4092
4093           if(ifx) ifx->generated = 1;
4094           return;
4095         }
4096
4097         if(sign) {
4098           /* signed comparisons to a literal byte */
4099
4100           int lp1 = (lit+1) & 0xff;
4101
4102           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4103           switch (lp1) {
4104           case 0:
4105             rFalseIfx.condition ^= 1;
4106             genSkipCond(&rFalseIfx,right,0,7);
4107             break;
4108           case 0x7f:
4109             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4110             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4111             genSkipz2(&rFalseIfx,1);
4112             break;
4113           default:
4114             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4115             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4116             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4117             rFalseIfx.condition ^= 1;
4118             genSkipc(&rFalseIfx);
4119             break;
4120           }
4121         } else {
4122           /* unsigned comparisons to a literal byte */
4123
4124           switch(lit & 0xff ) {
4125           case 0:
4126             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4127             genSkipz2(&rFalseIfx,0);
4128             break;
4129           case 0x7f:
4130             rFalseIfx.condition ^= 1;
4131             genSkipCond(&rFalseIfx,right,0,7);
4132             break;
4133
4134           default:
4135             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4136             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4137             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4138             rFalseIfx.condition ^= 1;
4139             if (AOP_TYPE(result) == AOP_CRY)
4140               genSkipc(&rFalseIfx);
4141             else {
4142               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4143               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4144             }         
4145             break;
4146           }
4147         }
4148
4149         if(ifx) ifx->generated = 1;
4150         //goto check_carry;
4151         return;
4152
4153       } else {
4154
4155         /* Size is greater than 1 */
4156
4157         if(sign) {
4158           int lp1 = lit+1;
4159
4160           size--;
4161
4162           if(lp1 == 0) {
4163             /* this means lit = 0xffffffff, or -1 */
4164
4165
4166             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4167             rFalseIfx.condition ^= 1;
4168             genSkipCond(&rFalseIfx,right,size,7);
4169             if(ifx) ifx->generated = 1;
4170             return;
4171           }
4172
4173           if(lit == 0) {
4174             int s = size;
4175
4176             if(rFalseIfx.condition) {
4177               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4178               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4179             }
4180
4181             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4182             while(size--)
4183               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4184
4185
4186             emitSKPZ;
4187             if(rFalseIfx.condition) {
4188               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4189               pic16_emitpLabel(truelbl->key);
4190             }else {
4191               rFalseIfx.condition ^= 1;
4192               genSkipCond(&rFalseIfx,right,s,7);
4193             }
4194
4195             if(ifx) ifx->generated = 1;
4196             return;
4197           }
4198
4199           if((size == 1) &&  (0 == (lp1&0xff))) {
4200             /* lower byte of signed word is zero */
4201             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4202             i = ((lp1 >> 8) & 0xff) ^0x80;
4203             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4204             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4205             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4206             rFalseIfx.condition ^= 1;
4207             genSkipc(&rFalseIfx);
4208
4209
4210             if(ifx) ifx->generated = 1;
4211             return;
4212           }
4213
4214           if(lit & (0x80 << (size*8))) {
4215             /* Lit is less than zero */
4216             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4217             //rFalseIfx.condition ^= 1;
4218             //genSkipCond(&rFalseIfx,left,size,7);
4219             //rFalseIfx.condition ^= 1;
4220             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4221             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4222
4223             if(rFalseIfx.condition)
4224               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4225             else
4226               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4227
4228
4229           } else {
4230             /* Lit is greater than or equal to zero */
4231             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4232             //rFalseIfx.condition ^= 1;
4233             //genSkipCond(&rFalseIfx,right,size,7);
4234             //rFalseIfx.condition ^= 1;
4235
4236             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4237             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4238
4239             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4240             if(rFalseIfx.condition)
4241               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4242             else
4243               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4244
4245           }
4246
4247
4248           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4249           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4250
4251           while(size--) {
4252
4253             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4254             emitSKPNZ;
4255             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4256           }
4257           rFalseIfx.condition ^= 1;
4258           //rFalseIfx.condition = 1;
4259           genSkipc(&rFalseIfx);
4260
4261           pic16_emitpLabel(truelbl->key);
4262
4263           if(ifx) ifx->generated = 1;
4264           return;
4265           // end of if (sign)
4266         } else {
4267
4268           /* compare word or long to an unsigned literal on the right.*/
4269
4270
4271           size--;
4272           if(lit < 0xff) {
4273             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4274             switch (lit) {
4275             case 0:
4276               break; /* handled above */
4277 /*
4278             case 0xff:
4279               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4280               while(size--)
4281                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4282               genSkipz2(&rFalseIfx,0);
4283               break;
4284 */
4285             default:
4286               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4287               while(--size)
4288                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4289
4290               emitSKPZ;
4291               if(rFalseIfx.condition)
4292                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4293               else
4294                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4295
4296
4297               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4298               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4299
4300               rFalseIfx.condition ^= 1;
4301               genSkipc(&rFalseIfx);
4302             }
4303
4304             pic16_emitpLabel(truelbl->key);
4305
4306             if(ifx) ifx->generated = 1;
4307             return;
4308           }
4309
4310
4311           lit++;
4312           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4313           i = (lit >> (size*8)) & 0xff;
4314
4315           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4316           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4317
4318           while(size--) {
4319             i = (lit >> (size*8)) & 0xff;
4320
4321             if(i) {
4322               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4323               emitSKPNZ;
4324               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4325             } else {
4326               /* this byte of the lit is zero, 
4327                *if it's not the last then OR in the variable */
4328               if(size)
4329                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4330             }
4331           }
4332
4333
4334           pic16_emitpLabel(lbl->key);
4335
4336           rFalseIfx.condition ^= 1;
4337           genSkipc(&rFalseIfx);
4338         }
4339
4340         if(sign)
4341           pic16_emitpLabel(truelbl->key);
4342         if(ifx) ifx->generated = 1;
4343         return;
4344       }
4345     }
4346     /* Compare two variables */
4347
4348     DEBUGpic16_emitcode(";sign","%d",sign);
4349
4350     size--;
4351     if(sign) {
4352       /* Sigh. thus sucks... */
4353       if(size) {
4354         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4355         pic16_emitpcode(POC_MOVWF, popRegFromIdx(pic16_Gstack_base_addr));
4356         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4357         pic16_emitpcode(POC_XORWF, popRegFromIdx(pic16_Gstack_base_addr));
4358         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4359         pic16_emitpcode(POC_SUBFW, popRegFromIdx(pic16_Gstack_base_addr));
4360       } else {
4361         /* Signed char comparison */
4362         /* Special thanks to Nikolai Golovchenko for this snippet */
4363         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4364         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4365         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4366         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4367         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4368         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4369
4370         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4371         genSkipc(&rFalseIfx);
4372           
4373         if(ifx) ifx->generated = 1;
4374         return;
4375       }
4376
4377     } else {
4378
4379       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4380       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4381     }
4382
4383
4384     /* The rest of the bytes of a multi-byte compare */
4385     while (size) {
4386
4387       emitSKPZ;
4388       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4389       size--;
4390
4391       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4392       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4393
4394
4395     }
4396
4397     pic16_emitpLabel(lbl->key);
4398
4399     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4400     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4401         (AOP_TYPE(result) == AOP_REG)) {
4402       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4403       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4404     } else {
4405       genSkipc(&rFalseIfx);
4406     }         
4407     //genSkipc(&rFalseIfx);
4408     if(ifx) ifx->generated = 1;
4409
4410     return;
4411
4412   }
4413
4414   // check_carry:
4415   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4416     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4417     pic16_outBitC(result);
4418   } else {
4419     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4420     /* if the result is used in the next
4421        ifx conditional branch then generate
4422        code a little differently */
4423     if (ifx )
4424       genIfxJump (ifx,"c");
4425     else
4426       pic16_outBitC(result);
4427     /* leave the result in acc */
4428   }
4429
4430 }
4431
4432 /*-----------------------------------------------------------------*/
4433 /* genCmpGt :- greater than comparison                             */
4434 /*-----------------------------------------------------------------*/
4435 static void genCmpGt (iCode *ic, iCode *ifx)
4436 {
4437     operand *left, *right, *result;
4438     sym_link *letype , *retype;
4439     int sign ;
4440
4441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4442     left = IC_LEFT(ic);
4443     right= IC_RIGHT(ic);
4444     result = IC_RESULT(ic);
4445
4446     letype = getSpec(operandType(left));
4447     retype =getSpec(operandType(right));
4448     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4449     /* assign the amsops */
4450     pic16_aopOp (left,ic,FALSE);
4451     pic16_aopOp (right,ic,FALSE);
4452     pic16_aopOp (result,ic,TRUE);
4453
4454     genCmp(right, left, result, ifx, sign);
4455
4456     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4457     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4458     pic16_freeAsmop(result,NULL,ic,TRUE); 
4459 }
4460
4461 /*-----------------------------------------------------------------*/
4462 /* genCmpLt - less than comparisons                                */
4463 /*-----------------------------------------------------------------*/
4464 static void genCmpLt (iCode *ic, iCode *ifx)
4465 {
4466     operand *left, *right, *result;
4467     sym_link *letype , *retype;
4468     int sign ;
4469
4470     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4471     left = IC_LEFT(ic);
4472     right= IC_RIGHT(ic);
4473     result = IC_RESULT(ic);
4474
4475     letype = getSpec(operandType(left));
4476     retype =getSpec(operandType(right));
4477     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4478
4479     /* assign the amsops */
4480     pic16_aopOp (left,ic,FALSE);
4481     pic16_aopOp (right,ic,FALSE);
4482     pic16_aopOp (result,ic,TRUE);
4483
4484     genCmp(left, right, result, ifx, sign);
4485
4486     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488     pic16_freeAsmop(result,NULL,ic,TRUE); 
4489 }
4490
4491 /*-----------------------------------------------------------------*/
4492 /* genc16bit2lit - compare a 16 bit value to a literal             */
4493 /*-----------------------------------------------------------------*/
4494 static void genc16bit2lit(operand *op, int lit, int offset)
4495 {
4496   int i;
4497
4498   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4499   if( (lit&0xff) == 0) 
4500     i=1;
4501   else
4502     i=0;
4503
4504   switch( BYTEofLONG(lit,i)) { 
4505   case 0:
4506     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4507     break;
4508   case 1:
4509     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4510     break;
4511   case 0xff:
4512     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4513     break;
4514   default:
4515     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4516     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4517   }
4518
4519   i ^= 1;
4520
4521   switch( BYTEofLONG(lit,i)) { 
4522   case 0:
4523     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4524     break;
4525   case 1:
4526     emitSKPNZ;
4527     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4528     break;
4529   case 0xff:
4530     emitSKPNZ;
4531     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4532     break;
4533   default:
4534     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4535     emitSKPNZ;
4536     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4537
4538   }
4539
4540 }
4541
4542 /*-----------------------------------------------------------------*/
4543 /* gencjneshort - compare and jump if not equal                    */
4544 /*-----------------------------------------------------------------*/
4545 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4546 {
4547   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4548   int offset = 0;
4549   int res_offset = 0;  /* the result may be a different size then left or right */
4550   int res_size = AOP_SIZE(result);
4551   resolvedIfx rIfx;
4552   symbol *lbl;
4553
4554   unsigned long lit = 0L;
4555   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4556   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4557   if(result)
4558     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4559   resolveIfx(&rIfx,ifx);
4560   lbl =  newiTempLabel(NULL);
4561
4562
4563   /* if the left side is a literal or 
4564      if the right is in a pointer register and left 
4565      is not */
4566   if ((AOP_TYPE(left) == AOP_LIT) || 
4567       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4568     operand *t = right;
4569     right = left;
4570     left = t;
4571   }
4572   if(AOP_TYPE(right) == AOP_LIT)
4573     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4574
4575   /* if the right side is a literal then anything goes */
4576   if (AOP_TYPE(right) == AOP_LIT &&
4577       AOP_TYPE(left) != AOP_DIR ) {
4578     switch(size) {
4579     case 2:
4580       genc16bit2lit(left, lit, 0);
4581       emitSKPNZ;
4582       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4583       break;
4584     default:
4585       while (size--) {
4586         if(lit & 0xff) {
4587           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4588           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4589         } else {
4590           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4591         }
4592
4593         emitSKPNZ;
4594         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4595         offset++;
4596         if(res_offset < res_size-1)
4597           res_offset++;
4598         lit >>= 8;
4599       }
4600       break;
4601     }
4602   }
4603
4604   /* if the right side is in a register or in direct space or
4605      if the left is a pointer register & right is not */    
4606   else if (AOP_TYPE(right) == AOP_REG ||
4607            AOP_TYPE(right) == AOP_DIR || 
4608            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4609            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4610     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4611     int lbl_key = lbl->key;
4612
4613     if(result) {
4614       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4615       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4616     }else {
4617       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4618       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4619               __FUNCTION__,__LINE__);
4620       return;
4621     }
4622
4623 /*     switch(size) { */
4624 /*     case 2: */
4625 /*       genc16bit2lit(left, lit, 0); */
4626 /*       emitSKPNZ; */
4627 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4628 /*       break; */
4629 /*     default: */
4630     while (size--) {
4631       int emit_skip=1;
4632       if((AOP_TYPE(left) == AOP_DIR) && 
4633          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4634
4635         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4636         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4637
4638       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4639             
4640         switch (lit & 0xff) {
4641         case 0:
4642           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4643           break;
4644         case 1:
4645           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4646           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4647           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4648           emit_skip=0;
4649           break;
4650         case 0xff:
4651           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4652           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4653           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4654           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4655           emit_skip=0;
4656           break;
4657         default:
4658           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4659           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4660         }
4661         lit >>= 8;
4662
4663       } else {
4664         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4665       }
4666       if(emit_skip) {
4667         if(AOP_TYPE(result) == AOP_CRY) {
4668           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4669           if(rIfx.condition)
4670             emitSKPNZ;
4671           else
4672             emitSKPZ;
4673           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4674         } else {
4675           /* fix me. probably need to check result size too */
4676           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4677           if(rIfx.condition)
4678             emitSKPZ;
4679           else
4680             emitSKPNZ;
4681           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4682           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4683         }
4684         if(ifx)
4685           ifx->generated=1;
4686       }
4687       emit_skip++;
4688       offset++;
4689       if(res_offset < res_size-1)
4690         res_offset++;
4691     }
4692 /*       break; */
4693 /*     } */
4694   } else if(AOP_TYPE(right) == AOP_REG &&
4695             AOP_TYPE(left) != AOP_DIR){
4696
4697     while(size--) {
4698       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4699       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4700       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4701       if(rIfx.condition)
4702         emitSKPNZ;
4703       else
4704         emitSKPZ;
4705       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4706       offset++;
4707       if(res_offset < res_size-1)
4708         res_offset++;
4709     }
4710       
4711   }else{
4712     /* right is a pointer reg need both a & b */
4713     while(size--) {
4714       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4715       if(strcmp(l,"b"))
4716         pic16_emitcode("mov","b,%s",l);
4717       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4718       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4719       offset++;
4720     }
4721   }
4722
4723   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4724   if(!rIfx.condition)
4725     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4726
4727   pic16_emitpLabel(lbl->key);
4728
4729   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4730
4731   if(ifx)
4732     ifx->generated = 1;
4733 }
4734
4735 #if 0
4736 /*-----------------------------------------------------------------*/
4737 /* gencjne - compare and jump if not equal                         */
4738 /*-----------------------------------------------------------------*/
4739 static void gencjne(operand *left, operand *right, iCode *ifx)
4740 {
4741     symbol *tlbl  = newiTempLabel(NULL);
4742
4743     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4744     gencjneshort(left, right, lbl);
4745
4746     pic16_emitcode("mov","a,%s",one);
4747     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4748     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4749     pic16_emitcode("clr","a");
4750     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4751
4752     pic16_emitpLabel(lbl->key);
4753     pic16_emitpLabel(tlbl->key);
4754
4755 }
4756 #endif
4757
4758 /*-----------------------------------------------------------------*/
4759 /* genCmpEq - generates code for equal to                          */
4760 /*-----------------------------------------------------------------*/
4761 static void genCmpEq (iCode *ic, iCode *ifx)
4762 {
4763     operand *left, *right, *result;
4764     unsigned long lit = 0L;
4765     int size,offset=0;
4766
4767     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4768
4769     if(ifx)
4770       DEBUGpic16_emitcode ("; ifx is non-null","");
4771     else
4772       DEBUGpic16_emitcode ("; ifx is null","");
4773
4774     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4775     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4776     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4777
4778     size = max(AOP_SIZE(left),AOP_SIZE(right));
4779
4780     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4781
4782     /* if literal, literal on the right or 
4783     if the right is in a pointer register and left 
4784     is not */
4785     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4786         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4787       operand *tmp = right ;
4788       right = left;
4789       left = tmp;
4790     }
4791
4792
4793     if(ifx && !AOP_SIZE(result)){
4794         symbol *tlbl;
4795         /* if they are both bit variables */
4796         if (AOP_TYPE(left) == AOP_CRY &&
4797             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4798             if(AOP_TYPE(right) == AOP_LIT){
4799                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4800                 if(lit == 0L){
4801                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4802                     pic16_emitcode("cpl","c");
4803                 } else if(lit == 1L) {
4804                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4805                 } else {
4806                     pic16_emitcode("clr","c");
4807                 }
4808                 /* AOP_TYPE(right) == AOP_CRY */
4809             } else {
4810                 symbol *lbl = newiTempLabel(NULL);
4811                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4812                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4813                 pic16_emitcode("cpl","c");
4814                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4815             }
4816             /* if true label then we jump if condition
4817             supplied is true */
4818             tlbl = newiTempLabel(NULL);
4819             if ( IC_TRUE(ifx) ) {
4820                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4821                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4822             } else {
4823                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4824                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4825             }
4826             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4827
4828             {
4829               /* left and right are both bit variables, result is carry */
4830               resolvedIfx rIfx;
4831               
4832               resolveIfx(&rIfx,ifx);
4833
4834               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4835               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4836               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4837               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4838               genSkipz2(&rIfx,0);
4839             }
4840         } else {
4841
4842           /* They're not both bit variables. Is the right a literal? */
4843           if(AOP_TYPE(right) == AOP_LIT) {
4844             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4845             
4846             switch(size) {
4847
4848             case 1:
4849               switch(lit & 0xff) {
4850               case 1:
4851                 if ( IC_TRUE(ifx) ) {
4852                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4853                   emitSKPNZ;
4854                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4855                 } else {
4856                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4857                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4858                 }
4859                 break;
4860               case 0xff:
4861                 if ( IC_TRUE(ifx) ) {
4862                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4863                   emitSKPNZ;
4864                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4865                 } else {
4866                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4867                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4868                 }
4869                 break;
4870               default:
4871                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4872                 if(lit)
4873                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4874                 genSkip(ifx,'z');
4875               }
4876
4877
4878               /* end of size == 1 */
4879               break;
4880               
4881             case 2:
4882               genc16bit2lit(left,lit,offset);
4883               genSkip(ifx,'z');
4884               break;
4885               /* end of size == 2 */
4886
4887             default:
4888               /* size is 4 */
4889               if(lit==0) {
4890                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4891                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4892                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4893                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4894
4895               } else {
4896
4897                 /* search for patterns that can be optimized */
4898
4899                 genc16bit2lit(left,lit,0);
4900                 lit >>= 16;
4901                 if(lit) {
4902                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4903                   //genSkip(ifx,'z');
4904                   genc16bit2lit(left,lit,2);
4905                 } else {
4906                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4907                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4908
4909                 }
4910                 
4911               }
4912
4913               genSkip(ifx,'z');
4914             }
4915           
4916             ifx->generated = 1;
4917             goto release ;
4918             
4919
4920           } else if(AOP_TYPE(right) == AOP_CRY ) {
4921             /* we know the left is not a bit, but that the right is */
4922             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4923             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4924                       pic16_popGet(AOP(right),offset));
4925             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4926
4927             /* if the two are equal, then W will be 0 and the Z bit is set
4928              * we could test Z now, or go ahead and check the high order bytes if
4929              * the variable we're comparing is larger than a byte. */
4930
4931             while(--size)
4932               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4933
4934             if ( IC_TRUE(ifx) ) {
4935               emitSKPNZ;
4936               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4937               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4938             } else {
4939               emitSKPZ;
4940               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4941               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4942             }
4943
4944           } else {
4945             /* They're both variables that are larger than bits */
4946             int s = size;
4947
4948             tlbl = newiTempLabel(NULL);
4949
4950             while(size--) {
4951               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4952               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4953
4954               if ( IC_TRUE(ifx) ) {
4955                 if(size) {
4956                   emitSKPZ;
4957                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4958                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4959                 } else {
4960                   emitSKPNZ;
4961                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4962                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4963                 }
4964               } else {
4965                 emitSKPZ;
4966                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4967                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4968               }
4969               offset++;
4970             }
4971             if(s>1 && IC_TRUE(ifx)) {
4972               pic16_emitpLabel(tlbl->key);
4973               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4974             }
4975           }
4976         }
4977         /* mark the icode as generated */
4978         ifx->generated = 1;
4979         goto release ;
4980     }
4981
4982     /* if they are both bit variables */
4983     if (AOP_TYPE(left) == AOP_CRY &&
4984         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4985         if(AOP_TYPE(right) == AOP_LIT){
4986             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4987             if(lit == 0L){
4988                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4989                 pic16_emitcode("cpl","c");
4990             } else if(lit == 1L) {
4991                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4992             } else {
4993                 pic16_emitcode("clr","c");
4994             }
4995             /* AOP_TYPE(right) == AOP_CRY */
4996         } else {
4997             symbol *lbl = newiTempLabel(NULL);
4998             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4999             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5000             pic16_emitcode("cpl","c");
5001             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5002         }
5003         /* c = 1 if egal */
5004         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5005             pic16_outBitC(result);
5006             goto release ;
5007         }
5008         if (ifx) {
5009             genIfxJump (ifx,"c");
5010             goto release ;
5011         }
5012         /* if the result is used in an arithmetic operation
5013         then put the result in place */
5014         pic16_outBitC(result);
5015     } else {
5016       
5017       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5018       gencjne(left,right,result,ifx);
5019 /*
5020       if(ifx) 
5021         gencjne(left,right,newiTempLabel(NULL));
5022       else {
5023         if(IC_TRUE(ifx)->key)
5024           gencjne(left,right,IC_TRUE(ifx)->key);
5025         else
5026           gencjne(left,right,IC_FALSE(ifx)->key);
5027         ifx->generated = 1;
5028         goto release ;
5029       }
5030       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5031         pic16_aopPut(AOP(result),"a",0);
5032         goto release ;
5033       }
5034
5035       if (ifx) {
5036         genIfxJump (ifx,"a");
5037         goto release ;
5038       }
5039 */
5040       /* if the result is used in an arithmetic operation
5041          then put the result in place */
5042 /*
5043       if (AOP_TYPE(result) != AOP_CRY) 
5044         pic16_outAcc(result);
5045 */
5046       /* leave the result in acc */
5047     }
5048
5049 release:
5050     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5051     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5052     pic16_freeAsmop(result,NULL,ic,TRUE);
5053 }
5054
5055 /*-----------------------------------------------------------------*/
5056 /* ifxForOp - returns the icode containing the ifx for operand     */
5057 /*-----------------------------------------------------------------*/
5058 static iCode *ifxForOp ( operand *op, iCode *ic )
5059 {
5060     /* if true symbol then needs to be assigned */
5061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5062     if (IS_TRUE_SYMOP(op))
5063         return NULL ;
5064
5065     /* if this has register type condition and
5066     the next instruction is ifx with the same operand
5067     and live to of the operand is upto the ifx only then */
5068     if (ic->next &&
5069         ic->next->op == IFX &&
5070         IC_COND(ic->next)->key == op->key &&
5071         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5072         return ic->next;
5073
5074     if (ic->next &&
5075         ic->next->op == IFX &&
5076         IC_COND(ic->next)->key == op->key) {
5077       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5078       return ic->next;
5079     }
5080
5081     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5082     if (ic->next &&
5083         ic->next->op == IFX)
5084       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5085
5086     if (ic->next &&
5087         ic->next->op == IFX &&
5088         IC_COND(ic->next)->key == op->key) {
5089       DEBUGpic16_emitcode ("; "," key is okay");
5090       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5091                            OP_SYMBOL(op)->liveTo,
5092                            ic->next->seq);
5093     }
5094
5095
5096     return NULL;
5097 }
5098 /*-----------------------------------------------------------------*/
5099 /* genAndOp - for && operation                                     */
5100 /*-----------------------------------------------------------------*/
5101 static void genAndOp (iCode *ic)
5102 {
5103     operand *left,*right, *result;
5104 /*     symbol *tlbl; */
5105
5106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5107     /* note here that && operations that are in an
5108     if statement are taken away by backPatchLabels
5109     only those used in arthmetic operations remain */
5110     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5111     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5112     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5113
5114     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5115
5116     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5117     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5118     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5119
5120     /* if both are bit variables */
5121 /*     if (AOP_TYPE(left) == AOP_CRY && */
5122 /*         AOP_TYPE(right) == AOP_CRY ) { */
5123 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5124 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5125 /*         pic16_outBitC(result); */
5126 /*     } else { */
5127 /*         tlbl = newiTempLabel(NULL); */
5128 /*         pic16_toBoolean(left);     */
5129 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5130 /*         pic16_toBoolean(right); */
5131 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5132 /*         pic16_outBitAcc(result); */
5133 /*     } */
5134
5135     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5136     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5137     pic16_freeAsmop(result,NULL,ic,TRUE);
5138 }
5139
5140
5141 /*-----------------------------------------------------------------*/
5142 /* genOrOp - for || operation                                      */
5143 /*-----------------------------------------------------------------*/
5144 /*
5145   tsd pic port -
5146   modified this code, but it doesn't appear to ever get called
5147 */
5148
5149 static void genOrOp (iCode *ic)
5150 {
5151     operand *left,*right, *result;
5152     symbol *tlbl;
5153
5154     /* note here that || operations that are in an
5155     if statement are taken away by backPatchLabels
5156     only those used in arthmetic operations remain */
5157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5158     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5159     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5160     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5161
5162     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5163
5164     /* if both are bit variables */
5165     if (AOP_TYPE(left) == AOP_CRY &&
5166         AOP_TYPE(right) == AOP_CRY ) {
5167       pic16_emitcode("clrc","");
5168       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5169                AOP(left)->aopu.aop_dir,
5170                AOP(left)->aopu.aop_dir);
5171       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5172                AOP(right)->aopu.aop_dir,
5173                AOP(right)->aopu.aop_dir);
5174       pic16_emitcode("setc","");
5175
5176     } else {
5177         tlbl = newiTempLabel(NULL);
5178         pic16_toBoolean(left);
5179         emitSKPZ;
5180         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5181         pic16_toBoolean(right);
5182         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5183
5184         pic16_outBitAcc(result);
5185     }
5186
5187     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5188     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5189     pic16_freeAsmop(result,NULL,ic,TRUE);            
5190 }
5191
5192 /*-----------------------------------------------------------------*/
5193 /* isLiteralBit - test if lit == 2^n                               */
5194 /*-----------------------------------------------------------------*/
5195 static int isLiteralBit(unsigned long lit)
5196 {
5197     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5198     0x100L,0x200L,0x400L,0x800L,
5199     0x1000L,0x2000L,0x4000L,0x8000L,
5200     0x10000L,0x20000L,0x40000L,0x80000L,
5201     0x100000L,0x200000L,0x400000L,0x800000L,
5202     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5203     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5204     int idx;
5205     
5206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5207     for(idx = 0; idx < 32; idx++)
5208         if(lit == pw[idx])
5209             return idx+1;
5210     return 0;
5211 }
5212
5213 /*-----------------------------------------------------------------*/
5214 /* continueIfTrue -                                                */
5215 /*-----------------------------------------------------------------*/
5216 static void continueIfTrue (iCode *ic)
5217 {
5218     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5219     if(IC_TRUE(ic))
5220         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5221     ic->generated = 1;
5222 }
5223
5224 /*-----------------------------------------------------------------*/
5225 /* jmpIfTrue -                                                     */
5226 /*-----------------------------------------------------------------*/
5227 static void jumpIfTrue (iCode *ic)
5228 {
5229     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5230     if(!IC_TRUE(ic))
5231         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5232     ic->generated = 1;
5233 }
5234
5235 /*-----------------------------------------------------------------*/
5236 /* jmpTrueOrFalse -                                                */
5237 /*-----------------------------------------------------------------*/
5238 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5239 {
5240     // ugly but optimized by peephole
5241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5242     if(IC_TRUE(ic)){
5243         symbol *nlbl = newiTempLabel(NULL);
5244         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5245         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5246         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5247         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5248     }
5249     else{
5250         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5251         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5252     }
5253     ic->generated = 1;
5254 }
5255
5256 /*-----------------------------------------------------------------*/
5257 /* genAnd  - code for and                                          */
5258 /*-----------------------------------------------------------------*/
5259 static void genAnd (iCode *ic, iCode *ifx)
5260 {
5261   operand *left, *right, *result;
5262   int size, offset=0;  
5263   unsigned long lit = 0L;
5264   int bytelit = 0;
5265   resolvedIfx rIfx;
5266
5267
5268   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5269   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5270   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5271   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5272
5273   resolveIfx(&rIfx,ifx);
5274
5275   /* if left is a literal & right is not then exchange them */
5276   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5277       AOP_NEEDSACC(left)) {
5278     operand *tmp = right ;
5279     right = left;
5280     left = tmp;
5281   }
5282
5283   /* if result = right then exchange them */
5284   if(pic16_sameRegs(AOP(result),AOP(right))){
5285     operand *tmp = right ;
5286     right = left;
5287     left = tmp;
5288   }
5289
5290   /* if right is bit then exchange them */
5291   if (AOP_TYPE(right) == AOP_CRY &&
5292       AOP_TYPE(left) != AOP_CRY){
5293     operand *tmp = right ;
5294     right = left;
5295     left = tmp;
5296   }
5297   if(AOP_TYPE(right) == AOP_LIT)
5298     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5299
5300   size = AOP_SIZE(result);
5301
5302   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5303
5304   // if(bit & yy)
5305   // result = bit & yy;
5306   if (AOP_TYPE(left) == AOP_CRY){
5307     // c = bit & literal;
5308     if(AOP_TYPE(right) == AOP_LIT){
5309       if(lit & 1) {
5310         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5311           // no change
5312           goto release;
5313         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5314       } else {
5315         // bit(result) = 0;
5316         if(size && (AOP_TYPE(result) == AOP_CRY)){
5317           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5318           goto release;
5319         }
5320         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5321           jumpIfTrue(ifx);
5322           goto release;
5323         }
5324         pic16_emitcode("clr","c");
5325       }
5326     } else {
5327       if (AOP_TYPE(right) == AOP_CRY){
5328         // c = bit & bit;
5329         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5330         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5331       } else {
5332         // c = bit & val;
5333         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5334         // c = lsb
5335         pic16_emitcode("rrc","a");
5336         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5337       }
5338     }
5339     // bit = c
5340     // val = c
5341     if(size)
5342       pic16_outBitC(result);
5343     // if(bit & ...)
5344     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5345       genIfxJump(ifx, "c");           
5346     goto release ;
5347   }
5348
5349   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5350   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5351   if((AOP_TYPE(right) == AOP_LIT) &&
5352      (AOP_TYPE(result) == AOP_CRY) &&
5353      (AOP_TYPE(left) != AOP_CRY)){
5354     int posbit = isLiteralBit(lit);
5355     /* left &  2^n */
5356     if(posbit){
5357       posbit--;
5358       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5359       // bit = left & 2^n
5360       if(size)
5361         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5362       // if(left &  2^n)
5363       else{
5364         if(ifx){
5365 /*
5366           if(IC_TRUE(ifx)) {
5367             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5368             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5369           } else {
5370             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5371             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5372           }
5373 */
5374           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5375                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5376           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5377           
5378           ifx->generated = 1;
5379         }
5380         goto release;
5381       }
5382     } else {
5383       symbol *tlbl = newiTempLabel(NULL);
5384       int sizel = AOP_SIZE(left);
5385       if(size)
5386         pic16_emitcode("setb","c");
5387       while(sizel--){
5388         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5389           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5390           // byte ==  2^n ?
5391           if((posbit = isLiteralBit(bytelit)) != 0)
5392             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5393           else{
5394             if(bytelit != 0x0FFL)
5395               pic16_emitcode("anl","a,%s",
5396                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5397             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5398           }
5399         }
5400         offset++;
5401       }
5402       // bit = left & literal
5403       if(size){
5404         pic16_emitcode("clr","c");
5405         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5406       }
5407       // if(left & literal)
5408       else{
5409         if(ifx)
5410           jmpTrueOrFalse(ifx, tlbl);
5411         goto release ;
5412       }
5413     }
5414     pic16_outBitC(result);
5415     goto release ;
5416   }
5417
5418   /* if left is same as result */
5419   if(pic16_sameRegs(AOP(result),AOP(left))){
5420     int know_W = -1;
5421     for(;size--; offset++,lit>>=8) {
5422       if(AOP_TYPE(right) == AOP_LIT){
5423         switch(lit & 0xff) {
5424         case 0x00:
5425           /*  and'ing with 0 has clears the result */
5426 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5427           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5428           break;
5429         case 0xff:
5430           /* and'ing with 0xff is a nop when the result and left are the same */
5431           break;
5432
5433         default:
5434           {
5435             int p = my_powof2( (~lit) & 0xff );
5436             if(p>=0) {
5437               /* only one bit is set in the literal, so use a bcf instruction */
5438 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5439               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5440
5441             } else {
5442               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5443               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5444               if(know_W != (lit&0xff))
5445                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5446               know_W = lit &0xff;
5447               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5448             }
5449           }    
5450         }
5451       } else {
5452         if (AOP_TYPE(left) == AOP_ACC) {
5453           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5454         } else {                    
5455           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5456           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5457
5458         }
5459       }
5460     }
5461
5462   } else {
5463     // left & result in different registers
5464     if(AOP_TYPE(result) == AOP_CRY){
5465       // result = bit
5466       // if(size), result in bit
5467       // if(!size && ifx), conditional oper: if(left & right)
5468       symbol *tlbl = newiTempLabel(NULL);
5469       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5470       if(size)
5471         pic16_emitcode("setb","c");
5472       while(sizer--){
5473         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5474         pic16_emitcode("anl","a,%s",
5475                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5476         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5477         offset++;
5478       }
5479       if(size){
5480         CLRC;
5481         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5482         pic16_outBitC(result);
5483       } else if(ifx)
5484         jmpTrueOrFalse(ifx, tlbl);
5485     } else {
5486       for(;(size--);offset++) {
5487         // normal case
5488         // result = left & right
5489         if(AOP_TYPE(right) == AOP_LIT){
5490           int t = (lit >> (offset*8)) & 0x0FFL;
5491           switch(t) { 
5492           case 0x00:
5493             pic16_emitcode("clrf","%s",
5494                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5495             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5496             break;
5497           case 0xff:
5498             pic16_emitcode("movf","%s,w",
5499                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5500             pic16_emitcode("movwf","%s",
5501                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5502             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5503             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5504             break;
5505           default:
5506             pic16_emitcode("movlw","0x%x",t);
5507             pic16_emitcode("andwf","%s,w",
5508                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5509             pic16_emitcode("movwf","%s",
5510                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5511               
5512             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5513             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5514             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5515           }
5516           continue;
5517         }
5518
5519         if (AOP_TYPE(left) == AOP_ACC) {
5520           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5521           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5522         } else {
5523           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5524           pic16_emitcode("andwf","%s,w",
5525                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5526           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5527           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5528         }
5529         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5530         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5531       }
5532     }
5533   }
5534
5535   release :
5536     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5537   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5538   pic16_freeAsmop(result,NULL,ic,TRUE);     
5539 }
5540
5541 /*-----------------------------------------------------------------*/
5542 /* genOr  - code for or                                            */
5543 /*-----------------------------------------------------------------*/
5544 static void genOr (iCode *ic, iCode *ifx)
5545 {
5546     operand *left, *right, *result;
5547     int size, offset=0;
5548     unsigned long lit = 0L;
5549
5550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5551
5552     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5553     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5554     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5555
5556     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5557
5558     /* if left is a literal & right is not then exchange them */
5559     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5560         AOP_NEEDSACC(left)) {
5561         operand *tmp = right ;
5562         right = left;
5563         left = tmp;
5564     }
5565
5566     /* if result = right then exchange them */
5567     if(pic16_sameRegs(AOP(result),AOP(right))){
5568         operand *tmp = right ;
5569         right = left;
5570         left = tmp;
5571     }
5572
5573     /* if right is bit then exchange them */
5574     if (AOP_TYPE(right) == AOP_CRY &&
5575         AOP_TYPE(left) != AOP_CRY){
5576         operand *tmp = right ;
5577         right = left;
5578         left = tmp;
5579     }
5580
5581     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5582
5583     if(AOP_TYPE(right) == AOP_LIT)
5584         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5585
5586     size = AOP_SIZE(result);
5587
5588     // if(bit | yy)
5589     // xx = bit | yy;
5590     if (AOP_TYPE(left) == AOP_CRY){
5591         if(AOP_TYPE(right) == AOP_LIT){
5592             // c = bit & literal;
5593             if(lit){
5594                 // lit != 0 => result = 1
5595                 if(AOP_TYPE(result) == AOP_CRY){
5596                   if(size)
5597                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5598                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5599                   //     AOP(result)->aopu.aop_dir,
5600                   //     AOP(result)->aopu.aop_dir);
5601                     else if(ifx)
5602                         continueIfTrue(ifx);
5603                     goto release;
5604                 }
5605             } else {
5606                 // lit == 0 => result = left
5607                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5608                     goto release;
5609                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5610             }
5611         } else {
5612             if (AOP_TYPE(right) == AOP_CRY){
5613               if(pic16_sameRegs(AOP(result),AOP(left))){
5614                 // c = bit | bit;
5615                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5616                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5617                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5618
5619                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5620                          AOP(result)->aopu.aop_dir,
5621                          AOP(result)->aopu.aop_dir);
5622                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5623                          AOP(right)->aopu.aop_dir,
5624                          AOP(right)->aopu.aop_dir);
5625                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5626                          AOP(result)->aopu.aop_dir,
5627                          AOP(result)->aopu.aop_dir);
5628               } else {
5629                 if( AOP_TYPE(result) == AOP_ACC) {
5630                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5631                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5632                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5633                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5634
5635                 } else {
5636
5637                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5638                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5639                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5640                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5641
5642                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5643                                  AOP(result)->aopu.aop_dir,
5644                                  AOP(result)->aopu.aop_dir);
5645                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5646                                  AOP(right)->aopu.aop_dir,
5647                                  AOP(right)->aopu.aop_dir);
5648                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5649                                  AOP(left)->aopu.aop_dir,
5650                                  AOP(left)->aopu.aop_dir);
5651                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5652                                  AOP(result)->aopu.aop_dir,
5653                                  AOP(result)->aopu.aop_dir);
5654                 }
5655               }
5656             } else {
5657                 // c = bit | val;
5658                 symbol *tlbl = newiTempLabel(NULL);
5659                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5660
5661
5662                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5663                 if( AOP_TYPE(right) == AOP_ACC) {
5664                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5665                   emitSKPNZ;
5666                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5667                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5668                 }
5669
5670
5671
5672                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5673                     pic16_emitcode(";XXX setb","c");
5674                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5675                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5676                 pic16_toBoolean(right);
5677                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5678                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5679                     jmpTrueOrFalse(ifx, tlbl);
5680                     goto release;
5681                 } else {
5682                     CLRC;
5683                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5684                 }
5685             }
5686         }
5687         // bit = c
5688         // val = c
5689         if(size)
5690             pic16_outBitC(result);
5691         // if(bit | ...)
5692         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5693             genIfxJump(ifx, "c");           
5694         goto release ;
5695     }
5696
5697     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5698     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5699     if((AOP_TYPE(right) == AOP_LIT) &&
5700        (AOP_TYPE(result) == AOP_CRY) &&
5701        (AOP_TYPE(left) != AOP_CRY)){
5702         if(lit){
5703           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5704             // result = 1
5705             if(size)
5706                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5707             else 
5708                 continueIfTrue(ifx);
5709             goto release;
5710         } else {
5711           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5712             // lit = 0, result = boolean(left)
5713             if(size)
5714                 pic16_emitcode(";XXX setb","c");
5715             pic16_toBoolean(right);
5716             if(size){
5717                 symbol *tlbl = newiTempLabel(NULL);
5718                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5719                 CLRC;
5720                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5721             } else {
5722                 genIfxJump (ifx,"a");
5723                 goto release;
5724             }
5725         }
5726         pic16_outBitC(result);
5727         goto release ;
5728     }
5729
5730     /* if left is same as result */
5731     if(pic16_sameRegs(AOP(result),AOP(left))){
5732       int know_W = -1;
5733       for(;size--; offset++,lit>>=8) {
5734         if(AOP_TYPE(right) == AOP_LIT){
5735           if((lit & 0xff) == 0)
5736             /*  or'ing with 0 has no effect */
5737             continue;
5738           else {
5739             int p = my_powof2(lit & 0xff);
5740             if(p>=0) {
5741               /* only one bit is set in the literal, so use a bsf instruction */
5742               pic16_emitpcode(POC_BSF,
5743                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5744             } else {
5745               if(know_W != (lit & 0xff))
5746                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5747               know_W = lit & 0xff;
5748               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5749             }
5750                     
5751           }
5752         } else {
5753           if (AOP_TYPE(left) == AOP_ACC) {
5754             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5755             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5756           } else {                  
5757             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5758             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5759
5760             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5761             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5762
5763           }
5764         }
5765       }
5766     } else {
5767         // left & result in different registers
5768         if(AOP_TYPE(result) == AOP_CRY){
5769             // result = bit
5770             // if(size), result in bit
5771             // if(!size && ifx), conditional oper: if(left | right)
5772             symbol *tlbl = newiTempLabel(NULL);
5773             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5774             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5775
5776
5777             if(size)
5778                 pic16_emitcode(";XXX setb","c");
5779             while(sizer--){
5780                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5781                 pic16_emitcode(";XXX orl","a,%s",
5782                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5783                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5784                 offset++;
5785             }
5786             if(size){
5787                 CLRC;
5788                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5789                 pic16_outBitC(result);
5790             } else if(ifx)
5791                 jmpTrueOrFalse(ifx, tlbl);
5792         } else for(;(size--);offset++){
5793           // normal case
5794           // result = left & right
5795           if(AOP_TYPE(right) == AOP_LIT){
5796             int t = (lit >> (offset*8)) & 0x0FFL;
5797             switch(t) { 
5798             case 0x00:
5799               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5800               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5801
5802               pic16_emitcode("movf","%s,w",
5803                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5804               pic16_emitcode("movwf","%s",
5805                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5806               break;
5807             default:
5808               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5809               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5810               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5811
5812               pic16_emitcode("movlw","0x%x",t);
5813               pic16_emitcode("iorwf","%s,w",
5814                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5815               pic16_emitcode("movwf","%s",
5816                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5817               
5818             }
5819             continue;
5820           }
5821
5822           // faster than result <- left, anl result,right
5823           // and better if result is SFR
5824           if (AOP_TYPE(left) == AOP_ACC) {
5825             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5826             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5827           } else {
5828             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5829             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5830
5831             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5832             pic16_emitcode("iorwf","%s,w",
5833                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5834           }
5835           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5836           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5837         }
5838     }
5839
5840 release :
5841     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5842     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5843     pic16_freeAsmop(result,NULL,ic,TRUE);     
5844 }
5845
5846 /*-----------------------------------------------------------------*/
5847 /* genXor - code for xclusive or                                   */
5848 /*-----------------------------------------------------------------*/
5849 static void genXor (iCode *ic, iCode *ifx)
5850 {
5851   operand *left, *right, *result;
5852   int size, offset=0;
5853   unsigned long lit = 0L;
5854
5855   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5856
5857   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5858   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5859   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5860
5861   /* if left is a literal & right is not ||
5862      if left needs acc & right does not */
5863   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5864       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5865     operand *tmp = right ;
5866     right = left;
5867     left = tmp;
5868   }
5869
5870   /* if result = right then exchange them */
5871   if(pic16_sameRegs(AOP(result),AOP(right))){
5872     operand *tmp = right ;
5873     right = left;
5874     left = tmp;
5875   }
5876
5877   /* if right is bit then exchange them */
5878   if (AOP_TYPE(right) == AOP_CRY &&
5879       AOP_TYPE(left) != AOP_CRY){
5880     operand *tmp = right ;
5881     right = left;
5882     left = tmp;
5883   }
5884   if(AOP_TYPE(right) == AOP_LIT)
5885     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5886
5887   size = AOP_SIZE(result);
5888
5889   // if(bit ^ yy)
5890   // xx = bit ^ yy;
5891   if (AOP_TYPE(left) == AOP_CRY){
5892     if(AOP_TYPE(right) == AOP_LIT){
5893       // c = bit & literal;
5894       if(lit>>1){
5895         // lit>>1  != 0 => result = 1
5896         if(AOP_TYPE(result) == AOP_CRY){
5897           if(size)
5898             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
5899             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5900           else if(ifx)
5901             continueIfTrue(ifx);
5902           goto release;
5903         }
5904         pic16_emitcode("setb","c");
5905       } else{
5906         // lit == (0 or 1)
5907         if(lit == 0){
5908           // lit == 0, result = left
5909           if(size && pic16_sameRegs(AOP(result),AOP(left)))
5910             goto release;
5911           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5912         } else{
5913           // lit == 1, result = not(left)
5914           if(size && pic16_sameRegs(AOP(result),AOP(left))){
5915             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
5916             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
5917             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5918             goto release;
5919           } else {
5920             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5921             pic16_emitcode("cpl","c");
5922           }
5923         }
5924       }
5925
5926     } else {
5927       // right != literal
5928       symbol *tlbl = newiTempLabel(NULL);
5929       if (AOP_TYPE(right) == AOP_CRY){
5930         // c = bit ^ bit;
5931         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5932       }
5933       else{
5934         int sizer = AOP_SIZE(right);
5935         // c = bit ^ val
5936         // if val>>1 != 0, result = 1
5937         pic16_emitcode("setb","c");
5938         while(sizer){
5939           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
5940           if(sizer == 1)
5941             // test the msb of the lsb
5942             pic16_emitcode("anl","a,#0xfe");
5943           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5944           sizer--;
5945         }
5946         // val = (0,1)
5947         pic16_emitcode("rrc","a");
5948       }
5949       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5950       pic16_emitcode("cpl","c");
5951       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
5952     }
5953     // bit = c
5954     // val = c
5955     if(size)
5956       pic16_outBitC(result);
5957     // if(bit | ...)
5958     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5959       genIfxJump(ifx, "c");           
5960     goto release ;
5961   }
5962
5963   if(pic16_sameRegs(AOP(result),AOP(left))){
5964     /* if left is same as result */
5965     for(;size--; offset++) {
5966       if(AOP_TYPE(right) == AOP_LIT){
5967         int t  = (lit >> (offset*8)) & 0x0FFL;
5968         if(t == 0x00L)
5969           continue;
5970         else
5971           if (IS_AOP_PREG(left)) {
5972             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5973             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5974             pic16_aopPut(AOP(result),"a",offset);
5975           } else {
5976             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5977             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5978             pic16_emitcode("xrl","%s,%s",
5979                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
5980                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5981           }
5982       } else {
5983         if (AOP_TYPE(left) == AOP_ACC)
5984           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5985         else {
5986           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5987           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5988 /*
5989           if (IS_AOP_PREG(left)) {
5990             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5991             pic16_aopPut(AOP(result),"a",offset);
5992           } else
5993             pic16_emitcode("xrl","%s,a",
5994                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5995 */
5996         }
5997       }
5998     }
5999   } else {
6000     // left & result in different registers
6001     if(AOP_TYPE(result) == AOP_CRY){
6002       // result = bit
6003       // if(size), result in bit
6004       // if(!size && ifx), conditional oper: if(left ^ right)
6005       symbol *tlbl = newiTempLabel(NULL);
6006       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6007       if(size)
6008         pic16_emitcode("setb","c");
6009       while(sizer--){
6010         if((AOP_TYPE(right) == AOP_LIT) &&
6011            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6012           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6013         } else {
6014           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6015           pic16_emitcode("xrl","a,%s",
6016                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6017         }
6018         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6019         offset++;
6020       }
6021       if(size){
6022         CLRC;
6023         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6024         pic16_outBitC(result);
6025       } else if(ifx)
6026         jmpTrueOrFalse(ifx, tlbl);
6027     } else for(;(size--);offset++){
6028       // normal case
6029       // result = left & right
6030       if(AOP_TYPE(right) == AOP_LIT){
6031         int t = (lit >> (offset*8)) & 0x0FFL;
6032         switch(t) { 
6033         case 0x00:
6034           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6035           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6036           pic16_emitcode("movf","%s,w",
6037                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6038           pic16_emitcode("movwf","%s",
6039                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6040           break;
6041         case 0xff:
6042           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6043           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6044           pic16_emitcode("comf","%s,w",
6045                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6046           pic16_emitcode("movwf","%s",
6047                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6048           break;
6049         default:
6050           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6051           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6052           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6053           pic16_emitcode("movlw","0x%x",t);
6054           pic16_emitcode("xorwf","%s,w",
6055                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6056           pic16_emitcode("movwf","%s",
6057                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6058
6059         }
6060         continue;
6061       }
6062
6063       // faster than result <- left, anl result,right
6064       // and better if result is SFR
6065       if (AOP_TYPE(left) == AOP_ACC) {
6066         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6067         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6068       } else {
6069         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6070         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6071         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6072         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6073       }
6074       if ( AOP_TYPE(result) != AOP_ACC){
6075         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6076         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6077       }
6078     }
6079   }
6080
6081   release :
6082     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6083   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6084   pic16_freeAsmop(result,NULL,ic,TRUE);     
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* genInline - write the inline code out                           */
6089 /*-----------------------------------------------------------------*/
6090 static void genInline (iCode *ic)
6091 {
6092     char *buffer, *bp, *bp1;
6093     
6094     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6095
6096     _G.inLine += (!options.asmpeep);
6097
6098     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6099     strcpy(buffer,IC_INLINE(ic));
6100
6101     /* emit each line as a code */
6102     while (*bp) {
6103         if (*bp == '\n') {
6104             *bp++ = '\0';
6105
6106             if(*bp1)
6107               pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6108             bp1 = bp;
6109         } else {
6110             if (*bp == ':') {
6111                 bp++;
6112                 *bp = '\0';
6113                 bp++;
6114                 pic16_emitcode(bp1,"");
6115                 bp1 = bp;
6116             } else
6117                 bp++;
6118         }
6119     }
6120     if ((bp1 != bp) && *bp1)
6121       pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6122
6123     Safe_free(buffer);
6124
6125     _G.inLine -= (!options.asmpeep);
6126 }
6127
6128 /*-----------------------------------------------------------------*/
6129 /* genRRC - rotate right with carry                                */
6130 /*-----------------------------------------------------------------*/
6131 static void genRRC (iCode *ic)
6132 {
6133   operand *left , *result ;
6134   int size, offset = 0, same;
6135
6136   /* rotate right with carry */
6137   left = IC_LEFT(ic);
6138   result=IC_RESULT(ic);
6139   pic16_aopOp (left,ic,FALSE);
6140   pic16_aopOp (result,ic,FALSE);
6141
6142   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6143
6144   same = pic16_sameRegs(AOP(result),AOP(left));
6145
6146   size = AOP_SIZE(result);    
6147
6148   /* get the lsb and put it into the carry */
6149   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6150
6151   offset = 0 ;
6152
6153   while(size--) {
6154
6155     if(same) {
6156       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6157     } else {
6158       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6159       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6160     }
6161
6162     offset++;
6163   }
6164
6165   pic16_freeAsmop(left,NULL,ic,TRUE);
6166   pic16_freeAsmop(result,NULL,ic,TRUE);
6167 }
6168
6169 /*-----------------------------------------------------------------*/
6170 /* genRLC - generate code for rotate left with carry               */
6171 /*-----------------------------------------------------------------*/
6172 static void genRLC (iCode *ic)
6173 {    
6174   operand *left , *result ;
6175   int size, offset = 0;
6176   int same;
6177
6178   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6179   /* rotate right with carry */
6180   left = IC_LEFT(ic);
6181   result=IC_RESULT(ic);
6182   pic16_aopOp (left,ic,FALSE);
6183   pic16_aopOp (result,ic,FALSE);
6184
6185   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6186
6187   same = pic16_sameRegs(AOP(result),AOP(left));
6188
6189   /* move it to the result */
6190   size = AOP_SIZE(result);    
6191
6192   /* get the msb and put it into the carry */
6193   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6194
6195   offset = 0 ;
6196
6197   while(size--) {
6198
6199     if(same) {
6200       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6201     } else {
6202       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6203       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6204     }
6205
6206     offset++;
6207   }
6208
6209
6210   pic16_freeAsmop(left,NULL,ic,TRUE);
6211   pic16_freeAsmop(result,NULL,ic,TRUE);
6212 }
6213
6214 /*-----------------------------------------------------------------*/
6215 /* genGetHbit - generates code get highest order bit               */
6216 /*-----------------------------------------------------------------*/
6217 static void genGetHbit (iCode *ic)
6218 {
6219     operand *left, *result;
6220     left = IC_LEFT(ic);
6221     result=IC_RESULT(ic);
6222     pic16_aopOp (left,ic,FALSE);
6223     pic16_aopOp (result,ic,FALSE);
6224
6225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6226     /* get the highest order byte into a */
6227     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6228     if(AOP_TYPE(result) == AOP_CRY){
6229         pic16_emitcode("rlc","a");
6230         pic16_outBitC(result);
6231     }
6232     else{
6233         pic16_emitcode("rl","a");
6234         pic16_emitcode("anl","a,#0x01");
6235         pic16_outAcc(result);
6236     }
6237
6238
6239     pic16_freeAsmop(left,NULL,ic,TRUE);
6240     pic16_freeAsmop(result,NULL,ic,TRUE);
6241 }
6242
6243 /*-----------------------------------------------------------------*/
6244 /* AccRol - rotate left accumulator by known count                 */
6245 /*-----------------------------------------------------------------*/
6246 static void AccRol (int shCount)
6247 {
6248     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6249     shCount &= 0x0007;              // shCount : 0..7
6250     switch(shCount){
6251         case 0 :
6252             break;
6253         case 1 :
6254             pic16_emitcode("rl","a");
6255             break;
6256         case 2 :
6257             pic16_emitcode("rl","a");
6258             pic16_emitcode("rl","a");
6259             break;
6260         case 3 :
6261             pic16_emitcode("swap","a");
6262             pic16_emitcode("rr","a");
6263             break;
6264         case 4 :
6265             pic16_emitcode("swap","a");
6266             break;
6267         case 5 :
6268             pic16_emitcode("swap","a");
6269             pic16_emitcode("rl","a");
6270             break;
6271         case 6 :
6272             pic16_emitcode("rr","a");
6273             pic16_emitcode("rr","a");
6274             break;
6275         case 7 :
6276             pic16_emitcode("rr","a");
6277             break;
6278     }
6279 }
6280
6281 /*-----------------------------------------------------------------*/
6282 /* AccLsh - left shift accumulator by known count                  */
6283 /*-----------------------------------------------------------------*/
6284 static void AccLsh (int shCount)
6285 {
6286     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6287     if(shCount != 0){
6288         if(shCount == 1)
6289             pic16_emitcode("add","a,acc");
6290         else 
6291             if(shCount == 2) {
6292             pic16_emitcode("add","a,acc");
6293             pic16_emitcode("add","a,acc");
6294         } else {
6295             /* rotate left accumulator */
6296             AccRol(shCount);
6297             /* and kill the lower order bits */
6298             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6299         }
6300     }
6301 }
6302
6303 /*-----------------------------------------------------------------*/
6304 /* AccRsh - right shift accumulator by known count                 */
6305 /*-----------------------------------------------------------------*/
6306 static void AccRsh (int shCount)
6307 {
6308     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6309     if(shCount != 0){
6310         if(shCount == 1){
6311             CLRC;
6312             pic16_emitcode("rrc","a");
6313         } else {
6314             /* rotate right accumulator */
6315             AccRol(8 - shCount);
6316             /* and kill the higher order bits */
6317             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6318         }
6319     }
6320 }
6321
6322 #if 0
6323 /*-----------------------------------------------------------------*/
6324 /* AccSRsh - signed right shift accumulator by known count                 */
6325 /*-----------------------------------------------------------------*/
6326 static void AccSRsh (int shCount)
6327 {
6328     symbol *tlbl ;
6329     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6330     if(shCount != 0){
6331         if(shCount == 1){
6332             pic16_emitcode("mov","c,acc.7");
6333             pic16_emitcode("rrc","a");
6334         } else if(shCount == 2){
6335             pic16_emitcode("mov","c,acc.7");
6336             pic16_emitcode("rrc","a");
6337             pic16_emitcode("mov","c,acc.7");
6338             pic16_emitcode("rrc","a");
6339         } else {
6340             tlbl = newiTempLabel(NULL);
6341             /* rotate right accumulator */
6342             AccRol(8 - shCount);
6343             /* and kill the higher order bits */
6344             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6345             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6346             pic16_emitcode("orl","a,#0x%02x",
6347                      (unsigned char)~SRMask[shCount]);
6348             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6349         }
6350     }
6351 }
6352 #endif
6353 /*-----------------------------------------------------------------*/
6354 /* shiftR1Left2Result - shift right one byte from left to result   */
6355 /*-----------------------------------------------------------------*/
6356 static void shiftR1Left2ResultSigned (operand *left, int offl,
6357                                 operand *result, int offr,
6358                                 int shCount)
6359 {
6360   int same;
6361
6362   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6363
6364   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6365
6366   switch(shCount) {
6367   case 1:
6368     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6369     if(same) 
6370       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6371     else {
6372       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6373       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6374     }
6375
6376     break;
6377   case 2:
6378
6379     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6380     if(same) 
6381       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6382     else {
6383       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6384       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6385     }
6386     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6387     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6388
6389     break;
6390
6391   case 3:
6392     if(same)
6393       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6394     else {
6395       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6396       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6397     }
6398
6399     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6400     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6401     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6402
6403     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6404     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6405
6406     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6407     break;
6408
6409   case 4:
6410     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6411     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6412     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6413     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6414     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6415     break;
6416   case 5:
6417     if(same) {
6418       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6419     } else {
6420       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6421       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6422     }
6423     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6424     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6425     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6426     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6427     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6428     break;
6429
6430   case 6:
6431     if(same) {
6432       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6433       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6434       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6435       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6436       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6437       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6438     } else {
6439       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6440       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6441       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6442       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6443       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6444     }
6445     break;
6446
6447   case 7:
6448     if(same) {
6449       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6450       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6451       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6452       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6453     } else {
6454       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6455       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6456       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6457     }
6458
6459   default:
6460     break;
6461   }
6462 }
6463
6464 /*-----------------------------------------------------------------*/
6465 /* shiftR1Left2Result - shift right one byte from left to result   */
6466 /*-----------------------------------------------------------------*/
6467 static void shiftR1Left2Result (operand *left, int offl,
6468                                 operand *result, int offr,
6469                                 int shCount, int sign)
6470 {
6471   int same;
6472
6473   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6474
6475   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6476
6477   /* Copy the msb into the carry if signed. */
6478   if(sign) {
6479     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6480     return;
6481   }
6482
6483
6484
6485   switch(shCount) {
6486   case 1:
6487     emitCLRC;
6488     if(same) 
6489       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6490     else {
6491       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6492       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6493     }
6494     break;
6495   case 2:
6496     emitCLRC;
6497     if(same) {
6498       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6499     } else {
6500       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6501       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6502     }
6503     emitCLRC;
6504     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6505
6506     break;
6507   case 3:
6508     if(same)
6509       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6510     else {
6511       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6512       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6513     }
6514
6515     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6516     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6517     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6518     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6519     break;
6520       
6521   case 4:
6522     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6523     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6524     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6525     break;
6526
6527   case 5:
6528     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6529     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6530     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6531     emitCLRC;
6532     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6533
6534     break;
6535   case 6:
6536
6537     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6538     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6539     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6540     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6541     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6542     break;
6543
6544   case 7:
6545
6546     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6547     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6548     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6549
6550     break;
6551
6552   default:
6553     break;
6554   }
6555 }
6556
6557 /*-----------------------------------------------------------------*/
6558 /* shiftL1Left2Result - shift left one byte from left to result    */
6559 /*-----------------------------------------------------------------*/
6560 static void shiftL1Left2Result (operand *left, int offl,
6561                                 operand *result, int offr, int shCount)
6562 {
6563   int same;
6564
6565   //    char *l;
6566   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6567
6568   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6569   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6570     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6571     //    MOVA(l);
6572     /* shift left accumulator */
6573     //AccLsh(shCount); // don't comment out just yet...
6574   //    pic16_aopPut(AOP(result),"a",offr);
6575
6576   switch(shCount) {
6577   case 1:
6578     /* Shift left 1 bit position */
6579     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6580     if(same) {
6581       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6582     } else {
6583       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6584       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6585     }
6586     break;
6587   case 2:
6588     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6589     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6590     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6591     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6592     break;
6593   case 3:
6594     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6595     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6596     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6597     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6598     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6599     break;
6600   case 4:
6601     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6602     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6603     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6604     break;
6605   case 5:
6606     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6607     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6608     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6609     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6610     break;
6611   case 6:
6612     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6613     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
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 7:
6619     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6620     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6621     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6622     break;
6623
6624   default:
6625     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6626   }
6627
6628 }
6629
6630 /*-----------------------------------------------------------------*/
6631 /* movLeft2Result - move byte from left to result                  */
6632 /*-----------------------------------------------------------------*/
6633 static void movLeft2Result (operand *left, int offl,
6634                             operand *result, int offr)
6635 {
6636   char *l;
6637   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6638   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6639     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6640
6641     if (*l == '@' && (IS_AOP_PREG(result))) {
6642       pic16_emitcode("mov","a,%s",l);
6643       pic16_aopPut(AOP(result),"a",offr);
6644     } else {
6645       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6646       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6647     }
6648   }
6649 }
6650
6651 /*-----------------------------------------------------------------*/
6652 /* shiftL2Left2Result - shift left two bytes from left to result   */
6653 /*-----------------------------------------------------------------*/
6654 static void shiftL2Left2Result (operand *left, int offl,
6655                                 operand *result, int offr, int shCount)
6656 {
6657
6658
6659   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6660
6661   if(pic16_sameRegs(AOP(result), AOP(left))) {
6662     switch(shCount) {
6663     case 0:
6664       break;
6665     case 1:
6666     case 2:
6667     case 3:
6668
6669       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6670       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6671       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6672
6673       while(--shCount) {
6674         emitCLRC;
6675         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6676         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6677       }
6678
6679       break;
6680     case 4:
6681     case 5:
6682       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6683       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6684       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6685       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6686       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6687       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6688       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6689       if(shCount >=5) {
6690         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6691         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6692       }
6693       break;
6694     case 6:
6695       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6696       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6697       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6698       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6699       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6700       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6701       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6702       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6703       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6704       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6705       break;
6706     case 7:
6707       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6708       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6709       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6710       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6711       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6712     }
6713
6714   } else {
6715     switch(shCount) {
6716     case 0:
6717       break;
6718     case 1:
6719     case 2:
6720     case 3:
6721       /* note, use a mov/add for the shift since the mov has a
6722          chance of getting optimized out */
6723       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6724       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6725       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6726       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6727       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6728
6729       while(--shCount) {
6730         emitCLRC;
6731         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6732         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6733       }
6734       break;
6735
6736     case 4:
6737     case 5:
6738       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6739       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6740       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6741       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6742       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6743       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6744       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6745       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6746
6747
6748       if(shCount == 5) {
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     case 6:
6754       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6755       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6756       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6757       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6758
6759       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6760       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6761       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6762       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6763       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6764       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6765       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6766       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6767       break;
6768     case 7:
6769       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6770       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6771       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6772       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6773       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6774     }
6775   }
6776
6777 }
6778 /*-----------------------------------------------------------------*/
6779 /* shiftR2Left2Result - shift right two bytes from left to result  */
6780 /*-----------------------------------------------------------------*/
6781 static void shiftR2Left2Result (operand *left, int offl,
6782                                 operand *result, int offr,
6783                                 int shCount, int sign)
6784 {
6785   int same=0;
6786
6787   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6788   same = pic16_sameRegs(AOP(result), AOP(left));
6789
6790   if(same && ((offl + MSB16) == offr)){
6791     same=1;
6792     /* don't crash result[offr] */
6793     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6794     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6795   }
6796 /* else {
6797     movLeft2Result(left,offl, result, offr);
6798     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6799   }
6800 */
6801   /* a:x >> shCount (x = lsb(result))*/
6802 /*
6803   if(sign)
6804     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6805   else {
6806     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6807 */
6808   switch(shCount) {
6809   case 0:
6810     break;
6811   case 1:
6812   case 2:
6813   case 3:
6814     if(sign)
6815       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6816     else
6817       emitCLRC;
6818
6819     if(same) {
6820       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6821       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6822     } else {
6823       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6824       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6825       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6826       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6827     }
6828
6829     while(--shCount) {
6830       if(sign)
6831         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6832       else
6833         emitCLRC;
6834       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6835       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6836     }
6837     break;
6838   case 4:
6839   case 5:
6840     if(same) {
6841
6842       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
6843       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
6844       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6845
6846       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6847       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
6848       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6849       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6850     } else {
6851       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6852       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6853       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6854
6855       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6857       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6858       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6859       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6860     }
6861
6862     if(shCount >=5) {
6863       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6864       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6865     }
6866
6867     if(sign) {
6868       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
6869       pic16_emitpcode(POC_BTFSC, 
6870                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6871       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6872     }
6873
6874     break;
6875
6876   case 6:
6877     if(same) {
6878
6879       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6880       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6881
6882       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6883       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6884       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6885       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6886       if(sign) {
6887         pic16_emitpcode(POC_BTFSC, 
6888                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6889         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6890       }
6891       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6892       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
6893       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6894       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6895     } else {
6896       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6897       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6898       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6899       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6900       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6901       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6902       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
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),0,0));
6907         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6908       }
6909       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6910       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6911
6912         
6913     }
6914
6915     break;
6916   case 7:
6917     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6918     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6919     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6920     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
6921     if(sign) {
6922       emitSKPNC;
6923       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
6924     } else 
6925       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6926   }
6927 }
6928
6929
6930 /*-----------------------------------------------------------------*/
6931 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6932 /*-----------------------------------------------------------------*/
6933 static void shiftLLeftOrResult (operand *left, int offl,
6934                                 operand *result, int offr, int shCount)
6935 {
6936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6937     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6938     /* shift left accumulator */
6939     AccLsh(shCount);
6940     /* or with result */
6941     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6942     /* back to result */
6943     pic16_aopPut(AOP(result),"a",offr);
6944 }
6945
6946 /*-----------------------------------------------------------------*/
6947 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6948 /*-----------------------------------------------------------------*/
6949 static void shiftRLeftOrResult (operand *left, int offl,
6950                                 operand *result, int offr, int shCount)
6951 {
6952     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6953     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6954     /* shift right accumulator */
6955     AccRsh(shCount);
6956     /* or with result */
6957     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6958     /* back to result */
6959     pic16_aopPut(AOP(result),"a",offr);
6960 }
6961
6962 /*-----------------------------------------------------------------*/
6963 /* genlshOne - left shift a one byte quantity by known count       */
6964 /*-----------------------------------------------------------------*/
6965 static void genlshOne (operand *result, operand *left, int shCount)
6966 {       
6967     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6968     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6969 }
6970
6971 /*-----------------------------------------------------------------*/
6972 /* genlshTwo - left shift two bytes by known amount != 0           */
6973 /*-----------------------------------------------------------------*/
6974 static void genlshTwo (operand *result,operand *left, int shCount)
6975 {
6976     int size;
6977     
6978     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6979     size = pic16_getDataSize(result);
6980
6981     /* if shCount >= 8 */
6982     if (shCount >= 8) {
6983         shCount -= 8 ;
6984
6985         if (size > 1){
6986             if (shCount)
6987                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6988             else 
6989                 movLeft2Result(left, LSB, result, MSB16);
6990         }
6991         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
6992     }
6993
6994     /*  1 <= shCount <= 7 */
6995     else {  
6996         if(size == 1)
6997             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6998         else 
6999             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7000     }
7001 }
7002
7003 /*-----------------------------------------------------------------*/
7004 /* shiftLLong - shift left one long from left to result            */
7005 /* offl = LSB or MSB16                                             */
7006 /*-----------------------------------------------------------------*/
7007 static void shiftLLong (operand *left, operand *result, int offr )
7008 {
7009     char *l;
7010     int size = AOP_SIZE(result);
7011
7012     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7013     if(size >= LSB+offr){
7014         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7015         MOVA(l);
7016         pic16_emitcode("add","a,acc");
7017         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7018             size >= MSB16+offr && offr != LSB )
7019             pic16_emitcode("xch","a,%s",
7020                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7021         else        
7022             pic16_aopPut(AOP(result),"a",LSB+offr);
7023     }
7024
7025     if(size >= MSB16+offr){
7026         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7027             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7028             MOVA(l);
7029         }
7030         pic16_emitcode("rlc","a");
7031         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7032             size >= MSB24+offr && offr != LSB)
7033             pic16_emitcode("xch","a,%s",
7034                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7035         else        
7036             pic16_aopPut(AOP(result),"a",MSB16+offr);
7037     }
7038
7039     if(size >= MSB24+offr){
7040         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7041             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7042             MOVA(l);
7043         }
7044         pic16_emitcode("rlc","a");
7045         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7046             size >= MSB32+offr && offr != LSB )
7047             pic16_emitcode("xch","a,%s",
7048                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7049         else        
7050             pic16_aopPut(AOP(result),"a",MSB24+offr);
7051     }
7052
7053     if(size > MSB32+offr){
7054         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7055             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7056             MOVA(l);    
7057         }
7058         pic16_emitcode("rlc","a");
7059         pic16_aopPut(AOP(result),"a",MSB32+offr);
7060     }
7061     if(offr != LSB)
7062         pic16_aopPut(AOP(result),zero,LSB);       
7063 }
7064
7065 /*-----------------------------------------------------------------*/
7066 /* genlshFour - shift four byte by a known amount != 0             */
7067 /*-----------------------------------------------------------------*/
7068 static void genlshFour (operand *result, operand *left, int shCount)
7069 {
7070     int size;
7071
7072     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7073     size = AOP_SIZE(result);
7074
7075     /* if shifting more that 3 bytes */
7076     if (shCount >= 24 ) {
7077         shCount -= 24;
7078         if (shCount)
7079             /* lowest order of left goes to the highest
7080             order of the destination */
7081             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7082         else
7083             movLeft2Result(left, LSB, result, MSB32);
7084         pic16_aopPut(AOP(result),zero,LSB);
7085         pic16_aopPut(AOP(result),zero,MSB16);
7086         pic16_aopPut(AOP(result),zero,MSB32);
7087         return;
7088     }
7089
7090     /* more than two bytes */
7091     else if ( shCount >= 16 ) {
7092         /* lower order two bytes goes to higher order two bytes */
7093         shCount -= 16;
7094         /* if some more remaining */
7095         if (shCount)
7096             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7097         else {
7098             movLeft2Result(left, MSB16, result, MSB32);
7099             movLeft2Result(left, LSB, result, MSB24);
7100         }
7101         pic16_aopPut(AOP(result),zero,MSB16);
7102         pic16_aopPut(AOP(result),zero,LSB);
7103         return;
7104     }    
7105
7106     /* if more than 1 byte */
7107     else if ( shCount >= 8 ) {
7108         /* lower order three bytes goes to higher order  three bytes */
7109         shCount -= 8;
7110         if(size == 2){
7111             if(shCount)
7112                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7113             else
7114                 movLeft2Result(left, LSB, result, MSB16);
7115         }
7116         else{   /* size = 4 */
7117             if(shCount == 0){
7118                 movLeft2Result(left, MSB24, result, MSB32);
7119                 movLeft2Result(left, MSB16, result, MSB24);
7120                 movLeft2Result(left, LSB, result, MSB16);
7121                 pic16_aopPut(AOP(result),zero,LSB);
7122             }
7123             else if(shCount == 1)
7124                 shiftLLong(left, result, MSB16);
7125             else{
7126                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7127                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7128                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7129                 pic16_aopPut(AOP(result),zero,LSB);
7130             }
7131         }
7132     }
7133
7134     /* 1 <= shCount <= 7 */
7135     else if(shCount <= 2){
7136         shiftLLong(left, result, LSB);
7137         if(shCount == 2)
7138             shiftLLong(result, result, LSB);
7139     }
7140     /* 3 <= shCount <= 7, optimize */
7141     else{
7142         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7143         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7144         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7145     }
7146 }
7147
7148 /*-----------------------------------------------------------------*/
7149 /* genLeftShiftLiteral - left shifting by known count              */
7150 /*-----------------------------------------------------------------*/
7151 static void genLeftShiftLiteral (operand *left,
7152                                  operand *right,
7153                                  operand *result,
7154                                  iCode *ic)
7155 {    
7156     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7157     int size;
7158
7159     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7160     pic16_freeAsmop(right,NULL,ic,TRUE);
7161
7162     pic16_aopOp(left,ic,FALSE);
7163     pic16_aopOp(result,ic,FALSE);
7164
7165     size = getSize(operandType(result));
7166
7167 #if VIEW_SIZE
7168     pic16_emitcode("; shift left ","result %d, left %d",size,
7169              AOP_SIZE(left));
7170 #endif
7171
7172     /* I suppose that the left size >= result size */
7173     if(shCount == 0){
7174         while(size--){
7175             movLeft2Result(left, size, result, size);
7176         }
7177     }
7178
7179     else if(shCount >= (size * 8))
7180         while(size--)
7181             pic16_aopPut(AOP(result),zero,size);
7182     else{
7183         switch (size) {
7184             case 1:
7185                 genlshOne (result,left,shCount);
7186                 break;
7187
7188             case 2:
7189             case 3:
7190                 genlshTwo (result,left,shCount);
7191                 break;
7192
7193             case 4:
7194                 genlshFour (result,left,shCount);
7195                 break;
7196         }
7197     }
7198     pic16_freeAsmop(left,NULL,ic,TRUE);
7199     pic16_freeAsmop(result,NULL,ic,TRUE);
7200 }
7201
7202 /*-----------------------------------------------------------------*
7203  * genMultiAsm - repeat assembly instruction for size of register.
7204  * if endian == 1, then the high byte (i.e base address + size of 
7205  * register) is used first else the low byte is used first;
7206  *-----------------------------------------------------------------*/
7207 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7208 {
7209
7210   int offset = 0;
7211
7212   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7213
7214   if(!reg)
7215     return;
7216
7217   if(!endian) {
7218     endian = 1;
7219   } else {
7220     endian = -1;
7221     offset = size-1;
7222   }
7223
7224   while(size--) {
7225     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7226     offset += endian;
7227   }
7228
7229 }
7230 /*-----------------------------------------------------------------*/
7231 /* genLeftShift - generates code for left shifting                 */
7232 /*-----------------------------------------------------------------*/
7233 static void genLeftShift (iCode *ic)
7234 {
7235   operand *left,*right, *result;
7236   int size, offset;
7237   char *l;
7238   symbol *tlbl , *tlbl1;
7239   pCodeOp *pctemp;
7240
7241   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7242
7243   right = IC_RIGHT(ic);
7244   left  = IC_LEFT(ic);
7245   result = IC_RESULT(ic);
7246
7247   pic16_aopOp(right,ic,FALSE);
7248
7249   /* if the shift count is known then do it 
7250      as efficiently as possible */
7251   if (AOP_TYPE(right) == AOP_LIT) {
7252     genLeftShiftLiteral (left,right,result,ic);
7253     return ;
7254   }
7255
7256   /* shift count is unknown then we have to form 
7257      a loop get the loop count in B : Note: we take
7258      only the lower order byte since shifting
7259      more that 32 bits make no sense anyway, ( the
7260      largest size of an object can be only 32 bits ) */  
7261
7262     
7263   pic16_aopOp(left,ic,FALSE);
7264   pic16_aopOp(result,ic,FALSE);
7265
7266   /* now move the left to the result if they are not the
7267      same */
7268   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7269       AOP_SIZE(result) > 1) {
7270
7271     size = AOP_SIZE(result);
7272     offset=0;
7273     while (size--) {
7274       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7275       if (*l == '@' && (IS_AOP_PREG(result))) {
7276
7277         pic16_emitcode("mov","a,%s",l);
7278         pic16_aopPut(AOP(result),"a",offset);
7279       } else {
7280         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7281         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7282         //pic16_aopPut(AOP(result),l,offset);
7283       }
7284       offset++;
7285     }
7286   }
7287
7288   size = AOP_SIZE(result);
7289
7290   /* if it is only one byte then */
7291   if (size == 1) {
7292     if(optimized_for_speed) {
7293       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7294       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7295       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7296       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7297       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7298       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7299       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7300       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7301       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7302       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7303       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7304       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7305     } else {
7306
7307       tlbl = newiTempLabel(NULL);
7308       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7309         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7310         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7311       }
7312
7313       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7314       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7315       pic16_emitpLabel(tlbl->key);
7316       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7317       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7318       emitSKPC;
7319       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7320     }
7321     goto release ;
7322   }
7323     
7324   if (pic16_sameRegs(AOP(left),AOP(result))) {
7325
7326     tlbl = newiTempLabel(NULL);
7327     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7328     genMultiAsm(POC_RRCF, result, size,1);
7329     pic16_emitpLabel(tlbl->key);
7330     genMultiAsm(POC_RLCF, result, size,0);
7331     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7332     emitSKPC;
7333     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7334     goto release;
7335   }
7336
7337   //tlbl = newiTempLabel(NULL);
7338   //offset = 0 ;   
7339   //tlbl1 = newiTempLabel(NULL);
7340
7341   //reAdjustPreg(AOP(result));    
7342     
7343   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7344   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7345   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7346   //MOVA(l);
7347   //pic16_emitcode("add","a,acc");         
7348   //pic16_aopPut(AOP(result),"a",offset++);
7349   //while (--size) {
7350   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7351   //  MOVA(l);
7352   //  pic16_emitcode("rlc","a");         
7353   //  pic16_aopPut(AOP(result),"a",offset++);
7354   //}
7355   //reAdjustPreg(AOP(result));
7356
7357   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7358   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7359
7360
7361   tlbl = newiTempLabel(NULL);
7362   tlbl1= newiTempLabel(NULL);
7363
7364   size = AOP_SIZE(result);
7365   offset = 1;
7366
7367   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7368
7369   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7370
7371   /* offset should be 0, 1 or 3 */
7372   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7373   emitSKPNZ;
7374   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7375
7376   pic16_emitpcode(POC_MOVWF, pctemp);
7377
7378
7379   pic16_emitpLabel(tlbl->key);
7380
7381   emitCLRC;
7382   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7383   while(--size)
7384     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7385
7386   pic16_emitpcode(POC_DECFSZ,  pctemp);
7387   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7388   pic16_emitpLabel(tlbl1->key);
7389
7390   pic16_popReleaseTempReg(pctemp);
7391
7392
7393  release:
7394   pic16_freeAsmop (right,NULL,ic,TRUE);
7395   pic16_freeAsmop(left,NULL,ic,TRUE);
7396   pic16_freeAsmop(result,NULL,ic,TRUE);
7397 }
7398
7399 /*-----------------------------------------------------------------*/
7400 /* genrshOne - right shift a one byte quantity by known count      */
7401 /*-----------------------------------------------------------------*/
7402 static void genrshOne (operand *result, operand *left,
7403                        int shCount, int sign)
7404 {
7405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7406     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7407 }
7408
7409 /*-----------------------------------------------------------------*/
7410 /* genrshTwo - right shift two bytes by known amount != 0          */
7411 /*-----------------------------------------------------------------*/
7412 static void genrshTwo (operand *result,operand *left,
7413                        int shCount, int sign)
7414 {
7415   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7416   /* if shCount >= 8 */
7417   if (shCount >= 8) {
7418     shCount -= 8 ;
7419     if (shCount)
7420       shiftR1Left2Result(left, MSB16, result, LSB,
7421                          shCount, sign);
7422     else
7423       movLeft2Result(left, MSB16, result, LSB);
7424
7425     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7426
7427     if(sign) {
7428       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7429       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7430     }
7431   }
7432
7433   /*  1 <= shCount <= 7 */
7434   else
7435     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7436 }
7437
7438 /*-----------------------------------------------------------------*/
7439 /* shiftRLong - shift right one long from left to result           */
7440 /* offl = LSB or MSB16                                             */
7441 /*-----------------------------------------------------------------*/
7442 static void shiftRLong (operand *left, int offl,
7443                         operand *result, int sign)
7444 {
7445     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7446     if(!sign)
7447         pic16_emitcode("clr","c");
7448     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7449     if(sign)
7450         pic16_emitcode("mov","c,acc.7");
7451     pic16_emitcode("rrc","a");
7452     pic16_aopPut(AOP(result),"a",MSB32-offl);
7453     if(offl == MSB16)
7454         /* add sign of "a" */
7455         pic16_addSign(result, MSB32, sign);
7456
7457     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7458     pic16_emitcode("rrc","a");
7459     pic16_aopPut(AOP(result),"a",MSB24-offl);
7460
7461     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7462     pic16_emitcode("rrc","a");
7463     pic16_aopPut(AOP(result),"a",MSB16-offl);
7464
7465     if(offl == LSB){
7466         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7467         pic16_emitcode("rrc","a");
7468         pic16_aopPut(AOP(result),"a",LSB);
7469     }
7470 }
7471
7472 /*-----------------------------------------------------------------*/
7473 /* genrshFour - shift four byte by a known amount != 0             */
7474 /*-----------------------------------------------------------------*/
7475 static void genrshFour (operand *result, operand *left,
7476                         int shCount, int sign)
7477 {
7478   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7479   /* if shifting more that 3 bytes */
7480   if(shCount >= 24 ) {
7481     shCount -= 24;
7482     if(shCount)
7483       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7484     else
7485       movLeft2Result(left, MSB32, result, LSB);
7486
7487     pic16_addSign(result, MSB16, sign);
7488   }
7489   else if(shCount >= 16){
7490     shCount -= 16;
7491     if(shCount)
7492       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7493     else{
7494       movLeft2Result(left, MSB24, result, LSB);
7495       movLeft2Result(left, MSB32, result, MSB16);
7496     }
7497     pic16_addSign(result, MSB24, sign);
7498   }
7499   else if(shCount >= 8){
7500     shCount -= 8;
7501     if(shCount == 1)
7502       shiftRLong(left, MSB16, result, sign);
7503     else if(shCount == 0){
7504       movLeft2Result(left, MSB16, result, LSB);
7505       movLeft2Result(left, MSB24, result, MSB16);
7506       movLeft2Result(left, MSB32, result, MSB24);
7507       pic16_addSign(result, MSB32, sign);
7508     }
7509     else{
7510       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7511       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7512       /* the last shift is signed */
7513       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7514       pic16_addSign(result, MSB32, sign);
7515     }
7516   }
7517   else{   /* 1 <= shCount <= 7 */
7518     if(shCount <= 2){
7519       shiftRLong(left, LSB, result, sign);
7520       if(shCount == 2)
7521         shiftRLong(result, LSB, result, sign);
7522     }
7523     else{
7524       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7525       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7526       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7527     }
7528   }
7529 }
7530
7531 /*-----------------------------------------------------------------*/
7532 /* genRightShiftLiteral - right shifting by known count            */
7533 /*-----------------------------------------------------------------*/
7534 static void genRightShiftLiteral (operand *left,
7535                                   operand *right,
7536                                   operand *result,
7537                                   iCode *ic,
7538                                   int sign)
7539 {    
7540   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7541   int lsize,res_size;
7542
7543   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7544   pic16_freeAsmop(right,NULL,ic,TRUE);
7545
7546   pic16_aopOp(left,ic,FALSE);
7547   pic16_aopOp(result,ic,FALSE);
7548
7549 #if VIEW_SIZE
7550   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7551                  AOP_SIZE(left));
7552 #endif
7553
7554   lsize = pic16_getDataSize(left);
7555   res_size = pic16_getDataSize(result);
7556   /* test the LEFT size !!! */
7557
7558   /* I suppose that the left size >= result size */
7559   if(shCount == 0){
7560     while(res_size--)
7561       movLeft2Result(left, lsize, result, res_size);
7562   }
7563
7564   else if(shCount >= (lsize * 8)){
7565
7566     if(res_size == 1) {
7567       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7568       if(sign) {
7569         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7570         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7571       }
7572     } else {
7573
7574       if(sign) {
7575         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7576         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7577         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7578         while(res_size--)
7579           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7580
7581       } else {
7582
7583         while(res_size--)
7584           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7585       }
7586     }
7587   } else {
7588
7589     switch (res_size) {
7590     case 1:
7591       genrshOne (result,left,shCount,sign);
7592       break;
7593
7594     case 2:
7595       genrshTwo (result,left,shCount,sign);
7596       break;
7597
7598     case 4:
7599       genrshFour (result,left,shCount,sign);
7600       break;
7601     default :
7602       break;
7603     }
7604
7605   }
7606
7607   pic16_freeAsmop(left,NULL,ic,TRUE);
7608   pic16_freeAsmop(result,NULL,ic,TRUE);
7609 }
7610
7611 /*-----------------------------------------------------------------*/
7612 /* genSignedRightShift - right shift of signed number              */
7613 /*-----------------------------------------------------------------*/
7614 static void genSignedRightShift (iCode *ic)
7615 {
7616   operand *right, *left, *result;
7617   int size, offset;
7618   //  char *l;
7619   symbol *tlbl, *tlbl1 ;
7620   pCodeOp *pctemp;
7621
7622   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7623
7624   /* we do it the hard way put the shift count in b
7625      and loop thru preserving the sign */
7626   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7627
7628   right = IC_RIGHT(ic);
7629   left  = IC_LEFT(ic);
7630   result = IC_RESULT(ic);
7631
7632   pic16_aopOp(right,ic,FALSE);  
7633   pic16_aopOp(left,ic,FALSE);
7634   pic16_aopOp(result,ic,FALSE);
7635
7636
7637   if ( AOP_TYPE(right) == AOP_LIT) {
7638     genRightShiftLiteral (left,right,result,ic,1);
7639     return ;
7640   }
7641   /* shift count is unknown then we have to form 
7642      a loop get the loop count in B : Note: we take
7643      only the lower order byte since shifting
7644      more that 32 bits make no sense anyway, ( the
7645      largest size of an object can be only 32 bits ) */  
7646
7647   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7648   //pic16_emitcode("inc","b");
7649   //pic16_freeAsmop (right,NULL,ic,TRUE);
7650   //pic16_aopOp(left,ic,FALSE);
7651   //pic16_aopOp(result,ic,FALSE);
7652
7653   /* now move the left to the result if they are not the
7654      same */
7655   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7656       AOP_SIZE(result) > 1) {
7657
7658     size = AOP_SIZE(result);
7659     offset=0;
7660     while (size--) { 
7661       /*
7662         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7663         if (*l == '@' && IS_AOP_PREG(result)) {
7664
7665         pic16_emitcode("mov","a,%s",l);
7666         pic16_aopPut(AOP(result),"a",offset);
7667         } else
7668         pic16_aopPut(AOP(result),l,offset);
7669       */
7670       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7671       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7672
7673       offset++;
7674     }
7675   }
7676
7677   /* mov the highest order bit to OVR */    
7678   tlbl = newiTempLabel(NULL);
7679   tlbl1= newiTempLabel(NULL);
7680
7681   size = AOP_SIZE(result);
7682   offset = size - 1;
7683
7684   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7685
7686   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7687
7688   /* offset should be 0, 1 or 3 */
7689   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7690   emitSKPNZ;
7691   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7692
7693   pic16_emitpcode(POC_MOVWF, pctemp);
7694
7695
7696   pic16_emitpLabel(tlbl->key);
7697
7698   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7699   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7700
7701   while(--size) {
7702     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7703   }
7704
7705   pic16_emitpcode(POC_DECFSZ,  pctemp);
7706   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7707   pic16_emitpLabel(tlbl1->key);
7708
7709   pic16_popReleaseTempReg(pctemp);
7710 #if 0
7711   size = AOP_SIZE(result);
7712   offset = size - 1;
7713   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7714   pic16_emitcode("rlc","a");
7715   pic16_emitcode("mov","ov,c");
7716   /* if it is only one byte then */
7717   if (size == 1) {
7718     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7719     MOVA(l);
7720     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7721     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7722     pic16_emitcode("mov","c,ov");
7723     pic16_emitcode("rrc","a");
7724     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7725     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7726     pic16_aopPut(AOP(result),"a",0);
7727     goto release ;
7728   }
7729
7730   reAdjustPreg(AOP(result));
7731   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7732   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7733   pic16_emitcode("mov","c,ov");
7734   while (size--) {
7735     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7736     MOVA(l);
7737     pic16_emitcode("rrc","a");         
7738     pic16_aopPut(AOP(result),"a",offset--);
7739   }
7740   reAdjustPreg(AOP(result));
7741   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7742   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7743
7744  release:
7745 #endif
7746
7747   pic16_freeAsmop(left,NULL,ic,TRUE);
7748   pic16_freeAsmop(result,NULL,ic,TRUE);
7749   pic16_freeAsmop(right,NULL,ic,TRUE);
7750 }
7751
7752 /*-----------------------------------------------------------------*/
7753 /* genRightShift - generate code for right shifting                */
7754 /*-----------------------------------------------------------------*/
7755 static void genRightShift (iCode *ic)
7756 {
7757     operand *right, *left, *result;
7758     sym_link *retype ;
7759     int size, offset;
7760     char *l;
7761     symbol *tlbl, *tlbl1 ;
7762
7763     /* if signed then we do it the hard way preserve the
7764     sign bit moving it inwards */
7765     retype = getSpec(operandType(IC_RESULT(ic)));
7766     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7767
7768     if (!SPEC_USIGN(retype)) {
7769         genSignedRightShift (ic);
7770         return ;
7771     }
7772
7773     /* signed & unsigned types are treated the same : i.e. the
7774     signed is NOT propagated inwards : quoting from the
7775     ANSI - standard : "for E1 >> E2, is equivalent to division
7776     by 2**E2 if unsigned or if it has a non-negative value,
7777     otherwise the result is implementation defined ", MY definition
7778     is that the sign does not get propagated */
7779
7780     right = IC_RIGHT(ic);
7781     left  = IC_LEFT(ic);
7782     result = IC_RESULT(ic);
7783
7784     pic16_aopOp(right,ic,FALSE);
7785
7786     /* if the shift count is known then do it 
7787     as efficiently as possible */
7788     if (AOP_TYPE(right) == AOP_LIT) {
7789         genRightShiftLiteral (left,right,result,ic, 0);
7790         return ;
7791     }
7792
7793     /* shift count is unknown then we have to form 
7794     a loop get the loop count in B : Note: we take
7795     only the lower order byte since shifting
7796     more that 32 bits make no sense anyway, ( the
7797     largest size of an object can be only 32 bits ) */  
7798
7799     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7800     pic16_emitcode("inc","b");
7801     pic16_aopOp(left,ic,FALSE);
7802     pic16_aopOp(result,ic,FALSE);
7803
7804     /* now move the left to the result if they are not the
7805     same */
7806     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7807         AOP_SIZE(result) > 1) {
7808
7809         size = AOP_SIZE(result);
7810         offset=0;
7811         while (size--) {
7812             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7813             if (*l == '@' && IS_AOP_PREG(result)) {
7814
7815                 pic16_emitcode("mov","a,%s",l);
7816                 pic16_aopPut(AOP(result),"a",offset);
7817             } else
7818                 pic16_aopPut(AOP(result),l,offset);
7819             offset++;
7820         }
7821     }
7822
7823     tlbl = newiTempLabel(NULL);
7824     tlbl1= newiTempLabel(NULL);
7825     size = AOP_SIZE(result);
7826     offset = size - 1;
7827
7828     /* if it is only one byte then */
7829     if (size == 1) {
7830
7831       tlbl = newiTempLabel(NULL);
7832       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7833         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7834         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7835       }
7836
7837       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7838       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7839       pic16_emitpLabel(tlbl->key);
7840       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7841       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7842       emitSKPC;
7843       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7844
7845       goto release ;
7846     }
7847
7848     reAdjustPreg(AOP(result));
7849     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7850     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7851     CLRC;
7852     while (size--) {
7853         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7854         MOVA(l);
7855         pic16_emitcode("rrc","a");         
7856         pic16_aopPut(AOP(result),"a",offset--);
7857     }
7858     reAdjustPreg(AOP(result));
7859
7860     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7861     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7862
7863 release:
7864     pic16_freeAsmop(left,NULL,ic,TRUE);
7865     pic16_freeAsmop (right,NULL,ic,TRUE);
7866     pic16_freeAsmop(result,NULL,ic,TRUE);
7867 }
7868
7869 /*-----------------------------------------------------------------*/
7870 /* genUnpackBits - generates code for unpacking bits               */
7871 /*-----------------------------------------------------------------*/
7872 static void genUnpackBits (operand *result, char *rname, int ptype)
7873 {    
7874     int shCnt ;
7875     int rlen = 0 ;
7876     sym_link *etype;
7877     int offset = 0 ;
7878
7879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7880     etype = getSpec(operandType(result));
7881
7882     /* read the first byte  */
7883     switch (ptype) {
7884
7885     case POINTER:
7886     case IPOINTER:
7887         pic16_emitcode("mov","a,@%s",rname);
7888         break;
7889         
7890     case PPOINTER:
7891         pic16_emitcode("movx","a,@%s",rname);
7892         break;
7893         
7894     case FPOINTER:
7895         pic16_emitcode("movx","a,@dptr");
7896         break;
7897
7898     case CPOINTER:
7899         pic16_emitcode("clr","a");
7900         pic16_emitcode("movc","a","@a+dptr");
7901         break;
7902
7903     case GPOINTER:
7904         pic16_emitcode("lcall","__gptrget");
7905         break;
7906     }
7907
7908     /* if we have bitdisplacement then it fits   */
7909     /* into this byte completely or if length is */
7910     /* less than a byte                          */
7911     if ((shCnt = SPEC_BSTR(etype)) || 
7912         (SPEC_BLEN(etype) <= 8))  {
7913
7914         /* shift right acc */
7915         AccRsh(shCnt);
7916
7917         pic16_emitcode("anl","a,#0x%02x",
7918                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7919         pic16_aopPut(AOP(result),"a",offset);
7920         return ;
7921     }
7922
7923     /* bit field did not fit in a byte  */
7924     rlen = SPEC_BLEN(etype) - 8;
7925     pic16_aopPut(AOP(result),"a",offset++);
7926
7927     while (1)  {
7928
7929         switch (ptype) {
7930         case POINTER:
7931         case IPOINTER:
7932             pic16_emitcode("inc","%s",rname);
7933             pic16_emitcode("mov","a,@%s",rname);
7934             break;
7935             
7936         case PPOINTER:
7937             pic16_emitcode("inc","%s",rname);
7938             pic16_emitcode("movx","a,@%s",rname);
7939             break;
7940
7941         case FPOINTER:
7942             pic16_emitcode("inc","dptr");
7943             pic16_emitcode("movx","a,@dptr");
7944             break;
7945             
7946         case CPOINTER:
7947             pic16_emitcode("clr","a");
7948             pic16_emitcode("inc","dptr");
7949             pic16_emitcode("movc","a","@a+dptr");
7950             break;
7951             
7952         case GPOINTER:
7953             pic16_emitcode("inc","dptr");
7954             pic16_emitcode("lcall","__gptrget");
7955             break;
7956         }
7957
7958         rlen -= 8;            
7959         /* if we are done */
7960         if ( rlen <= 0 )
7961             break ;
7962         
7963         pic16_aopPut(AOP(result),"a",offset++);
7964                               
7965     }
7966     
7967     if (rlen) {
7968         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7969         pic16_aopPut(AOP(result),"a",offset);          
7970     }
7971     
7972     return ;
7973 }
7974
7975 #if 0
7976 /*-----------------------------------------------------------------*/
7977 /* genDataPointerGet - generates code when ptr offset is known     */
7978 /*-----------------------------------------------------------------*/
7979 static void genDataPointerGet (operand *left, 
7980                                operand *result, 
7981                                iCode *ic)
7982 {
7983   int size , offset = 0;
7984
7985
7986   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7987
7988
7989   /* optimization - most of the time, left and result are the same
7990    * address, but different types. for the pic code, we could omit
7991    * the following
7992    */
7993
7994   pic16_aopOp(result,ic,TRUE);
7995
7996   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7997
7998   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7999
8000   size = AOP_SIZE(result);
8001
8002   while (size--) {
8003     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8004     offset++;
8005   }
8006
8007   pic16_freeAsmop(left,NULL,ic,TRUE);
8008   pic16_freeAsmop(result,NULL,ic,TRUE);
8009 }
8010 #endif
8011 /*-----------------------------------------------------------------*/
8012 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8013 /*-----------------------------------------------------------------*/
8014 static void genNearPointerGet (operand *left, 
8015                                operand *result, 
8016                                iCode *ic)
8017 {
8018     asmop *aop = NULL;
8019     //regs *preg = NULL ;
8020     char *rname ;
8021     sym_link *rtype, *retype;
8022     sym_link *ltype = operandType(left);    
8023     //char buffer[80];
8024
8025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8026
8027     rtype = operandType(result);
8028     retype= getSpec(rtype);
8029     
8030     pic16_aopOp(left,ic,FALSE);
8031     
8032     /* if left is rematerialisable and
8033        result is not bit variable type and
8034        the left is pointer to data space i.e
8035        lower 128 bytes of space */
8036     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8037         !IS_BITVAR(retype)         &&
8038         DCL_TYPE(ltype) == POINTER) {
8039       //genDataPointerGet (left,result,ic);
8040         return ;
8041     }
8042     
8043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8044
8045         /* if the value is already in a pointer register
8046        then don't need anything more */
8047     if (!AOP_INPREG(AOP(left))) {
8048         /* otherwise get a free pointer register */
8049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8050 /*
8051         aop = newAsmop(0);
8052         preg = getFreePtr(ic,&aop,FALSE);
8053         pic16_emitcode("mov","%s,%s",
8054                 preg->name,
8055                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8056         rname = preg->name ;
8057 */
8058     rname ="BAD";
8059     } else
8060         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8061     
8062     pic16_aopOp (result,ic,FALSE);
8063     
8064       /* if bitfield then unpack the bits */
8065     if (IS_BITVAR(retype)) 
8066         genUnpackBits (result,rname,POINTER);
8067     else {
8068         /* we have can just get the values */
8069       int size = AOP_SIZE(result);
8070       int offset = 0 ;  
8071         
8072       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8073
8074       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8075       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8076       while(size--) {
8077         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8078         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8079         if(size)
8080           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8081       }
8082 /*
8083         while (size--) {
8084             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8085
8086                 pic16_emitcode("mov","a,@%s",rname);
8087                 pic16_aopPut(AOP(result),"a",offset);
8088             } else {
8089                 sprintf(buffer,"@%s",rname);
8090                 pic16_aopPut(AOP(result),buffer,offset);
8091             }
8092             offset++ ;
8093             if (size)
8094                 pic16_emitcode("inc","%s",rname);
8095         }
8096 */
8097     }
8098
8099     /* now some housekeeping stuff */
8100     if (aop) {
8101         /* we had to allocate for this iCode */
8102     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8103         pic16_freeAsmop(NULL,aop,ic,TRUE);
8104     } else { 
8105         /* we did not allocate which means left
8106            already in a pointer register, then
8107            if size > 0 && this could be used again
8108            we have to point it back to where it 
8109            belongs */
8110     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8111         if (AOP_SIZE(result) > 1 &&
8112             !OP_SYMBOL(left)->remat &&
8113             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8114               ic->depth )) {
8115             int size = AOP_SIZE(result) - 1;
8116             while (size--)
8117                 pic16_emitcode("dec","%s",rname);
8118         }
8119     }
8120
8121     /* done */
8122     pic16_freeAsmop(left,NULL,ic,TRUE);
8123     pic16_freeAsmop(result,NULL,ic,TRUE);
8124      
8125 }
8126
8127 /*-----------------------------------------------------------------*/
8128 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8129 /*-----------------------------------------------------------------*/
8130 static void genPagedPointerGet (operand *left, 
8131                                operand *result, 
8132                                iCode *ic)
8133 {
8134     asmop *aop = NULL;
8135     regs *preg = NULL ;
8136     char *rname ;
8137     sym_link *rtype, *retype;    
8138
8139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8140
8141     rtype = operandType(result);
8142     retype= getSpec(rtype);
8143     
8144     pic16_aopOp(left,ic,FALSE);
8145
8146   /* if the value is already in a pointer register
8147        then don't need anything more */
8148     if (!AOP_INPREG(AOP(left))) {
8149         /* otherwise get a free pointer register */
8150         aop = newAsmop(0);
8151         preg = getFreePtr(ic,&aop,FALSE);
8152         pic16_emitcode("mov","%s,%s",
8153                 preg->name,
8154                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8155         rname = preg->name ;
8156     } else
8157         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8158     
8159     pic16_freeAsmop(left,NULL,ic,TRUE);
8160     pic16_aopOp (result,ic,FALSE);
8161
8162     /* if bitfield then unpack the bits */
8163     if (IS_BITVAR(retype)) 
8164         genUnpackBits (result,rname,PPOINTER);
8165     else {
8166         /* we have can just get the values */
8167         int size = AOP_SIZE(result);
8168         int offset = 0 ;        
8169         
8170         while (size--) {
8171             
8172             pic16_emitcode("movx","a,@%s",rname);
8173             pic16_aopPut(AOP(result),"a",offset);
8174             
8175             offset++ ;
8176             
8177             if (size)
8178                 pic16_emitcode("inc","%s",rname);
8179         }
8180     }
8181
8182     /* now some housekeeping stuff */
8183     if (aop) {
8184         /* we had to allocate for this iCode */
8185         pic16_freeAsmop(NULL,aop,ic,TRUE);
8186     } else { 
8187         /* we did not allocate which means left
8188            already in a pointer register, then
8189            if size > 0 && this could be used again
8190            we have to point it back to where it 
8191            belongs */
8192         if (AOP_SIZE(result) > 1 &&
8193             !OP_SYMBOL(left)->remat &&
8194             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8195               ic->depth )) {
8196             int size = AOP_SIZE(result) - 1;
8197             while (size--)
8198                 pic16_emitcode("dec","%s",rname);
8199         }
8200     }
8201
8202     /* done */
8203     pic16_freeAsmop(result,NULL,ic,TRUE);
8204     
8205         
8206 }
8207
8208 /*-----------------------------------------------------------------*/
8209 /* genFarPointerGet - gget value from far space                    */
8210 /*-----------------------------------------------------------------*/
8211 static void genFarPointerGet (operand *left,
8212                               operand *result, iCode *ic)
8213 {
8214     int size, offset ;
8215     sym_link *retype = getSpec(operandType(result));
8216
8217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8218
8219     pic16_aopOp(left,ic,FALSE);
8220
8221     /* if the operand is already in dptr 
8222     then we do nothing else we move the value to dptr */
8223     if (AOP_TYPE(left) != AOP_STR) {
8224         /* if this is remateriazable */
8225         if (AOP_TYPE(left) == AOP_IMMD)
8226             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8227         else { /* we need to get it byte by byte */
8228             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8229             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8230             if (options.model == MODEL_FLAT24)
8231             {
8232                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8233             }
8234         }
8235     }
8236     /* so dptr know contains the address */
8237     pic16_freeAsmop(left,NULL,ic,TRUE);
8238     pic16_aopOp(result,ic,FALSE);
8239
8240     /* if bit then unpack */
8241     if (IS_BITVAR(retype)) 
8242         genUnpackBits(result,"dptr",FPOINTER);
8243     else {
8244         size = AOP_SIZE(result);
8245         offset = 0 ;
8246
8247         while (size--) {
8248             pic16_emitcode("movx","a,@dptr");
8249             pic16_aopPut(AOP(result),"a",offset++);
8250             if (size)
8251                 pic16_emitcode("inc","dptr");
8252         }
8253     }
8254
8255     pic16_freeAsmop(result,NULL,ic,TRUE);
8256 }
8257 #if 0
8258 /*-----------------------------------------------------------------*/
8259 /* genCodePointerGet - get value from code space                  */
8260 /*-----------------------------------------------------------------*/
8261 static void genCodePointerGet (operand *left,
8262                                 operand *result, iCode *ic)
8263 {
8264     int size, offset ;
8265     sym_link *retype = getSpec(operandType(result));
8266
8267     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8268
8269     pic16_aopOp(left,ic,FALSE);
8270
8271     /* if the operand is already in dptr 
8272     then we do nothing else we move the value to dptr */
8273     if (AOP_TYPE(left) != AOP_STR) {
8274         /* if this is remateriazable */
8275         if (AOP_TYPE(left) == AOP_IMMD)
8276             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8277         else { /* we need to get it byte by byte */
8278             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8279             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8280             if (options.model == MODEL_FLAT24)
8281             {
8282                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8283             }
8284         }
8285     }
8286     /* so dptr know contains the address */
8287     pic16_freeAsmop(left,NULL,ic,TRUE);
8288     pic16_aopOp(result,ic,FALSE);
8289
8290     /* if bit then unpack */
8291     if (IS_BITVAR(retype)) 
8292         genUnpackBits(result,"dptr",CPOINTER);
8293     else {
8294         size = AOP_SIZE(result);
8295         offset = 0 ;
8296
8297         while (size--) {
8298             pic16_emitcode("clr","a");
8299             pic16_emitcode("movc","a,@a+dptr");
8300             pic16_aopPut(AOP(result),"a",offset++);
8301             if (size)
8302                 pic16_emitcode("inc","dptr");
8303         }
8304     }
8305
8306     pic16_freeAsmop(result,NULL,ic,TRUE);
8307 }
8308 #endif
8309 /*-----------------------------------------------------------------*/
8310 /* genGenPointerGet - gget value from generic pointer space        */
8311 /*-----------------------------------------------------------------*/
8312 static void genGenPointerGet (operand *left,
8313                               operand *result, iCode *ic)
8314 {
8315   int size, offset ;
8316   sym_link *retype = getSpec(operandType(result));
8317
8318   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8319   pic16_aopOp(left,ic,FALSE);
8320   pic16_aopOp(result,ic,FALSE);
8321
8322
8323   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8324
8325   /* if the operand is already in dptr 
8326      then we do nothing else we move the value to dptr */
8327   //  if (AOP_TYPE(left) != AOP_STR) {
8328     /* if this is remateriazable */
8329     if (AOP_TYPE(left) == AOP_IMMD) {
8330       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8331       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8332     }
8333     else { /* we need to get it byte by byte */
8334
8335       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8336       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8337
8338       size = AOP_SIZE(result);
8339       offset = 0 ;
8340
8341       while(size--) {
8342         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8343         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8344         if(size)
8345           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8346       }
8347       goto release;
8348     }
8349     //}
8350   /* so dptr know contains the address */
8351
8352   /* if bit then unpack */
8353   //if (IS_BITVAR(retype)) 
8354   //  genUnpackBits(result,"dptr",GPOINTER);
8355
8356  release:
8357   pic16_freeAsmop(left,NULL,ic,TRUE);
8358   pic16_freeAsmop(result,NULL,ic,TRUE);
8359
8360 }
8361
8362 /*-----------------------------------------------------------------*/
8363 /* genConstPointerGet - get value from const generic pointer space */
8364 /*-----------------------------------------------------------------*/
8365 static void genConstPointerGet (operand *left,
8366                                 operand *result, iCode *ic)
8367 {
8368   //sym_link *retype = getSpec(operandType(result));
8369   symbol *albl = newiTempLabel(NULL);
8370   symbol *blbl = newiTempLabel(NULL);
8371   PIC_OPCODE poc;
8372
8373   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8374   pic16_aopOp(left,ic,FALSE);
8375   pic16_aopOp(result,ic,FALSE);
8376
8377
8378   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8379
8380   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8381
8382   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8383   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8384   pic16_emitpLabel(albl->key);
8385
8386   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8387     
8388   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8389   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8390   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8391   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8392
8393   pic16_emitpLabel(blbl->key);
8394
8395   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8396
8397
8398   pic16_freeAsmop(left,NULL,ic,TRUE);
8399   pic16_freeAsmop(result,NULL,ic,TRUE);
8400
8401 }
8402 /*-----------------------------------------------------------------*/
8403 /* genPointerGet - generate code for pointer get                   */
8404 /*-----------------------------------------------------------------*/
8405 static void genPointerGet (iCode *ic)
8406 {
8407     operand *left, *result ;
8408     sym_link *type, *etype;
8409     int p_type;
8410
8411     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8412
8413     left = IC_LEFT(ic);
8414     result = IC_RESULT(ic) ;
8415
8416     /* depending on the type of pointer we need to
8417     move it to the correct pointer register */
8418     type = operandType(left);
8419     etype = getSpec(type);
8420
8421 #if 0
8422     if (IS_PTR_CONST(type))
8423 #else
8424     if (IS_CODEPTR(type))
8425 #endif
8426       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8427
8428     /* if left is of type of pointer then it is simple */
8429     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8430         p_type = DCL_TYPE(type);
8431     else {
8432         /* we have to go by the storage class */
8433         p_type = PTR_TYPE(SPEC_OCLS(etype));
8434
8435         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8436
8437         if (SPEC_OCLS(etype)->codesp ) {
8438           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8439           //p_type = CPOINTER ; 
8440         }
8441         else
8442             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8443               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8444                /*p_type = FPOINTER ;*/ 
8445             else
8446                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8447                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8448 /*                  p_type = PPOINTER; */
8449                 else
8450                     if (SPEC_OCLS(etype) == idata )
8451                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8452 /*                      p_type = IPOINTER; */
8453                     else
8454                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8455 /*                      p_type = POINTER ; */
8456     }
8457
8458     /* now that we have the pointer type we assign
8459     the pointer values */
8460     switch (p_type) {
8461
8462     case POINTER:       
8463     case IPOINTER:
8464         genNearPointerGet (left,result,ic);
8465         break;
8466
8467     case PPOINTER:
8468         genPagedPointerGet(left,result,ic);
8469         break;
8470
8471     case FPOINTER:
8472         genFarPointerGet (left,result,ic);
8473         break;
8474
8475     case CPOINTER:
8476         genConstPointerGet (left,result,ic);
8477         //pic16_emitcodePointerGet (left,result,ic);
8478         break;
8479
8480     case GPOINTER:
8481 #if 0
8482       if (IS_PTR_CONST(type))
8483         genConstPointerGet (left,result,ic);
8484       else
8485 #endif
8486         genGenPointerGet (left,result,ic);
8487       break;
8488     }
8489
8490 }
8491
8492 /*-----------------------------------------------------------------*/
8493 /* genPackBits - generates code for packed bit storage             */
8494 /*-----------------------------------------------------------------*/
8495 static void genPackBits (sym_link    *etype ,
8496                          operand *right ,
8497                          char *rname, int p_type)
8498 {
8499     int shCount = 0 ;
8500     int offset = 0  ;
8501     int rLen = 0 ;
8502     int blen, bstr ;   
8503     char *l ;
8504
8505     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8506     blen = SPEC_BLEN(etype);
8507     bstr = SPEC_BSTR(etype);
8508
8509     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8510     MOVA(l);   
8511
8512     /* if the bit lenth is less than or    */
8513     /* it exactly fits a byte then         */
8514     if (SPEC_BLEN(etype) <= 8 )  {
8515         shCount = SPEC_BSTR(etype) ;
8516
8517         /* shift left acc */
8518         AccLsh(shCount);
8519
8520         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8521
8522
8523             switch (p_type) {
8524                 case POINTER:
8525                     pic16_emitcode ("mov","b,a");
8526                     pic16_emitcode("mov","a,@%s",rname);
8527                     break;
8528
8529                 case FPOINTER:
8530                     pic16_emitcode ("mov","b,a");
8531                     pic16_emitcode("movx","a,@dptr");
8532                     break;
8533
8534                 case GPOINTER:
8535                     pic16_emitcode ("push","b");
8536                     pic16_emitcode ("push","acc");
8537                     pic16_emitcode ("lcall","__gptrget");
8538                     pic16_emitcode ("pop","b");
8539                     break;
8540             }
8541
8542             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8543                       ((unsigned char)(0xFF << (blen+bstr)) | 
8544                        (unsigned char)(0xFF >> (8-bstr)) ) );
8545             pic16_emitcode ("orl","a,b");
8546             if (p_type == GPOINTER)
8547                 pic16_emitcode("pop","b");
8548         }
8549     }
8550
8551     switch (p_type) {
8552         case POINTER:
8553             pic16_emitcode("mov","@%s,a",rname);
8554             break;
8555
8556         case FPOINTER:
8557             pic16_emitcode("movx","@dptr,a");
8558             break;
8559
8560         case GPOINTER:
8561             DEBUGpic16_emitcode(";lcall","__gptrput");
8562             break;
8563     }
8564
8565     /* if we r done */
8566     if ( SPEC_BLEN(etype) <= 8 )
8567         return ;
8568
8569     pic16_emitcode("inc","%s",rname);
8570     rLen = SPEC_BLEN(etype) ;     
8571
8572     /* now generate for lengths greater than one byte */
8573     while (1) {
8574
8575         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8576
8577         rLen -= 8 ;
8578         if (rLen <= 0 )
8579             break ;
8580
8581         switch (p_type) {
8582             case POINTER:
8583                 if (*l == '@') {
8584                     MOVA(l);
8585                     pic16_emitcode("mov","@%s,a",rname);
8586                 } else
8587                     pic16_emitcode("mov","@%s,%s",rname,l);
8588                 break;
8589
8590             case FPOINTER:
8591                 MOVA(l);
8592                 pic16_emitcode("movx","@dptr,a");
8593                 break;
8594
8595             case GPOINTER:
8596                 MOVA(l);
8597                 DEBUGpic16_emitcode(";lcall","__gptrput");
8598                 break;  
8599         }   
8600         pic16_emitcode ("inc","%s",rname);
8601     }
8602
8603     MOVA(l);
8604
8605     /* last last was not complete */
8606     if (rLen)   {
8607         /* save the byte & read byte */
8608         switch (p_type) {
8609             case POINTER:
8610                 pic16_emitcode ("mov","b,a");
8611                 pic16_emitcode("mov","a,@%s",rname);
8612                 break;
8613
8614             case FPOINTER:
8615                 pic16_emitcode ("mov","b,a");
8616                 pic16_emitcode("movx","a,@dptr");
8617                 break;
8618
8619             case GPOINTER:
8620                 pic16_emitcode ("push","b");
8621                 pic16_emitcode ("push","acc");
8622                 pic16_emitcode ("lcall","__gptrget");
8623                 pic16_emitcode ("pop","b");
8624                 break;
8625         }
8626
8627         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8628         pic16_emitcode ("orl","a,b");
8629     }
8630
8631     if (p_type == GPOINTER)
8632         pic16_emitcode("pop","b");
8633
8634     switch (p_type) {
8635
8636     case POINTER:
8637         pic16_emitcode("mov","@%s,a",rname);
8638         break;
8639         
8640     case FPOINTER:
8641         pic16_emitcode("movx","@dptr,a");
8642         break;
8643         
8644     case GPOINTER:
8645         DEBUGpic16_emitcode(";lcall","__gptrput");
8646         break;                  
8647     }
8648 }
8649 /*-----------------------------------------------------------------*/
8650 /* genDataPointerSet - remat pointer to data space                 */
8651 /*-----------------------------------------------------------------*/
8652 static void genDataPointerSet(operand *right,
8653                               operand *result,
8654                               iCode *ic)
8655 {
8656     int size, offset = 0 ;
8657     char *l, buffer[256];
8658
8659     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8660     pic16_aopOp(right,ic,FALSE);
8661     
8662     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8663     size = AOP_SIZE(right);
8664 /*
8665     if ( AOP_TYPE(result) == AOP_PCODE) {
8666       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8667               AOP(result)->aopu.pcop->name,
8668               PCOI(AOP(result)->aopu.pcop)->offset);
8669     }
8670 */
8671
8672     // tsd, was l+1 - the underline `_' prefix was being stripped
8673     while (size--) {
8674       if (offset) {
8675         sprintf(buffer,"(%s + %d)",l,offset);
8676         fprintf(stderr,"oops  %s\n",buffer);
8677       } else
8678         sprintf(buffer,"%s",l);
8679
8680         if (AOP_TYPE(right) == AOP_LIT) {
8681           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8682           lit = lit >> (8*offset);
8683           if(lit&0xff) {
8684             pic16_emitcode("movlw","%d",lit);
8685             pic16_emitcode("movwf","%s",buffer);
8686
8687             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8688             //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
8689             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8690
8691           } else {
8692             pic16_emitcode("clrf","%s",buffer);
8693             //pic16_emitpcode(POC_CLRF, popRegFromString(buffer));
8694             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8695           }
8696         }else {
8697           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8698           pic16_emitcode("movwf","%s",buffer);
8699
8700           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8701           //pic16_emitpcode(POC_MOVWF, popRegFromString(buffer));
8702           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8703
8704         }
8705
8706         offset++;
8707     }
8708
8709     pic16_freeAsmop(right,NULL,ic,TRUE);
8710     pic16_freeAsmop(result,NULL,ic,TRUE);
8711 }
8712
8713 /*-----------------------------------------------------------------*/
8714 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8715 /*-----------------------------------------------------------------*/
8716 static void genNearPointerSet (operand *right,
8717                                operand *result, 
8718                                iCode *ic)
8719 {
8720   asmop *aop = NULL;
8721   char *l;
8722   sym_link *retype;
8723   sym_link *ptype = operandType(result);
8724
8725     
8726   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8727   retype= getSpec(operandType(right));
8728
8729   pic16_aopOp(result,ic,FALSE);
8730
8731     
8732   /* if the result is rematerializable &
8733      in data space & not a bit variable */
8734   //if (AOP_TYPE(result) == AOP_IMMD &&
8735   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8736       DCL_TYPE(ptype) == POINTER   &&
8737       !IS_BITVAR(retype)) {
8738     genDataPointerSet (right,result,ic);
8739     pic16_freeAsmop(result,NULL,ic,TRUE);
8740     return;
8741   }
8742
8743   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8744   pic16_aopOp(right,ic,FALSE);
8745   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8746
8747   /* if the value is already in a pointer register
8748      then don't need anything more */
8749   if (!AOP_INPREG(AOP(result))) {
8750     /* otherwise get a free pointer register */
8751     //aop = newAsmop(0);
8752     //preg = getFreePtr(ic,&aop,FALSE);
8753     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8754     //pic16_emitcode("mov","%s,%s",
8755     //         preg->name,
8756     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8757     //rname = preg->name ;
8758     //pic16_emitcode("movwf","fsr0");
8759     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8760     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8761     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8762     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8763     goto release;
8764
8765   }// else
8766   //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8767
8768
8769   /* if bitfield then unpack the bits */
8770   if (IS_BITVAR(retype)) {
8771     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8772            "The programmer is obviously confused");
8773     //genPackBits (retype,right,rname,POINTER);
8774     exit(1);
8775   }
8776   else {
8777     /* we have can just get the values */
8778     int size = AOP_SIZE(right);
8779     int offset = 0 ;    
8780
8781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8782     while (size--) {
8783       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8784       if (*l == '@' ) {
8785         //MOVA(l);
8786         //pic16_emitcode("mov","@%s,a",rname);
8787         pic16_emitcode("movf","indf0,w ;1");
8788       } else {
8789
8790         if (AOP_TYPE(right) == AOP_LIT) {
8791           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8792           if(lit) {
8793             pic16_emitcode("movlw","%s",l);
8794             pic16_emitcode("movwf","indf0 ;2");
8795           } else 
8796             pic16_emitcode("clrf","indf0");
8797         }else {
8798           pic16_emitcode("movf","%s,w",l);
8799           pic16_emitcode("movwf","indf0 ;2");
8800         }
8801         //pic16_emitcode("mov","@%s,%s",rname,l);
8802       }
8803       if (size)
8804         pic16_emitcode("incf","fsr0,f ;3");
8805       //pic16_emitcode("inc","%s",rname);
8806       offset++;
8807     }
8808   }
8809
8810   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8811   /* now some housekeeping stuff */
8812   if (aop) {
8813     /* we had to allocate for this iCode */
8814     pic16_freeAsmop(NULL,aop,ic,TRUE);
8815   } else { 
8816     /* we did not allocate which means left
8817        already in a pointer register, then
8818        if size > 0 && this could be used again
8819        we have to point it back to where it 
8820        belongs */
8821     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8822     if (AOP_SIZE(right) > 1 &&
8823         !OP_SYMBOL(result)->remat &&
8824         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8825           ic->depth )) {
8826       int size = AOP_SIZE(right) - 1;
8827       while (size--)
8828         pic16_emitcode("decf","fsr0,f");
8829       //pic16_emitcode("dec","%s",rname);
8830     }
8831   }
8832
8833   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8834   /* done */
8835  release:
8836   pic16_freeAsmop(right,NULL,ic,TRUE);
8837   pic16_freeAsmop(result,NULL,ic,TRUE);
8838 }
8839
8840 /*-----------------------------------------------------------------*/
8841 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
8842 /*-----------------------------------------------------------------*/
8843 static void genPagedPointerSet (operand *right,
8844                                operand *result, 
8845                                iCode *ic)
8846 {
8847     asmop *aop = NULL;
8848     regs *preg = NULL ;
8849     char *rname , *l;
8850     sym_link *retype;
8851        
8852     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8853
8854     retype= getSpec(operandType(right));
8855     
8856     pic16_aopOp(result,ic,FALSE);
8857     
8858     /* if the value is already in a pointer register
8859        then don't need anything more */
8860     if (!AOP_INPREG(AOP(result))) {
8861         /* otherwise get a free pointer register */
8862         aop = newAsmop(0);
8863         preg = getFreePtr(ic,&aop,FALSE);
8864         pic16_emitcode("mov","%s,%s",
8865                 preg->name,
8866                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
8867         rname = preg->name ;
8868     } else
8869         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8870     
8871     pic16_freeAsmop(result,NULL,ic,TRUE);
8872     pic16_aopOp (right,ic,FALSE);
8873
8874     /* if bitfield then unpack the bits */
8875     if (IS_BITVAR(retype)) 
8876         genPackBits (retype,right,rname,PPOINTER);
8877     else {
8878         /* we have can just get the values */
8879         int size = AOP_SIZE(right);
8880         int offset = 0 ;        
8881         
8882         while (size--) {
8883             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8884             
8885             MOVA(l);
8886             pic16_emitcode("movx","@%s,a",rname);
8887
8888             if (size)
8889                 pic16_emitcode("inc","%s",rname);
8890
8891             offset++;
8892         }
8893     }
8894     
8895     /* now some housekeeping stuff */
8896     if (aop) {
8897         /* we had to allocate for this iCode */
8898         pic16_freeAsmop(NULL,aop,ic,TRUE);
8899     } else { 
8900         /* we did not allocate which means left
8901            already in a pointer register, then
8902            if size > 0 && this could be used again
8903            we have to point it back to where it 
8904            belongs */
8905         if (AOP_SIZE(right) > 1 &&
8906             !OP_SYMBOL(result)->remat &&
8907             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8908               ic->depth )) {
8909             int size = AOP_SIZE(right) - 1;
8910             while (size--)
8911                 pic16_emitcode("dec","%s",rname);
8912         }
8913     }
8914
8915     /* done */
8916     pic16_freeAsmop(right,NULL,ic,TRUE);
8917     
8918         
8919 }
8920
8921 /*-----------------------------------------------------------------*/
8922 /* genFarPointerSet - set value from far space                     */
8923 /*-----------------------------------------------------------------*/
8924 static void genFarPointerSet (operand *right,
8925                               operand *result, iCode *ic)
8926 {
8927     int size, offset ;
8928     sym_link *retype = getSpec(operandType(right));
8929
8930     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8931     pic16_aopOp(result,ic,FALSE);
8932
8933     /* if the operand is already in dptr 
8934     then we do nothing else we move the value to dptr */
8935     if (AOP_TYPE(result) != AOP_STR) {
8936         /* if this is remateriazable */
8937         if (AOP_TYPE(result) == AOP_IMMD)
8938             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8939         else { /* we need to get it byte by byte */
8940             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
8941             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
8942             if (options.model == MODEL_FLAT24)
8943             {
8944                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
8945             }
8946         }
8947     }
8948     /* so dptr know contains the address */
8949     pic16_freeAsmop(result,NULL,ic,TRUE);
8950     pic16_aopOp(right,ic,FALSE);
8951
8952     /* if bit then unpack */
8953     if (IS_BITVAR(retype)) 
8954         genPackBits(retype,right,"dptr",FPOINTER);
8955     else {
8956         size = AOP_SIZE(right);
8957         offset = 0 ;
8958
8959         while (size--) {
8960             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8961             MOVA(l);
8962             pic16_emitcode("movx","@dptr,a");
8963             if (size)
8964                 pic16_emitcode("inc","dptr");
8965         }
8966     }
8967
8968     pic16_freeAsmop(right,NULL,ic,TRUE);
8969 }
8970
8971 /*-----------------------------------------------------------------*/
8972 /* genGenPointerSet - set value from generic pointer space         */
8973 /*-----------------------------------------------------------------*/
8974 static void genGenPointerSet (operand *right,
8975                               operand *result, iCode *ic)
8976 {
8977   int size, offset ;
8978   sym_link *retype = getSpec(operandType(right));
8979
8980   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8981
8982   pic16_aopOp(result,ic,FALSE);
8983   pic16_aopOp(right,ic,FALSE);
8984   size = AOP_SIZE(right);
8985
8986   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8987
8988   /* if the operand is already in dptr 
8989      then we do nothing else we move the value to dptr */
8990   if (AOP_TYPE(result) != AOP_STR) {
8991     /* if this is remateriazable */
8992     if (AOP_TYPE(result) == AOP_IMMD) {
8993       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8994       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8995     }
8996     else { /* we need to get it byte by byte */
8997       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8998       size = AOP_SIZE(right);
8999       offset = 0 ;
9000
9001       /* hack hack! see if this the FSR. If so don't load W */
9002       if(AOP_TYPE(right) != AOP_ACC) {
9003
9004
9005         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9006         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9007
9008         if(AOP_SIZE(result) > 1) {
9009           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9010           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9011           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9012
9013         }
9014
9015         //if(size==2)
9016         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9017         //if(size==4) {
9018         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9019         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9020         //}
9021
9022         while(size--) {
9023           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9024           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9025           
9026           if(size)
9027             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9028         }
9029
9030
9031         goto release;
9032       } 
9033
9034       if(aopIdx(AOP(result),0) != 4) {
9035
9036         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9037         goto release;
9038       }
9039
9040       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9041       goto release;
9042
9043     }
9044   }
9045   /* so dptr know contains the address */
9046
9047
9048   /* if bit then unpack */
9049   if (IS_BITVAR(retype)) 
9050     genPackBits(retype,right,"dptr",GPOINTER);
9051   else {
9052     size = AOP_SIZE(right);
9053     offset = 0 ;
9054
9055   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9056
9057     while (size--) {
9058
9059       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9060       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9061
9062       if (AOP_TYPE(right) == AOP_LIT) 
9063         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9064       else
9065         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9066
9067       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9068
9069       offset++;
9070     }
9071   }
9072
9073  release:
9074   pic16_freeAsmop(right,NULL,ic,TRUE);
9075   pic16_freeAsmop(result,NULL,ic,TRUE);
9076 }
9077
9078 /*-----------------------------------------------------------------*/
9079 /* genPointerSet - stores the value into a pointer location        */
9080 /*-----------------------------------------------------------------*/
9081 static void genPointerSet (iCode *ic)
9082 {    
9083     operand *right, *result ;
9084     sym_link *type, *etype;
9085     int p_type;
9086
9087     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9088
9089     right = IC_RIGHT(ic);
9090     result = IC_RESULT(ic) ;
9091
9092     /* depending on the type of pointer we need to
9093     move it to the correct pointer register */
9094     type = operandType(result);
9095     etype = getSpec(type);
9096     /* if left is of type of pointer then it is simple */
9097     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9098         p_type = DCL_TYPE(type);
9099     }
9100     else {
9101         /* we have to go by the storage class */
9102         p_type = PTR_TYPE(SPEC_OCLS(etype));
9103
9104 /*      if (SPEC_OCLS(etype)->codesp ) { */
9105 /*          p_type = CPOINTER ;  */
9106 /*      } */
9107 /*      else */
9108 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9109 /*              p_type = FPOINTER ; */
9110 /*          else */
9111 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9112 /*                  p_type = PPOINTER ; */
9113 /*              else */
9114 /*                  if (SPEC_OCLS(etype) == idata ) */
9115 /*                      p_type = IPOINTER ; */
9116 /*                  else */
9117 /*                      p_type = POINTER ; */
9118     }
9119
9120     /* now that we have the pointer type we assign
9121     the pointer values */
9122     switch (p_type) {
9123
9124     case POINTER:
9125     case IPOINTER:
9126         genNearPointerSet (right,result,ic);
9127         break;
9128
9129     case PPOINTER:
9130         genPagedPointerSet (right,result,ic);
9131         break;
9132
9133     case FPOINTER:
9134         genFarPointerSet (right,result,ic);
9135         break;
9136
9137     case GPOINTER:
9138         genGenPointerSet (right,result,ic);
9139         break;
9140
9141     default:
9142       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9143               "genPointerSet: illegal pointer type");
9144     }
9145 }
9146
9147 /*-----------------------------------------------------------------*/
9148 /* genIfx - generate code for Ifx statement                        */
9149 /*-----------------------------------------------------------------*/
9150 static void genIfx (iCode *ic, iCode *popIc)
9151 {
9152   operand *cond = IC_COND(ic);
9153   int isbit =0;
9154
9155   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9156
9157   pic16_aopOp(cond,ic,FALSE);
9158
9159   /* get the value into acc */
9160   if (AOP_TYPE(cond) != AOP_CRY)
9161     pic16_toBoolean(cond);
9162   else
9163     isbit = 1;
9164   /* the result is now in the accumulator */
9165   pic16_freeAsmop(cond,NULL,ic,TRUE);
9166
9167   /* if there was something to be popped then do it */
9168   if (popIc)
9169     genIpop(popIc);
9170
9171   /* if the condition is  a bit variable */
9172   if (isbit && IS_ITEMP(cond) && 
9173       SPIL_LOC(cond)) {
9174     genIfxJump(ic,SPIL_LOC(cond)->rname);
9175     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9176   }
9177   else {
9178     if (isbit && !IS_ITEMP(cond))
9179       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9180     else
9181       genIfxJump(ic,"a");
9182   }
9183   ic->generated = 1;
9184
9185 }
9186
9187 /*-----------------------------------------------------------------*/
9188 /* genAddrOf - generates code for address of                       */
9189 /*-----------------------------------------------------------------*/
9190 static void genAddrOf (iCode *ic)
9191 {
9192   operand *right, *result, *left;
9193   int size, offset ;
9194
9195   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9196
9197
9198   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9199
9200   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9201   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9202   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9203
9204   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9205
9206   size = AOP_SIZE(IC_RESULT(ic));
9207   offset = 0;
9208
9209
9210   while (size--) {
9211     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9212     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9213     offset++;
9214   }
9215
9216
9217   pic16_freeAsmop(left,NULL,ic,FALSE);
9218   pic16_freeAsmop(result,NULL,ic,TRUE);
9219
9220 }
9221
9222 #if 0
9223 /*-----------------------------------------------------------------*/
9224 /* genFarFarAssign - assignment when both are in far space         */
9225 /*-----------------------------------------------------------------*/
9226 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9227 {
9228     int size = AOP_SIZE(right);
9229     int offset = 0;
9230     char *l ;
9231     /* first push the right side on to the stack */
9232     while (size--) {
9233         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9234         MOVA(l);
9235         pic16_emitcode ("push","acc");
9236     }
9237     
9238     pic16_freeAsmop(right,NULL,ic,FALSE);
9239     /* now assign DPTR to result */
9240     pic16_aopOp(result,ic,FALSE);
9241     size = AOP_SIZE(result);
9242     while (size--) {
9243         pic16_emitcode ("pop","acc");
9244         pic16_aopPut(AOP(result),"a",--offset);
9245     }
9246     pic16_freeAsmop(result,NULL,ic,FALSE);
9247         
9248 }
9249 #endif
9250
9251 /*-----------------------------------------------------------------*/
9252 /* genAssign - generate code for assignment                        */
9253 /*-----------------------------------------------------------------*/
9254 static void genAssign (iCode *ic)
9255 {
9256   operand *result, *right;
9257   int size, offset,know_W;
9258   unsigned long lit = 0L;
9259
9260   result = IC_RESULT(ic);
9261   right  = IC_RIGHT(ic) ;
9262
9263   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9264   
9265   /* if they are the same */
9266   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9267     return ;
9268
9269   pic16_aopOp(right,ic,FALSE);
9270   pic16_aopOp(result,ic,TRUE);
9271
9272   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9273
9274   /* if they are the same registers */
9275   if (pic16_sameRegs(AOP(right),AOP(result)))
9276     goto release;
9277
9278   /* if the result is a bit */
9279   if (AOP_TYPE(result) == AOP_CRY) {
9280     /* if the right size is a literal then
9281        we know what the value is */
9282     if (AOP_TYPE(right) == AOP_LIT) {
9283           
9284       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9285                   pic16_popGet(AOP(result),0));
9286
9287       if (((int) operandLitValue(right))) 
9288         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9289                        AOP(result)->aopu.aop_dir,
9290                        AOP(result)->aopu.aop_dir);
9291       else
9292         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9293                        AOP(result)->aopu.aop_dir,
9294                        AOP(result)->aopu.aop_dir);
9295       goto release;
9296     }
9297
9298     /* the right is also a bit variable */
9299     if (AOP_TYPE(right) == AOP_CRY) {
9300       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9301       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9302       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9303
9304       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9305                      AOP(result)->aopu.aop_dir,
9306                      AOP(result)->aopu.aop_dir);
9307       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9308                      AOP(right)->aopu.aop_dir,
9309                      AOP(right)->aopu.aop_dir);
9310       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9311                      AOP(result)->aopu.aop_dir,
9312                      AOP(result)->aopu.aop_dir);
9313       goto release ;
9314     }
9315
9316     /* we need to or */
9317     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9318     pic16_toBoolean(right);
9319     emitSKPZ;
9320     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9321     //pic16_aopPut(AOP(result),"a",0);
9322     goto release ;
9323   }
9324
9325   /* bit variables done */
9326   /* general case */
9327   size = AOP_SIZE(result);
9328   offset = 0 ;
9329   if(AOP_TYPE(right) == AOP_LIT)
9330     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9331
9332 /* VR - What is this?! */
9333   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9334   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9335     if(aopIdx(AOP(result),0) == 4) {
9336   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9337       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9338       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9339       goto release;
9340     } else
9341       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9342   }
9343
9344   know_W=-1;
9345   while (size--) {
9346   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9347     if(AOP_TYPE(right) == AOP_LIT) {
9348       if(lit&0xff) {
9349         if(know_W != (lit&0xff))
9350           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9351         know_W = lit&0xff;
9352         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9353       } else
9354         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9355
9356       lit >>= 8;
9357
9358     } else if (AOP_TYPE(right) == AOP_CRY) {
9359       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9360       if(offset == 0) {
9361         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9362         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9363       }
9364     } else {
9365   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9366
9367 #if 1
9368         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9369            normally should work, but mind that thw W register live range
9370            is not checked, so if the code generator assumes that the W
9371            is already loaded after such a pair, wrong code will be generated.
9372            
9373            Checking the live range is the next step.
9374            This is experimental code yet and has not been fully tested yet.
9375            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9376            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9377            
9378         
9379         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9380 #else   
9381         /* This is the old code, which is assumed(?!) that works fine(!?) */
9382
9383         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9384         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9385 #endif
9386     }
9387             
9388     offset++;
9389   }
9390
9391     
9392  release:
9393   pic16_freeAsmop (right,NULL,ic,FALSE);
9394   pic16_freeAsmop (result,NULL,ic,TRUE);
9395 }   
9396
9397 /*-----------------------------------------------------------------*/
9398 /* genJumpTab - generates code for jump table                       */
9399 /*-----------------------------------------------------------------*/
9400 static void genJumpTab (iCode *ic)
9401 {
9402     symbol *jtab;
9403     char *l;
9404
9405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9406
9407     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9408     /* get the condition into accumulator */
9409     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9410     MOVA(l);
9411     /* multiply by three */
9412     pic16_emitcode("add","a,acc");
9413     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9414
9415     jtab = newiTempLabel(NULL);
9416     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9417     pic16_emitcode("jmp","@a+dptr");
9418     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9419
9420     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9421     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9422     emitSKPNC;
9423     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9424     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9425     pic16_emitpLabel(jtab->key);
9426
9427     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9428
9429     /* now generate the jump labels */
9430     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9431          jtab = setNextItem(IC_JTLABELS(ic))) {
9432         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9433         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9434         
9435     }
9436
9437 }
9438
9439 /*-----------------------------------------------------------------*/
9440 /* genMixedOperation - gen code for operators between mixed types  */
9441 /*-----------------------------------------------------------------*/
9442 /*
9443   TSD - Written for the PIC port - but this unfortunately is buggy.
9444   This routine is good in that it is able to efficiently promote 
9445   types to different (larger) sizes. Unfortunately, the temporary
9446   variables that are optimized out by this routine are sometimes
9447   used in other places. So until I know how to really parse the 
9448   iCode tree, I'm going to not be using this routine :(.
9449 */
9450 static int genMixedOperation (iCode *ic)
9451 {
9452 #if 0
9453   operand *result = IC_RESULT(ic);
9454   sym_link *ctype = operandType(IC_LEFT(ic));
9455   operand *right = IC_RIGHT(ic);
9456   int ret = 0;
9457   int big,small;
9458   int offset;
9459
9460   iCode *nextic;
9461   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9462
9463   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9464
9465   nextic = ic->next;
9466   if(!nextic)
9467     return 0;
9468
9469   nextright = IC_RIGHT(nextic);
9470   nextleft  = IC_LEFT(nextic);
9471   nextresult = IC_RESULT(nextic);
9472
9473   pic16_aopOp(right,ic,FALSE);
9474   pic16_aopOp(result,ic,FALSE);
9475   pic16_aopOp(nextright,  nextic, FALSE);
9476   pic16_aopOp(nextleft,   nextic, FALSE);
9477   pic16_aopOp(nextresult, nextic, FALSE);
9478
9479   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9480
9481     operand *t = right;
9482     right = nextright;
9483     nextright = t; 
9484
9485     pic16_emitcode(";remove right +","");
9486
9487   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9488 /*
9489     operand *t = right;
9490     right = nextleft;
9491     nextleft = t; 
9492 */
9493     pic16_emitcode(";remove left +","");
9494   } else
9495     return 0;
9496
9497   big = AOP_SIZE(nextleft);
9498   small = AOP_SIZE(nextright);
9499
9500   switch(nextic->op) {
9501
9502   case '+':
9503     pic16_emitcode(";optimize a +","");
9504     /* if unsigned or not an integral type */
9505     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9506       pic16_emitcode(";add a bit to something","");
9507     } else {
9508
9509       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9510
9511       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9512         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9513         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9514       } else
9515         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9516
9517       offset = 0;
9518       while(--big) {
9519
9520         offset++;
9521
9522         if(--small) {
9523           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9524             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9525             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9526           }
9527
9528           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9529           emitSKPNC;
9530           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9531                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9532                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9533           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9534           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9535
9536         } else {
9537           pic16_emitcode("rlf","known_zero,w");
9538
9539           /*
9540             if right is signed
9541               btfsc  right,7
9542                addlw ff
9543           */
9544           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9545             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9546             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9547           } else {
9548             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9549           }
9550         }
9551       }
9552       ret = 1;
9553     }
9554   }
9555   ret = 1;
9556
9557 release:
9558   pic16_freeAsmop(right,NULL,ic,TRUE);
9559   pic16_freeAsmop(result,NULL,ic,TRUE);
9560   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9561   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9562   if(ret)
9563     nextic->generated = 1;
9564
9565   return ret;
9566 #else
9567   return 0;
9568 #endif
9569 }
9570 /*-----------------------------------------------------------------*/
9571 /* genCast - gen code for casting                                  */
9572 /*-----------------------------------------------------------------*/
9573 static void genCast (iCode *ic)
9574 {
9575     operand *result = IC_RESULT(ic);
9576     sym_link *ctype = operandType(IC_LEFT(ic));
9577     sym_link *rtype = operandType(IC_RIGHT(ic));
9578     operand *right = IC_RIGHT(ic);
9579     int size, offset ;
9580
9581     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9582     /* if they are equivalent then do nothing */
9583     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9584         return ;
9585
9586     pic16_aopOp(right,ic,FALSE) ;
9587     pic16_aopOp(result,ic,FALSE);
9588
9589     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9590
9591     /* if the result is a bit */
9592     if (AOP_TYPE(result) == AOP_CRY) {
9593         /* if the right size is a literal then
9594         we know what the value is */
9595       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9596         if (AOP_TYPE(right) == AOP_LIT) {
9597
9598           pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9599                       pic16_popGet(AOP(result),0));
9600
9601             if (((int) operandLitValue(right))) 
9602               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9603                        AOP(result)->aopu.aop_dir,
9604                        AOP(result)->aopu.aop_dir);
9605             else
9606               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9607                        AOP(result)->aopu.aop_dir,
9608                        AOP(result)->aopu.aop_dir);
9609
9610             goto release;
9611         }
9612
9613         /* the right is also a bit variable */
9614         if (AOP_TYPE(right) == AOP_CRY) {
9615
9616           emitCLRC;
9617           pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9618
9619           pic16_emitcode("clrc","");
9620           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9621                    AOP(right)->aopu.aop_dir,
9622                    AOP(right)->aopu.aop_dir);
9623             pic16_aopPut(AOP(result),"c",0);
9624             goto release ;
9625         }
9626
9627         /* we need to or */
9628         if (AOP_TYPE(right) == AOP_REG) {
9629           pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9630           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9631           pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9632         }
9633         pic16_toBoolean(right);
9634         pic16_aopPut(AOP(result),"a",0);
9635         goto release ;
9636     }
9637
9638     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9639       int offset = 1;
9640       size = AOP_SIZE(result);
9641
9642       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9643
9644       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9645       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9646       pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9647
9648       while (size--)
9649         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9650
9651       goto release;
9652     }
9653
9654     /* if they are the same size : or less */
9655     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9656
9657         /* if they are in the same place */
9658       if (pic16_sameRegs(AOP(right),AOP(result)))
9659         goto release;
9660
9661       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9662 #if 0
9663       if (IS_PTR_CONST(rtype))
9664 #else
9665       if (IS_CODEPTR(rtype))
9666 #endif
9667         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9668 #if 0
9669       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9670 #else
9671       if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9672 #endif
9673         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9674
9675       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9676         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9677         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9678         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9679         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9680         if(AOP_SIZE(result) <2)
9681           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9682
9683       } else {
9684
9685         /* if they in different places then copy */
9686         size = AOP_SIZE(result);
9687         offset = 0 ;
9688         while (size--) {
9689           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9690           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9691
9692           //pic16_aopPut(AOP(result),
9693           // pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9694           // offset);
9695
9696           offset++;
9697         }
9698       }
9699       goto release;
9700     }
9701
9702
9703     /* if the result is of type pointer */
9704     if (IS_PTR(ctype)) {
9705
9706         int p_type;
9707         sym_link *type = operandType(right);
9708         sym_link *etype = getSpec(type);
9709       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9710
9711         /* pointer to generic pointer */
9712         if (IS_GENPTR(ctype)) {
9713             char *l = zero;
9714             
9715             if (IS_PTR(type)) 
9716                 p_type = DCL_TYPE(type);
9717             else {
9718                 /* we have to go by the storage class */
9719                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9720
9721 /*              if (SPEC_OCLS(etype)->codesp )  */
9722 /*                  p_type = CPOINTER ;  */
9723 /*              else */
9724 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9725 /*                      p_type = FPOINTER ; */
9726 /*                  else */
9727 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9728 /*                          p_type = PPOINTER; */
9729 /*                      else */
9730 /*                          if (SPEC_OCLS(etype) == idata ) */
9731 /*                              p_type = IPOINTER ; */
9732 /*                          else */
9733 /*                              p_type = POINTER ; */
9734             }
9735                 
9736             /* the first two bytes are known */
9737       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9738             size = GPTRSIZE - 1; 
9739             offset = 0 ;
9740             while (size--) {
9741               if(offset < AOP_SIZE(right)) {
9742       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9743                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9744                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9745                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9746                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9747                 } else { 
9748                   pic16_aopPut(AOP(result),
9749                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9750                          offset);
9751                 }
9752               } else 
9753                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9754               offset++;
9755             }
9756             /* the last byte depending on type */
9757             switch (p_type) {
9758             case IPOINTER:
9759             case POINTER:
9760                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
9761                 break;
9762             case FPOINTER:
9763               pic16_emitcode(";BUG!? ","%d",__LINE__);
9764                 l = one;
9765                 break;
9766             case CPOINTER:
9767               pic16_emitcode(";BUG!? ","%d",__LINE__);
9768                 l = "#0x02";
9769                 break;                          
9770             case PPOINTER:
9771               pic16_emitcode(";BUG!? ","%d",__LINE__);
9772                 l = "#0x03";
9773                 break;
9774                 
9775             default:
9776                 /* this should never happen */
9777                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9778                        "got unknown pointer type");
9779                 exit(1);
9780             }
9781             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
9782             goto release ;
9783         }
9784         
9785         /* just copy the pointers */
9786         size = AOP_SIZE(result);
9787         offset = 0 ;
9788         while (size--) {
9789             pic16_aopPut(AOP(result),
9790                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9791                    offset);
9792             offset++;
9793         }
9794         goto release ;
9795     }
9796     
9797
9798
9799     /* so we now know that the size of destination is greater
9800     than the size of the source.
9801     Now, if the next iCode is an operator then we might be
9802     able to optimize the operation without performing a cast.
9803     */
9804     if(genMixedOperation(ic))
9805       goto release;
9806
9807     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9808     
9809     /* we move to result for the size of source */
9810     size = AOP_SIZE(right);
9811     offset = 0 ;
9812     while (size--) {
9813       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
9814       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
9815       offset++;
9816     }
9817
9818     /* now depending on the sign of the destination */
9819     size = AOP_SIZE(result) - AOP_SIZE(right);
9820     /* if unsigned or not an integral type */
9821     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9822       while (size--)
9823         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9824     } else {
9825       /* we need to extend the sign :{ */
9826
9827       if(size == 1) {
9828         /* Save one instruction of casting char to int */
9829         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9830         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9831         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
9832       } else {
9833         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9834
9835         if(offset)
9836           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9837         else
9838           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9839         
9840         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9841
9842         while (size--)
9843           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9844       }
9845     }
9846
9847 release:
9848     pic16_freeAsmop(right,NULL,ic,TRUE);
9849     pic16_freeAsmop(result,NULL,ic,TRUE);
9850
9851 }
9852
9853 /*-----------------------------------------------------------------*/
9854 /* genDjnz - generate decrement & jump if not zero instrucion      */
9855 /*-----------------------------------------------------------------*/
9856 static int genDjnz (iCode *ic, iCode *ifx)
9857 {
9858     symbol *lbl, *lbl1;
9859     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9860
9861     if (!ifx)
9862         return 0;
9863     
9864     /* if the if condition has a false label
9865        then we cannot save */
9866     if (IC_FALSE(ifx))
9867         return 0;
9868
9869     /* if the minus is not of the form 
9870        a = a - 1 */
9871     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9872         !IS_OP_LITERAL(IC_RIGHT(ic)))
9873         return 0;
9874
9875     if (operandLitValue(IC_RIGHT(ic)) != 1)
9876         return 0;
9877
9878     /* if the size of this greater than one then no
9879        saving */
9880     if (getSize(operandType(IC_RESULT(ic))) > 1)
9881         return 0;
9882
9883     /* otherwise we can save BIG */
9884     lbl = newiTempLabel(NULL);
9885     lbl1= newiTempLabel(NULL);
9886
9887     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9888     
9889     if (IS_AOP_PREG(IC_RESULT(ic))) {
9890         pic16_emitcode("dec","%s",
9891                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9892         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9893         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
9894     } else {    
9895
9896
9897       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9898       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9899
9900       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9901       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9902
9903     }
9904 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9905 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
9906 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9907 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
9908
9909     
9910     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9911     ifx->generated = 1;
9912     return 1;
9913 }
9914
9915 /*-----------------------------------------------------------------*/
9916 /* genReceive - generate code for a receive iCode                  */
9917 /*-----------------------------------------------------------------*/
9918 static void genReceive (iCode *ic)
9919 {    
9920   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9921
9922   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9923       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9924         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9925
9926     int size = getSize(operandType(IC_RESULT(ic)));
9927     int offset =  pic16_fReturnSizePic - size;
9928     while (size--) {
9929       pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9930                                     fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9931       offset++;
9932     }
9933     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9934     size = AOP_SIZE(IC_RESULT(ic));
9935     offset = 0;
9936     while (size--) {
9937       pic16_emitcode ("pop","acc");
9938       pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9939     }
9940         
9941   } else {
9942     _G.accInUse++;
9943     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9944     _G.accInUse--;
9945     assignResultValue(IC_RESULT(ic));   
9946   }
9947
9948   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9949 }
9950
9951 /*-----------------------------------------------------------------*/
9952 /* genDummyRead - generate code for dummy read of volatiles        */
9953 /*-----------------------------------------------------------------*/
9954 static void
9955 genDummyRead (iCode * ic)
9956 {
9957   pic16_emitcode ("; genDummyRead","");
9958   pic16_emitcode ("; not implemented","");
9959
9960   ic = ic;
9961 }
9962
9963 /*-----------------------------------------------------------------*/
9964 /* genpic16Code - generate code for pic16 based controllers        */
9965 /*-----------------------------------------------------------------*/
9966 /*
9967  * At this point, ralloc.c has gone through the iCode and attempted
9968  * to optimize in a way suitable for a PIC. Now we've got to generate
9969  * PIC instructions that correspond to the iCode.
9970  *
9971  * Once the instructions are generated, we'll pass through both the
9972  * peep hole optimizer and the pCode optimizer.
9973  *-----------------------------------------------------------------*/
9974
9975 void genpic16Code (iCode *lic)
9976 {
9977     iCode *ic;
9978     int cln = 0;
9979
9980     lineHead = lineCurr = NULL;
9981
9982     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
9983     pic16_addpBlock(pb);
9984
9985 #if 0
9986     /* if debug information required */
9987     if (options.debug && currFunc) {
9988       if (currFunc) {
9989         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9990         _G.debugLine = 1;
9991         if (IS_STATIC(currFunc->etype)) {
9992           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9993           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
9994         } else {
9995           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9996           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
9997         }
9998         _G.debugLine = 0;
9999       }
10000     }
10001 #endif
10002
10003 //    dumpiCode(lic);
10004
10005     for (ic = lic ; ic ; ic = ic->next ) {
10006
10007 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10008 //      DEBUGpic16_emitcode("; VR", "");
10009       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10010         if ( cln != ic->lineno ) {
10011             if ( options.debug ) {
10012                 _G.debugLine = 1;
10013                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10014                          FileBaseName(ic->filename),ic->lineno,
10015                          ic->level,ic->block);
10016                 _G.debugLine = 0;
10017             }
10018             /*
10019               pic16_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
10020               pic16_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
10021               printCLine(ic->filename, ic->lineno));
10022             */
10023             pic16_addpCode2pBlock(pb,
10024                             pic16_newpCodeCSource(ic->lineno, 
10025                                             ic->filename, 
10026                                             printCLine(ic->filename, ic->lineno)));
10027
10028             cln = ic->lineno ;
10029         }
10030         /* if the result is marked as
10031            spilt and rematerializable or code for
10032            this has already been generated then
10033            do nothing */
10034         if (resultRemat(ic) || ic->generated ) 
10035             continue ;
10036         
10037         /* depending on the operation */
10038         switch (ic->op) {
10039         case '!' :
10040             genNot(ic);
10041             break;
10042             
10043         case '~' :
10044             genCpl(ic);
10045             break;
10046             
10047         case UNARYMINUS:
10048             genUminus (ic);
10049             break;
10050             
10051         case IPUSH:
10052             genIpush (ic);
10053             break;
10054             
10055         case IPOP:
10056             /* IPOP happens only when trying to restore a 
10057                spilt live range, if there is an ifx statement
10058                following this pop then the if statement might
10059                be using some of the registers being popped which
10060                would destroy the contents of the register so
10061                we need to check for this condition and handle it */
10062             if (ic->next            && 
10063                 ic->next->op == IFX &&
10064                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10065                 genIfx (ic->next,ic);
10066             else
10067                 genIpop (ic);
10068             break; 
10069             
10070         case CALL:
10071             genCall (ic);
10072             break;
10073             
10074         case PCALL:
10075             genPcall (ic);
10076             break;
10077             
10078         case FUNCTION:
10079             genFunction (ic);
10080             break;
10081             
10082         case ENDFUNCTION:
10083             genEndFunction (ic);
10084             break;
10085             
10086         case RETURN:
10087             genRet (ic);
10088             break;
10089             
10090         case LABEL:
10091             genLabel (ic);
10092             break;
10093             
10094         case GOTO:
10095             genGoto (ic);
10096             break;
10097             
10098         case '+' :
10099             pic16_genPlus (ic) ;
10100             break;
10101             
10102         case '-' :
10103             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10104                 pic16_genMinus (ic);
10105             break;
10106             
10107         case '*' :
10108             genMult (ic);
10109             break;
10110             
10111         case '/' :
10112             genDiv (ic) ;
10113             break;
10114             
10115         case '%' :
10116             genMod (ic);
10117             break;
10118             
10119         case '>' :
10120             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10121             break;
10122             
10123         case '<' :
10124             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10125             break;
10126             
10127         case LE_OP:
10128         case GE_OP:
10129         case NE_OP:
10130             
10131             /* note these two are xlated by algebraic equivalence
10132                during parsing SDCC.y */
10133             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10134                    "got '>=' or '<=' shouldn't have come here");
10135             break;      
10136             
10137         case EQ_OP:
10138             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10139             break;          
10140             
10141         case AND_OP:
10142             genAndOp (ic);
10143             break;
10144             
10145         case OR_OP:
10146             genOrOp (ic);
10147             break;
10148             
10149         case '^' :
10150             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10151             break;
10152             
10153         case '|' :
10154                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10155             break;
10156             
10157         case BITWISEAND:
10158             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10159             break;
10160             
10161         case INLINEASM:
10162             genInline (ic);
10163             break;
10164             
10165         case RRC:
10166             genRRC (ic);
10167             break;
10168             
10169         case RLC:
10170             genRLC (ic);
10171             break;
10172             
10173         case GETHBIT:
10174             genGetHbit (ic);
10175             break;
10176             
10177         case LEFT_OP:
10178             genLeftShift (ic);
10179             break;
10180             
10181         case RIGHT_OP:
10182             genRightShift (ic);
10183             break;
10184             
10185         case GET_VALUE_AT_ADDRESS:
10186             genPointerGet(ic);
10187             break;
10188             
10189         case '=' :
10190             if (POINTER_SET(ic))
10191                 genPointerSet(ic);
10192             else
10193                 genAssign(ic);
10194             break;
10195             
10196         case IFX:
10197             genIfx (ic,NULL);
10198             break;
10199             
10200         case ADDRESS_OF:
10201             genAddrOf (ic);
10202             break;
10203             
10204         case JUMPTABLE:
10205             genJumpTab (ic);
10206             break;
10207             
10208         case CAST:
10209             genCast (ic);
10210             break;
10211             
10212         case RECEIVE:
10213             genReceive(ic);
10214             break;
10215             
10216         case SEND:
10217             addSet(&_G.sendSet,ic);
10218             break;
10219
10220         case DUMMY_READ_VOLATILE:
10221           genDummyRead (ic);
10222           break;
10223
10224         default :
10225             ic = ic;
10226         }
10227     }
10228
10229
10230     /* now we are ready to call the
10231        peep hole optimizer */
10232     if (!options.nopeep) {
10233       peepHole (&lineHead);
10234     }
10235     /* now do the actual printing */
10236     printLine (lineHead,codeOutFile);
10237
10238 #ifdef PCODE_DEBUG
10239     DFPRINTF((stderr,"printing pBlock\n\n"));
10240     pic16_printpBlock(stdout,pb);
10241 #endif
10242
10243     return;
10244 }
10245