2004-01-05 Vangelis Rokas <vrokas@otenet.gr>
[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 *pic16_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
65 /* max_key keeps track of the largest label number used in 
66    a function. This is then used to adjust the label offset
67    for the next function.
68 */
69 static int max_key=0;
70 static int GpsuedoStkPtr=0;
71
72 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
73 unsigned int pic16aopLiteral (value *val, int offset);
74 const char *pic16_AopType(short type);
75 static iCode *ifxForOp ( operand *op, iCode *ic );
76
77 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
78
79 /* this is the down and dirty file with all kinds of 
80    kludgy & hacky stuff. This is what it is all about
81    CODE GENERATION for a specific MCU . some of the
82    routines may be reusable, will have to see */
83
84 static char *zero = "#0x00";
85 static char *one  = "#0x01";
86 static char *spname = "sp";
87
88 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
89 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
90 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic16;
92
93 static char *accUse[] = {"a","b"};
94
95 //static short rbank = -1;
96
97 static struct {
98     short r0Pushed;
99     short r1Pushed;
100     short accInUse;
101     short inLine;
102     short debugLine;
103     short nRegsSaved;
104     set *sendSet;
105 } _G;
106
107 /* Resolved ifx structure. This structure stores information
108    about an iCode ifx that makes it easier to generate code.
109 */
110 typedef struct resolvedIfx {
111   symbol *lbl;     /* pointer to a label */
112   int condition;   /* true or false ifx */
113   int generated;   /* set true when the code associated with the ifx
114                     * is generated */
115 } resolvedIfx;
116
117 extern int pic16_ptrRegReq ;
118 extern int pic16_nRegs;
119 extern FILE *codeOutFile;
120 static void saverbank (int, iCode *,bool);
121
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
124
125 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
126 0xE0, 0xC0, 0x80, 0x00};
127 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
129
130 static  pBlock *pb;
131
132 /*-----------------------------------------------------------------*/
133 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
134 /*                 exponent of 2 is returned, otherwise -1 is      */
135 /*                 returned.                                       */
136 /* note that this is similar to the function `powof2' in SDCCsymt  */
137 /* if(n == 2^y)                                                    */
138 /*   return y;                                                     */
139 /* return -1;                                                      */
140 /*-----------------------------------------------------------------*/
141 static int my_powof2 (unsigned long num)
142 {
143   if(num) {
144     if( (num & (num-1)) == 0) {
145       int nshifts = -1;
146       while(num) {
147         num>>=1;
148         nshifts++;
149       }
150       return nshifts;
151     }
152   }
153
154   return -1;
155 }
156
157 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
158 {
159
160   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
161                        line_no,
162                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
163                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
164                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
165                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
166                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
167                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
168                        ((result) ? AOP_SIZE(result) : 0));
169
170 }
171
172 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
173 {
174
175   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
176                        line_no,
177                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
178                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
179                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
180                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
181                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
182                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
183
184 }
185
186 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
187 {
188     va_list ap;
189     char lb[INITIAL_INLINEASM];  
190     char *lbp = lb;
191
192     if(!pic16_debug_verbose)
193       return;
194
195     va_start(ap,fmt);   
196
197     if (inst && *inst) {
198         if (fmt && *fmt)
199             sprintf(lb,"%s\t",inst);
200         else
201             sprintf(lb,"%s",inst);
202         vsprintf(lb+(strlen(lb)),fmt,ap);
203     }  else
204         vsprintf(lb,fmt,ap);
205
206     while (isspace(*lbp)) lbp++;
207
208     if (lbp && *lbp) 
209         lineCurr = (lineCurr ?
210                     connectLine(lineCurr,newLineNode(lb)) :
211                     (lineHead = newLineNode(lb)));
212     lineCurr->isInline = _G.inLine;
213     lineCurr->isDebug  = _G.debugLine;
214
215     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
216     va_end(ap);
217
218 //      fprintf(stderr, "%s\n", lb);
219 }
220
221
222 void pic16_emitpLabel(int key)
223 {
224   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
225 }
226
227 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
228 {
229
230   if(pcop)
231     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
232   else
233     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
234     
235 //    fprintf(stderr, "%s\n", pcop->name);
236 }
237
238 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
239 {
240
241   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
242
243 }
244
245 /*-----------------------------------------------------------------*/
246 /* pic16_emitcode - writes the code into a file : for now it is simple    */
247 /*-----------------------------------------------------------------*/
248 void pic16_emitcode (char *inst,char *fmt, ...)
249 {
250     va_list ap;
251     char lb[INITIAL_INLINEASM];  
252     char *lbp = lb;
253
254     va_start(ap,fmt);   
255
256     if (inst && *inst) {
257         if (fmt && *fmt)
258             sprintf(lb,"%s\t",inst);
259         else
260             sprintf(lb,"%s",inst);
261         vsprintf(lb+(strlen(lb)),fmt,ap);
262     }  else
263         vsprintf(lb,fmt,ap);
264
265     while (isspace(*lbp)) lbp++;
266
267     if (lbp && *lbp) 
268         lineCurr = (lineCurr ?
269                     connectLine(lineCurr,newLineNode(lb)) :
270                     (lineHead = newLineNode(lb)));
271     lineCurr->isInline = _G.inLine;
272     lineCurr->isDebug  = _G.debugLine;
273
274 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
275
276     if(pic16_debug_verbose)
277       pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
278
279     va_end(ap);
280 }
281
282
283 /*-----------------------------------------------------------------*/
284 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
285 /*-----------------------------------------------------------------*/
286 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
287 {
288     bool r0iu = FALSE , r1iu = FALSE;
289     bool r0ou = FALSE , r1ou = FALSE;
290
291         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
292
293     /* the logic: if r0 & r1 used in the instruction
294     then we are in trouble otherwise */
295
296     /* first check if r0 & r1 are used by this
297     instruction, in which case we are in trouble */
298     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
299         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
300     {
301         goto endOfWorld;      
302     }
303
304     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
305     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
306
307     /* if no usage of r0 then return it */
308     if (!r0iu && !r0ou) {
309         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
310         (*aopp)->type = AOP_R0;
311         
312         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
313     }
314
315     /* if no usage of r1 then return it */
316     if (!r1iu && !r1ou) {
317         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
318         (*aopp)->type = AOP_R1;
319
320         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
321     }    
322
323     /* now we know they both have usage */
324     /* if r0 not used in this instruction */
325     if (!r0iu) {
326         /* push it if not already pushed */
327         if (!_G.r0Pushed) {
328           //pic16_emitcode ("push","%s",
329           //          pic16_regWithIdx(R0_IDX)->dname);
330             _G.r0Pushed++ ;
331         }
332         
333         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
334         (*aopp)->type = AOP_R0;
335
336         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
337     }
338
339     /* if r1 not used then */
340
341     if (!r1iu) {
342         /* push it if not already pushed */
343         if (!_G.r1Pushed) {
344           //pic16_emitcode ("push","%s",
345           //          pic16_regWithIdx(R1_IDX)->dname);
346             _G.r1Pushed++ ;
347         }
348         
349         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
350         (*aopp)->type = AOP_R1;
351         return pic16_regWithIdx(R1_IDX);
352     }
353
354 endOfWorld :
355     /* I said end of world but not quite end of world yet */
356     /* if this is a result then we can push it on the stack*/
357     if (result) {
358         (*aopp)->type = AOP_STK;    
359         return NULL;
360     }
361
362     /* other wise this is true end of the world */
363     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
364            "getFreePtr should never reach here");
365     exit(0);
366 }
367
368 /*-----------------------------------------------------------------*/
369 /* newAsmop - creates a new asmOp                                  */
370 /*-----------------------------------------------------------------*/
371 static asmop *newAsmop (short type)
372 {
373     asmop *aop;
374
375     aop = Safe_calloc(1,sizeof(asmop));
376     aop->type = type;
377     return aop;
378 }
379
380 static void genSetDPTR(int n)
381 {
382     if (!n)
383     {
384         pic16_emitcode(";", "Select standard DPTR");
385         pic16_emitcode("mov", "dps, #0x00");
386     }
387     else
388     {
389         pic16_emitcode(";", "Select alternate DPTR");
390         pic16_emitcode("mov", "dps, #0x01");
391     }
392 }
393
394 /*-----------------------------------------------------------------*/
395 /* resolveIfx - converts an iCode ifx into a form more useful for  */
396 /*              generating code                                    */
397 /*-----------------------------------------------------------------*/
398 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
399 {
400   if(!resIfx) 
401     return;
402
403   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
404
405   resIfx->condition = 1;    /* assume that the ifx is true */
406   resIfx->generated = 0;    /* indicate that the ifx has not been used */
407
408   if(!ifx) {
409     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
410 /*
411     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
412                         __FUNCTION__,__LINE__,resIfx->lbl->key);
413 */
414   } else {
415     if(IC_TRUE(ifx)) {
416       resIfx->lbl = IC_TRUE(ifx);
417     } else {
418       resIfx->lbl = IC_FALSE(ifx);
419       resIfx->condition = 0;
420     }
421 /*
422     if(IC_TRUE(ifx)) 
423       DEBUGpic16_emitcode("; ***","ifx true is non-null");
424     if(IC_FALSE(ifx)) 
425       DEBUGpic16_emitcode("; ***","ifx false is non-null");
426 */
427   }
428
429   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
430
431 }
432 /*-----------------------------------------------------------------*/
433 /* pointerCode - returns the code for a pointer type               */
434 /*-----------------------------------------------------------------*/
435 static int pointerCode (sym_link *etype)
436 {
437
438     return PTR_TYPE(SPEC_OCLS(etype));
439
440 }
441
442 /*-----------------------------------------------------------------*/
443 /* aopForSym - for a true symbol                                   */
444 /*-----------------------------------------------------------------*/
445 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
446 {
447     asmop *aop;
448     memmap *space= SPEC_OCLS(sym->etype);
449
450     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
451     /* if already has one */
452     if (sym->aop) {
453             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
454         return sym->aop;
455     }
456
457     /* assign depending on the storage class */
458     /* if it is on the stack or indirectly addressable */
459     /* space we need to assign either r0 or r1 to it   */    
460     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
461         sym->aop = aop = newAsmop(0);
462         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
463         aop->size = getSize(sym->type);
464
465         /* now assign the address of the variable to 
466         the pointer register */
467         if (aop->type != AOP_STK) {
468
469             if (sym->onStack) {
470                     if ( _G.accInUse )
471                         pic16_emitcode("push","acc");
472
473                     pic16_emitcode("mov","a,_bp");
474                     pic16_emitcode("add","a,#0x%02x",
475                              ((sym->stack < 0) ?
476                               ((char)(sym->stack - _G.nRegsSaved )) :
477                               ((char)sym->stack)) & 0xff);
478                     pic16_emitcode("mov","%s,a",
479                              aop->aopu.aop_ptr->name);
480
481                     if ( _G.accInUse )
482                         pic16_emitcode("pop","acc");
483             } else
484                 pic16_emitcode("mov","%s,#%s",
485                          aop->aopu.aop_ptr->name,
486                          sym->rname);
487             aop->paged = space->paged;
488         } else
489             aop->aopu.aop_stk = sym->stack;
490         return aop;
491     }
492     
493     if (sym->onStack && options.stack10bit)
494     {
495         /* It's on the 10 bit stack, which is located in
496          * far data space.
497          */
498          
499       //DEBUGpic16_emitcode(";","%d",__LINE__);
500
501         if ( _G.accInUse )
502                 pic16_emitcode("push","acc");
503
504         pic16_emitcode("mov","a,_bp");
505         pic16_emitcode("add","a,#0x%02x",
506                  ((sym->stack < 0) ?
507                    ((char)(sym->stack - _G.nRegsSaved )) :
508                    ((char)sym->stack)) & 0xff);
509         
510         genSetDPTR(1);
511         pic16_emitcode ("mov","dpx1,#0x40");
512         pic16_emitcode ("mov","dph1,#0x00");
513         pic16_emitcode ("mov","dpl1, a");
514         genSetDPTR(0);
515         
516         if ( _G.accInUse )
517             pic16_emitcode("pop","acc");
518             
519         sym->aop = aop = newAsmop(AOP_DPTR2);
520         aop->size = getSize(sym->type); 
521         return aop;
522     }
523
524     //DEBUGpic16_emitcode(";","%d",__LINE__);
525     /* if in bit space */
526     if (IN_BITSPACE(space)) {
527         sym->aop = aop = newAsmop (AOP_CRY);
528         aop->aopu.aop_dir = sym->rname ;
529         aop->size = getSize(sym->type);
530         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
531         return aop;
532     }
533     /* if it is in direct space */
534     if (IN_DIRSPACE(space)) {
535         sym->aop = aop = newAsmop (AOP_DIR);
536         aop->aopu.aop_dir = sym->rname ;
537         aop->size = getSize(sym->type);
538         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
539         return aop;
540     }
541
542     /* special case for a function */
543     if (IS_FUNC(sym->type)) {   
544         sym->aop = aop = newAsmop(AOP_IMMD);    
545         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
546         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
547         strcpy(aop->aopu.aop_immd,sym->rname);
548         aop->size = FPTRSIZE; 
549         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
550         return aop;
551     }
552
553
554     /* only remaining is far space */
555     /* in which case DPTR gets the address */
556     sym->aop = aop = newAsmop(AOP_PCODE);
557
558     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
559     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
560     PCOI(aop->aopu.pcop)->index = 0;
561
562     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
563                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
564
565     pic16_allocDirReg (IC_LEFT(ic));
566
567     aop->size = FPTRSIZE; 
568 /*
569     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
570     sym->aop = aop = newAsmop(AOP_DPTR);
571     pic16_emitcode ("mov","dptr,#%s", sym->rname);
572     aop->size = getSize(sym->type);
573
574     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
575 */
576
577     /* if it is in code space */
578     if (IN_CODESPACE(space))
579         aop->code = 1;
580
581     return aop;     
582 }
583
584 /*-----------------------------------------------------------------*/
585 /* aopForRemat - rematerialzes an object                           */
586 /*-----------------------------------------------------------------*/
587 static asmop *aopForRemat (operand *op) // x symbol *sym)
588 {
589   symbol *sym = OP_SYMBOL(op);
590   iCode *ic = NULL;
591   asmop *aop = newAsmop(AOP_PCODE);
592   int val = 0;
593   int offset = 0;
594
595   ic = sym->rematiCode;
596
597   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
598   if(IS_OP_POINTER(op)) {
599     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
600   }
601   for (;;) {
602     if (ic->op == '+') {
603       val += (int) operandLitValue(IC_RIGHT(ic));
604     } else if (ic->op == '-') {
605       val -= (int) operandLitValue(IC_RIGHT(ic));
606     } else
607       break;
608         
609     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
610   }
611
612   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
613   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
614 #if 0
615   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616 #else
617   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
618 #endif
619   PCOI(aop->aopu.pcop)->index = val;
620
621   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
622                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
623 #if 0
624                       val, IS_PTR_CONST(operandType(op)));
625 #else
626                       val, IS_CODEPTR(operandType(op)));
627 #endif
628
629   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
630
631   pic16_allocDirReg (IC_LEFT(ic));
632
633   return aop;        
634 }
635
636 static int aopIdx (asmop *aop, int offset)
637 {
638   if(!aop)
639     return -1;
640
641   if(aop->type !=  AOP_REG)
642     return -2;
643         
644   return aop->aopu.aop_reg[offset]->rIdx;
645
646 }
647 /*-----------------------------------------------------------------*/
648 /* regsInCommon - two operands have some registers in common       */
649 /*-----------------------------------------------------------------*/
650 static bool regsInCommon (operand *op1, operand *op2)
651 {
652     symbol *sym1, *sym2;
653     int i;
654
655     /* if they have registers in common */
656     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
657         return FALSE ;
658
659     sym1 = OP_SYMBOL(op1);
660     sym2 = OP_SYMBOL(op2);
661
662     if (sym1->nRegs == 0 || sym2->nRegs == 0)
663         return FALSE ;
664
665     for (i = 0 ; i < sym1->nRegs ; i++) {
666         int j;
667         if (!sym1->regs[i])
668             continue ;
669
670         for (j = 0 ; j < sym2->nRegs ;j++ ) {
671             if (!sym2->regs[j])
672                 continue ;
673
674             if (sym2->regs[j] == sym1->regs[i])
675                 return TRUE ;
676         }
677     }
678
679     return FALSE ;
680 }
681
682 /*-----------------------------------------------------------------*/
683 /* operandsEqu - equivalent                                        */
684 /*-----------------------------------------------------------------*/
685 static bool operandsEqu ( operand *op1, operand *op2)
686 {
687     symbol *sym1, *sym2;
688
689     /* if they not symbols */
690     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
691         return FALSE;
692
693     sym1 = OP_SYMBOL(op1);
694     sym2 = OP_SYMBOL(op2);
695
696     /* if both are itemps & one is spilt
697        and the other is not then false */
698     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
699         sym1->isspilt != sym2->isspilt )
700         return FALSE ;
701
702     /* if they are the same */
703     if (sym1 == sym2)
704         return TRUE ;
705
706     if (strcmp(sym1->rname,sym2->rname) == 0)
707         return TRUE;
708
709
710     /* if left is a tmp & right is not */
711     if (IS_ITEMP(op1)  && 
712         !IS_ITEMP(op2) &&
713         sym1->isspilt  &&
714         (sym1->usl.spillLoc == sym2))
715         return TRUE;
716
717     if (IS_ITEMP(op2)  && 
718         !IS_ITEMP(op1) &&
719         sym2->isspilt  &&
720         sym1->level > 0 &&
721         (sym2->usl.spillLoc == sym1))
722         return TRUE ;
723
724     return FALSE ;
725 }
726
727 /*-----------------------------------------------------------------*/
728 /* pic16_sameRegs - two asmops have the same registers                   */
729 /*-----------------------------------------------------------------*/
730 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
731 {
732     int i;
733
734     if (aop1 == aop2)
735         return TRUE ;
736
737     if (aop1->type != AOP_REG ||
738         aop2->type != AOP_REG )
739         return FALSE ;
740
741     if (aop1->size != aop2->size )
742         return FALSE ;
743
744     for (i = 0 ; i < aop1->size ; i++ )
745         if (aop1->aopu.aop_reg[i] !=
746             aop2->aopu.aop_reg[i] )
747             return FALSE ;
748
749     return TRUE ;
750 }
751
752 /*-----------------------------------------------------------------*/
753 /* pic16_aopOp - allocates an asmop for an operand  :                    */
754 /*-----------------------------------------------------------------*/
755 void pic16_aopOp (operand *op, iCode *ic, bool result)
756 {
757     asmop *aop;
758     symbol *sym;
759     int i;
760
761     if (!op)
762         return ;
763
764         DEBUGpic16_emitcode(";","%d",__LINE__);
765     /* if this a literal */
766     if (IS_OP_LITERAL(op)) {
767         op->aop = aop = newAsmop(AOP_LIT);
768         aop->aopu.aop_lit = op->operand.valOperand;
769         aop->size = getSize(operandType(op));
770         return;
771     }
772
773     {
774       sym_link *type = operandType(op);
775 #if 0
776       if(IS_PTR_CONST(type))
777 #else
778       if(IS_CODEPTR(type))
779 #endif
780         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
781     }
782
783     /* if already has a asmop then continue */
784     if (op->aop)
785         return ;
786
787     /* if the underlying symbol has a aop */
788     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
789       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
790         op->aop = OP_SYMBOL(op)->aop;
791         return;
792     }
793
794     /* if this is a true symbol */
795     if (IS_TRUE_SYMOP(op)) {    
796         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
797       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
798       return ;
799     }
800
801     /* this is a temporary : this has
802     only four choices :
803     a) register
804     b) spillocation
805     c) rematerialize 
806     d) conditional   
807     e) can be a return use only */
808
809     sym = OP_SYMBOL(op);
810
811         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
812     /* if the type is a conditional */
813     if (sym->regType == REG_CND) {
814         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
815         aop->size = 0;
816         return;
817     }
818
819     /* if it is spilt then two situations
820     a) is rematerialize 
821     b) has a spill location */
822     if (sym->isspilt || sym->nRegs == 0) {
823
824       DEBUGpic16_emitcode(";","%d",__LINE__);
825         /* rematerialize it NOW */
826         if (sym->remat) {
827
828             sym->aop = op->aop = aop =
829                                       aopForRemat (op);
830             aop->size = getSize(sym->type);
831             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
832             return;
833         }
834
835         if (sym->accuse) {
836             int i;
837             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
838             aop->size = getSize(sym->type);
839             for ( i = 0 ; i < 2 ; i++ )
840                 aop->aopu.aop_str[i] = accUse[i];
841             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
842             return;  
843         }
844
845         if (sym->ruonly ) {
846           /*
847           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
848           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
849           //pic16_allocDirReg (IC_LEFT(ic));
850           aop->size = getSize(sym->type);
851           */
852
853           unsigned i;
854
855           aop = op->aop = sym->aop = newAsmop(AOP_STR);
856           aop->size = getSize(sym->type);
857           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
858             aop->aopu.aop_str[i] = fReturn[i];
859
860           DEBUGpic16_emitcode(";","%d",__LINE__);
861           return;
862         }
863
864         /* else spill location  */
865         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
866             /* force a new aop if sizes differ */
867             sym->usl.spillLoc->aop = NULL;
868         }
869         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
870                             __FUNCTION__,__LINE__,
871                             sym->usl.spillLoc->rname,
872                             sym->rname, sym->usl.spillLoc->offset);
873
874         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
875         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
876         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
877                                           getSize(sym->type), 
878                                           sym->usl.spillLoc->offset);
879         aop->size = getSize(sym->type);
880
881         return;
882     }
883
884     {
885       sym_link *type = operandType(op);
886 #if 0
887       if(IS_PTR_CONST(type)) 
888 #else
889       if(IS_CODEPTR(type)) 
890 #endif
891         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
892     }
893
894     /* must be in a register */
895     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
896     sym->aop = op->aop = aop = newAsmop(AOP_REG);
897     aop->size = sym->nRegs;
898     for ( i = 0 ; i < sym->nRegs ;i++)
899         aop->aopu.aop_reg[i] = sym->regs[i];
900 }
901
902 /*-----------------------------------------------------------------*/
903 /* pic16_freeAsmop - free up the asmop given to an operand               */
904 /*----------------------------------------------------------------*/
905 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
906 {   
907     asmop *aop ;
908
909     if (!op)
910         aop = aaop;
911     else 
912         aop = op->aop;
913
914     if (!aop)
915         return ;
916
917     if (aop->freed)
918         goto dealloc; 
919
920     aop->freed = 1;
921
922     /* depending on the asmop type only three cases need work AOP_RO
923        , AOP_R1 && AOP_STK */
924 #if 0
925     switch (aop->type) {
926         case AOP_R0 :
927             if (_G.r0Pushed ) {
928                 if (pop) {
929                     pic16_emitcode ("pop","ar0");     
930                     _G.r0Pushed--;
931                 }
932             }
933             bitVectUnSetBit(ic->rUsed,R0_IDX);
934             break;
935
936         case AOP_R1 :
937             if (_G.r1Pushed ) {
938                 if (pop) {
939                     pic16_emitcode ("pop","ar1");
940                     _G.r1Pushed--;
941                 }
942             }
943             bitVectUnSetBit(ic->rUsed,R1_IDX);          
944             break;
945
946         case AOP_STK :
947         {
948             int sz = aop->size;    
949             int stk = aop->aopu.aop_stk + aop->size;
950             bitVectUnSetBit(ic->rUsed,R0_IDX);
951             bitVectUnSetBit(ic->rUsed,R1_IDX);          
952
953             getFreePtr(ic,&aop,FALSE);
954             
955             if (options.stack10bit)
956             {
957                 /* I'm not sure what to do here yet... */
958                 /* #STUB */
959                 fprintf(stderr, 
960                         "*** Warning: probably generating bad code for "
961                         "10 bit stack mode.\n");
962             }
963             
964             if (stk) {
965                 pic16_emitcode ("mov","a,_bp");
966                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
967                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
968             } else {
969                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
970             }
971
972             while (sz--) {
973                 pic16_emitcode("pop","acc");
974                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
975                 if (!sz) break;
976                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
977             }
978             op->aop = aop;
979             pic16_freeAsmop(op,NULL,ic,TRUE);
980             if (_G.r0Pushed) {
981                 pic16_emitcode("pop","ar0");
982                 _G.r0Pushed--;
983             }
984
985             if (_G.r1Pushed) {
986                 pic16_emitcode("pop","ar1");
987                 _G.r1Pushed--;
988             }       
989         }
990     }
991 #endif
992
993 dealloc:
994     /* all other cases just dealloc */
995     if (op ) {
996         op->aop = NULL;
997         if (IS_SYMOP(op)) {
998             OP_SYMBOL(op)->aop = NULL;    
999             /* if the symbol has a spill */
1000             if (SPIL_LOC(op))
1001                 SPIL_LOC(op)->aop = NULL;
1002         }
1003     }
1004 }
1005
1006 /*-----------------------------------------------------------------*/
1007 /* pic16_aopGet - for fetching value of the aop                          */
1008 /*-----------------------------------------------------------------*/
1009 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1010 {
1011     char *s = buffer ;
1012     char *rs;
1013
1014     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1015     /* offset is greater than
1016     size then zero */
1017     if (offset > (aop->size - 1) &&
1018         aop->type != AOP_LIT)
1019         return zero;
1020
1021     /* depending on type */
1022     switch (aop->type) {
1023         
1024     case AOP_R0:
1025     case AOP_R1:
1026         DEBUGpic16_emitcode(";","%d",__LINE__);
1027         /* if we need to increment it */       
1028         while (offset > aop->coff) {        
1029             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1030             aop->coff++;
1031         }
1032         
1033         while (offset < aop->coff) {
1034             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1035             aop->coff--;
1036         }
1037         
1038         aop->coff = offset ;
1039         if (aop->paged) {
1040             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1041             return (dname ? "acc" : "a");
1042         }       
1043         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1044         rs = Safe_calloc(1,strlen(s)+1);
1045         strcpy(rs,s);   
1046         return rs;
1047         
1048     case AOP_DPTR:
1049     case AOP_DPTR2:
1050         DEBUGpic16_emitcode(";","%d",__LINE__);
1051     if (aop->type == AOP_DPTR2)
1052     {
1053         genSetDPTR(1);
1054     }
1055     
1056         while (offset > aop->coff) {
1057             pic16_emitcode ("inc","dptr");
1058             aop->coff++;
1059         }
1060         
1061         while (offset < aop->coff) {        
1062             pic16_emitcode("lcall","__decdptr");
1063             aop->coff--;
1064         }
1065         
1066         aop->coff = offset;
1067         if (aop->code) {
1068             pic16_emitcode("clr","a");
1069             pic16_emitcode("movc","a,@a+dptr");
1070         }
1071     else {
1072             pic16_emitcode("movx","a,@dptr");
1073     }
1074             
1075     if (aop->type == AOP_DPTR2)
1076     {
1077         genSetDPTR(0);
1078     }
1079             
1080     return (dname ? "acc" : "a");
1081         
1082         
1083     case AOP_IMMD:
1084         if (bit16) 
1085             sprintf (s,"%s",aop->aopu.aop_immd);
1086         else
1087             if (offset) 
1088                 sprintf(s,"(%s >> %d)",
1089                         aop->aopu.aop_immd,
1090                         offset*8);
1091             else
1092                 sprintf(s,"%s",
1093                         aop->aopu.aop_immd);
1094         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1095         rs = Safe_calloc(1,strlen(s)+1);
1096         strcpy(rs,s);   
1097         return rs;
1098         
1099     case AOP_DIR:
1100       if (offset) {
1101         sprintf(s,"(%s + %d)",
1102                 aop->aopu.aop_dir,
1103                 offset);
1104         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1105       } else
1106             sprintf(s,"%s",aop->aopu.aop_dir);
1107         rs = Safe_calloc(1,strlen(s)+1);
1108         strcpy(rs,s);   
1109         return rs;
1110         
1111     case AOP_REG:
1112       //if (dname) 
1113       //    return aop->aopu.aop_reg[offset]->dname;
1114       //else
1115             return aop->aopu.aop_reg[offset]->name;
1116         
1117     case AOP_CRY:
1118       //pic16_emitcode(";","%d",__LINE__);
1119       return aop->aopu.aop_dir;
1120         
1121     case AOP_ACC:
1122         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1123         return "AOP_accumulator_bug";
1124
1125     case AOP_LIT:
1126         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1127         rs = Safe_calloc(1,strlen(s)+1);
1128         strcpy(rs,s);   
1129         return rs;
1130         
1131     case AOP_STR:
1132         aop->coff = offset ;
1133         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1134             dname)
1135             return "acc";
1136         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1137         
1138         return aop->aopu.aop_str[offset];
1139         
1140     case AOP_PCODE:
1141       {
1142         pCodeOp *pcop = aop->aopu.pcop;
1143         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1144         if(pcop->name) {
1145           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1146           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1147           sprintf(s,"%s", pcop->name);
1148         } else
1149           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1150
1151       }
1152       rs = Safe_calloc(1,strlen(s)+1);
1153       strcpy(rs,s);   
1154       return rs;
1155
1156     }
1157
1158     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1159            "aopget got unsupported aop->type");
1160     exit(0);
1161 }
1162
1163
1164 /*-----------------------------------------------------------------*/
1165 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1166 /*-----------------------------------------------------------------*/
1167 pCodeOp *pic16_popGetTempReg(void)
1168 {
1169
1170   pCodeOp *pcop;
1171
1172   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1173   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1174     PCOR(pcop)->r->wasUsed=1;
1175     PCOR(pcop)->r->isFree=0;
1176   }
1177
1178   return pcop;
1179 }
1180
1181 /*-----------------------------------------------------------------*/
1182 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1183 /*-----------------------------------------------------------------*/
1184 void pic16_popReleaseTempReg(pCodeOp *pcop)
1185 {
1186
1187   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1188     PCOR(pcop)->r->isFree = 1;
1189
1190 }
1191 /*-----------------------------------------------------------------*/
1192 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1193 /*-----------------------------------------------------------------*/
1194 pCodeOp *pic16_popGetLabel(unsigned int key)
1195 {
1196
1197   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1198
1199   if(key>max_key)
1200     max_key = key;
1201
1202   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1203 }
1204
1205 /*-----------------------------------------------------------------*/
1206 /* pic16_popCopyReg - copy a pcode operator                              */
1207 /*-----------------------------------------------------------------*/
1208 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1209 {
1210   pCodeOpReg *pcor;
1211
1212   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1213   pcor->pcop.type = pc->pcop.type;
1214   if(pc->pcop.name) {
1215     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1216       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1217   } else
1218     pcor->pcop.name = NULL;
1219
1220   pcor->r = pc->r;
1221   pcor->rIdx = pc->rIdx;
1222   pcor->r->wasUsed=1;
1223
1224   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1225
1226   return PCOP(pcor);
1227 }
1228 /*-----------------------------------------------------------------*/
1229 /* pic16_popGet - asm operator to pcode operator conversion              */
1230 /*-----------------------------------------------------------------*/
1231 pCodeOp *pic16_popGetLit(unsigned int lit)
1232 {
1233
1234   return pic16_newpCodeOpLit(lit);
1235 }
1236
1237
1238 /*-----------------------------------------------------------------*/
1239 /* pic16_popGetImmd - asm operator to pcode immediate conversion         */
1240 /*-----------------------------------------------------------------*/
1241 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1242 {
1243
1244   return pic16_newpCodeOpImmd(name, offset,index, 0);
1245 }
1246
1247
1248 /*-----------------------------------------------------------------*/
1249 /* pic16_popGet - asm operator to pcode operator conversion              */
1250 /*-----------------------------------------------------------------*/
1251 pCodeOp *pic16_popGetWithString(char *str)
1252 {
1253   pCodeOp *pcop;
1254
1255
1256   if(!str) {
1257     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1258     exit (1);
1259   }
1260
1261   pcop = pic16_newpCodeOp(str,PO_STR);
1262
1263   return pcop;
1264 }
1265
1266 /*-----------------------------------------------------------------*/
1267 /* pic16_popRegFromString -                                        */
1268 /*-----------------------------------------------------------------*/
1269 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1270 {
1271
1272   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1273   pcop->type = PO_DIR;
1274
1275   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1276 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1277
1278   if(!str)
1279     str = "BAD_STRING";
1280
1281   pcop->name = Safe_calloc(1,strlen(str)+1);
1282   strcpy(pcop->name,str);
1283
1284   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1285
1286   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1287   if(PCOR(pcop)->r == NULL) {
1288     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1289     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1290
1291         //fprintf(stderr, "allocating new register -> %s\n", str);
1292
1293     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1294   } else {
1295     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1296   }
1297   PCOR(pcop)->instance = offset;
1298
1299   return pcop;
1300 }
1301
1302 static pCodeOp *popRegFromIdx(int rIdx)
1303 {
1304   pCodeOp *pcop;
1305
1306   DEBUGpic16_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1307                        __FUNCTION__,__LINE__,rIdx);
1308
1309   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1310
1311   PCOR(pcop)->rIdx = rIdx;
1312   PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1313   PCOR(pcop)->r->isFree = 0;
1314   PCOR(pcop)->r->wasUsed = 1;
1315
1316   pcop->type = PCOR(pcop)->r->pc_type;
1317
1318
1319   return pcop;
1320 }
1321
1322 /*---------------------------------------------------------------------------------*/
1323 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1324 /*                 VR 030601                                                       */
1325 /*---------------------------------------------------------------------------------*/
1326 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1327 {
1328   pCodeOpReg2 *pcop2;
1329   pCodeOp *temp;
1330   
1331         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1332         temp = pic16_popGet(aop_dst, offset);
1333         pcop2->pcop2 = temp;
1334         
1335   return PCOP(pcop2);
1336 }
1337
1338
1339 /*-----------------------------------------------------------------*/
1340 /* pic16_popGet - asm operator to pcode operator conversion              */
1341 /*-----------------------------------------------------------------*/
1342 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1343 {
1344   //char *s = buffer ;
1345     //char *rs;
1346
1347     pCodeOp *pcop;
1348
1349     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1350     /* offset is greater than
1351     size then zero */
1352
1353     if (offset > (aop->size - 1) &&
1354         aop->type != AOP_LIT)
1355       return NULL;  //zero;
1356
1357     /* depending on type */
1358     switch (aop->type) {
1359         
1360     case AOP_R0:
1361     case AOP_R1:
1362     case AOP_DPTR:
1363     case AOP_DPTR2:
1364     case AOP_ACC:
1365         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1366         return NULL;
1367         
1368     case AOP_IMMD:
1369       DEBUGpic16_emitcode(";","%d",__LINE__);
1370       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1371
1372     case AOP_DIR:
1373       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1374
1375 #if 0
1376         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1377         pcop->type = PO_DIR;
1378
1379         /*
1380         if (offset)
1381             sprintf(s,"(%s + %d)",
1382                     aop->aopu.aop_dir,
1383                     offset);
1384         else
1385             sprintf(s,"%s",aop->aopu.aop_dir);
1386         pcop->name = Safe_calloc(1,strlen(s)+1);
1387         strcpy(pcop->name,s);   
1388         */
1389         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1390         strcpy(pcop->name,aop->aopu.aop_dir);   
1391         PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1392         if(PCOR(pcop)->r == NULL) {
1393           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1394           PCOR(pcop)->r = pic16_allocRegByName (aop->aopu.aop_dir,aop->size);
1395           DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1396         } else {
1397           DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1398         }
1399         PCOR(pcop)->instance = offset;
1400
1401         return pcop;
1402 #endif
1403         
1404     case AOP_REG:
1405       {
1406         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1407
1408         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1409         PCOR(pcop)->rIdx = rIdx;
1410         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1411         PCOR(pcop)->r->wasUsed=1;
1412         PCOR(pcop)->r->isFree=0;
1413
1414         PCOR(pcop)->instance = offset;
1415         pcop->type = PCOR(pcop)->r->pc_type;
1416         //rs = aop->aopu.aop_reg[offset]->name;
1417         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1418         return pcop;
1419       }
1420
1421     case AOP_CRY:
1422       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1423       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1424       //if(PCOR(pcop)->r == NULL)
1425       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1426       return pcop;
1427         
1428     case AOP_LIT:
1429       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1430
1431     case AOP_STR:
1432       DEBUGpic16_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1433       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1434       /*
1435       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1436       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1437       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1438       pcop->type = PCOR(pcop)->r->pc_type;
1439       pcop->name = PCOR(pcop)->r->name;
1440
1441       return pcop;
1442       */
1443
1444     case AOP_PCODE:
1445       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1446                           __LINE__, 
1447                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1448       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1449       PCOI(pcop)->offset = offset;
1450       return pcop;
1451     }
1452
1453     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1454            "pic16_popGet got unsupported aop->type");
1455     exit(0);
1456 }
1457 /*-----------------------------------------------------------------*/
1458 /* pic16_aopPut - puts a string for a aop                                */
1459 /*-----------------------------------------------------------------*/
1460 void pic16_aopPut (asmop *aop, char *s, int offset)
1461 {
1462     char *d = buffer ;
1463     symbol *lbl ;
1464
1465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1466
1467     if (aop->size && offset > ( aop->size - 1)) {
1468         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1469                "pic16_aopPut got offset > aop->size");
1470         exit(0);
1471     }
1472
1473     /* will assign value to value */
1474     /* depending on where it is ofcourse */
1475     switch (aop->type) {
1476     case AOP_DIR:
1477       if (offset) {
1478         sprintf(d,"(%s + %d)",
1479                 aop->aopu.aop_dir,offset);
1480         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1481
1482       } else
1483             sprintf(d,"%s",aop->aopu.aop_dir);
1484         
1485         if (strcmp(d,s)) {
1486           DEBUGpic16_emitcode(";","%d",__LINE__);
1487           if(strcmp(s,"W"))
1488             pic16_emitcode("movf","%s,w",s);
1489           pic16_emitcode("movwf","%s",d);
1490
1491           if(strcmp(s,"W")) {
1492             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1493             if(offset >= aop->size) {
1494               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1495               break;
1496             } else
1497               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1498           }
1499
1500           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1501
1502
1503         }
1504         break;
1505         
1506     case AOP_REG:
1507       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1508         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1509           /*
1510             if (*s == '@'           ||
1511                 strcmp(s,"r0") == 0 ||
1512                 strcmp(s,"r1") == 0 ||
1513                 strcmp(s,"r2") == 0 ||
1514                 strcmp(s,"r3") == 0 ||
1515                 strcmp(s,"r4") == 0 ||
1516                 strcmp(s,"r5") == 0 ||
1517                 strcmp(s,"r6") == 0 || 
1518                 strcmp(s,"r7") == 0 )
1519                 pic16_emitcode("mov","%s,%s  ; %d",
1520                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1521             else
1522           */
1523
1524           if(strcmp(s,"W")==0 )
1525             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1526
1527           pic16_emitcode("movwf","%s",
1528                    aop->aopu.aop_reg[offset]->name);
1529
1530           if(strcmp(s,zero)==0) {
1531             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1532
1533           } else if(strcmp(s,"W")==0) {
1534             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1535             pcop->type = PO_GPR_REGISTER;
1536
1537             PCOR(pcop)->rIdx = -1;
1538             PCOR(pcop)->r = NULL;
1539
1540             DEBUGpic16_emitcode(";","%d",__LINE__);
1541             pcop->name = Safe_strdup(s);
1542             pic16_emitpcode(POC_MOVFW,pcop);
1543             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1544           } else if(strcmp(s,one)==0) {
1545             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1546             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1547           } else {
1548             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1549           }
1550         }
1551         break;
1552         
1553     case AOP_DPTR:
1554     case AOP_DPTR2:
1555     
1556     if (aop->type == AOP_DPTR2)
1557     {
1558         genSetDPTR(1);
1559     }
1560     
1561         if (aop->code) {
1562             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1563                    "pic16_aopPut writting to code space");
1564             exit(0);
1565         }
1566         
1567         while (offset > aop->coff) {
1568             aop->coff++;
1569             pic16_emitcode ("inc","dptr");
1570         }
1571         
1572         while (offset < aop->coff) {
1573             aop->coff-- ;
1574             pic16_emitcode("lcall","__decdptr");
1575         }
1576         
1577         aop->coff = offset;
1578         
1579         /* if not in accumulater */
1580         MOVA(s);        
1581         
1582         pic16_emitcode ("movx","@dptr,a");
1583         
1584     if (aop->type == AOP_DPTR2)
1585     {
1586         genSetDPTR(0);
1587     }
1588         break;
1589         
1590     case AOP_R0:
1591     case AOP_R1:
1592         while (offset > aop->coff) {
1593             aop->coff++;
1594             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1595         }
1596         while (offset < aop->coff) {
1597             aop->coff-- ;
1598             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1599         }
1600         aop->coff = offset;
1601         
1602         if (aop->paged) {
1603             MOVA(s);           
1604             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1605             
1606         } else
1607             if (*s == '@') {
1608                 MOVA(s);
1609                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1610             } else
1611                 if (strcmp(s,"r0") == 0 ||
1612                     strcmp(s,"r1") == 0 ||
1613                     strcmp(s,"r2") == 0 ||
1614                     strcmp(s,"r3") == 0 ||
1615                     strcmp(s,"r4") == 0 ||
1616                     strcmp(s,"r5") == 0 ||
1617                     strcmp(s,"r6") == 0 || 
1618                     strcmp(s,"r7") == 0 ) {
1619                     char buffer[10];
1620                     sprintf(buffer,"a%s",s);
1621                     pic16_emitcode("mov","@%s,%s",
1622                              aop->aopu.aop_ptr->name,buffer);
1623                 } else
1624                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1625         
1626         break;
1627         
1628     case AOP_STK:
1629         if (strcmp(s,"a") == 0)
1630             pic16_emitcode("push","acc");
1631         else
1632             pic16_emitcode("push","%s",s);
1633         
1634         break;
1635         
1636     case AOP_CRY:
1637         /* if bit variable */
1638         if (!aop->aopu.aop_dir) {
1639             pic16_emitcode("clr","a");
1640             pic16_emitcode("rlc","a");
1641         } else {
1642             if (s == zero) 
1643                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1644             else
1645                 if (s == one)
1646                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1647                 else
1648                     if (!strcmp(s,"c"))
1649                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1650                     else {
1651                         lbl = newiTempLabel(NULL);
1652                         
1653                         if (strcmp(s,"a")) {
1654                             MOVA(s);
1655                         }
1656                         pic16_emitcode("clr","c");
1657                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1658                         pic16_emitcode("cpl","c");
1659                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1660                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1661                     }
1662         }
1663         break;
1664         
1665     case AOP_STR:
1666         aop->coff = offset;
1667         if (strcmp(aop->aopu.aop_str[offset],s))
1668             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1669         break;
1670         
1671     case AOP_ACC:
1672         aop->coff = offset;
1673         if (!offset && (strcmp(s,"acc") == 0))
1674             break;
1675         
1676         if (strcmp(aop->aopu.aop_str[offset],s))
1677             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1678         break;
1679
1680     default :
1681         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1682                "pic16_aopPut got unsupported aop->type");
1683         exit(0);    
1684     }    
1685
1686 }
1687
1688 /*-----------------------------------------------------------------*/
1689 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1690 /*-----------------------------------------------------------------*/
1691 static void mov2w (asmop *aop, int offset)
1692 {
1693
1694   if(!aop)
1695     return;
1696
1697   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1698
1699   if ( aop->type == AOP_PCODE ||
1700        aop->type == AOP_LIT )
1701     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1702   else
1703     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1704
1705 }
1706
1707 /*-----------------------------------------------------------------*/
1708 /* reAdjustPreg - points a register back to where it should        */
1709 /*-----------------------------------------------------------------*/
1710 static void reAdjustPreg (asmop *aop)
1711 {
1712     int size ;
1713
1714     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1715     aop->coff = 0;
1716     if ((size = aop->size) <= 1)
1717         return ;
1718     size-- ;
1719     switch (aop->type) {
1720         case AOP_R0 :
1721         case AOP_R1 :
1722             while (size--)
1723                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1724             break;          
1725         case AOP_DPTR :
1726         case AOP_DPTR2:
1727             if (aop->type == AOP_DPTR2)
1728             {
1729                 genSetDPTR(1);
1730             } 
1731             while (size--)
1732             {
1733                 pic16_emitcode("lcall","__decdptr");
1734             }
1735                 
1736             if (aop->type == AOP_DPTR2)
1737             {
1738                 genSetDPTR(0);
1739             }                
1740             break;  
1741
1742     }   
1743
1744 }
1745
1746
1747 #if 0
1748 /*-----------------------------------------------------------------*/
1749 /* opIsGptr: returns non-zero if the passed operand is             */   
1750 /* a generic pointer type.                                         */
1751 /*-----------------------------------------------------------------*/ 
1752 static int opIsGptr(operand *op)
1753 {
1754     sym_link *type = operandType(op);
1755     
1756     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1757     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1758     {
1759         return 1;
1760     }
1761     return 0;        
1762 }
1763 #endif
1764
1765 /*-----------------------------------------------------------------*/
1766 /* pic16_getDataSize - get the operand data size                         */
1767 /*-----------------------------------------------------------------*/
1768 int pic16_getDataSize(operand *op)
1769 {
1770     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1771
1772
1773     return AOP_SIZE(op);
1774
1775     // tsd- in the pic port, the genptr size is 1, so this code here
1776     // fails. ( in the 8051 port, the size was 4).
1777 #if 0
1778     int size;
1779     size = AOP_SIZE(op);
1780     if (size == GPTRSIZE)
1781     {
1782         sym_link *type = operandType(op);
1783         if (IS_GENPTR(type))
1784         {
1785             /* generic pointer; arithmetic operations
1786              * should ignore the high byte (pointer type).
1787              */
1788             size--;
1789     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1790         }
1791     }
1792     return size;
1793 #endif
1794 }
1795
1796 /*-----------------------------------------------------------------*/
1797 /* pic16_outAcc - output Acc                                             */
1798 /*-----------------------------------------------------------------*/
1799 void pic16_outAcc(operand *result)
1800 {
1801   int size,offset;
1802   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1803   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1804
1805
1806   size = pic16_getDataSize(result);
1807   if(size){
1808     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1809     size--;
1810     offset = 1;
1811     /* unsigned or positive */
1812     while(size--)
1813       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1814   }
1815
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* pic16_outBitC - output a bit C                                        */
1820 /*-----------------------------------------------------------------*/
1821 void pic16_outBitC(operand *result)
1822 {
1823
1824     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1825     /* if the result is bit */
1826     if (AOP_TYPE(result) == AOP_CRY) 
1827         pic16_aopPut(AOP(result),"c",0);
1828     else {
1829         pic16_emitcode("clr","a  ; %d", __LINE__);
1830         pic16_emitcode("rlc","a");
1831         pic16_outAcc(result);
1832     }
1833 }
1834
1835 /*-----------------------------------------------------------------*/
1836 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1837 /*-----------------------------------------------------------------*/
1838 void pic16_toBoolean(operand *oper)
1839 {
1840     int size = AOP_SIZE(oper) - 1;
1841     int offset = 1;
1842
1843     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1844
1845     if ( AOP_TYPE(oper) != AOP_ACC) {
1846       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1847     }
1848     while (size--) {
1849       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1850     }
1851 }
1852
1853
1854 /*-----------------------------------------------------------------*/
1855 /* genNot - generate code for ! operation                          */
1856 /*-----------------------------------------------------------------*/
1857 static void genNot (iCode *ic)
1858 {
1859   symbol *tlbl;
1860   int size;
1861
1862   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1863   /* assign asmOps to operand & result */
1864   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1865   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1866
1867   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1868   /* if in bit space then a special case */
1869   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1870     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1871       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1872       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1873     } else {
1874       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1875       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1876       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1877     }
1878     goto release;
1879   }
1880
1881   size = AOP_SIZE(IC_LEFT(ic));
1882   if(size == 1) {
1883     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1884     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1885     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1886     goto release;
1887   }
1888   pic16_toBoolean(IC_LEFT(ic));
1889
1890   tlbl = newiTempLabel(NULL);
1891   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1892   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1893   pic16_outBitC(IC_RESULT(ic));
1894
1895  release:    
1896   /* release the aops */
1897   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1898   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1899 }
1900
1901
1902 /*-----------------------------------------------------------------*/
1903 /* genCpl - generate code for complement                           */
1904 /*-----------------------------------------------------------------*/
1905 static void genCpl (iCode *ic)
1906 {
1907     int offset = 0;
1908     int size ;
1909
1910
1911     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1912     /* assign asmOps to operand & result */
1913     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1914     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1915
1916     /* if both are in bit space then 
1917     a special case */
1918     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1919         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1920
1921         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1922         pic16_emitcode("cpl","c"); 
1923         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1924         goto release; 
1925     } 
1926
1927     size = AOP_SIZE(IC_RESULT(ic));
1928     while (size--) {
1929 /*
1930         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1931         MOVA(l);       
1932         pic16_emitcode("cpl","a");
1933         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1934 */
1935         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1936               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
1937         } else {
1938                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
1939                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1940         }
1941         offset++;
1942
1943     }
1944
1945
1946 release:
1947     /* release the aops */
1948     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1949     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1950 }
1951
1952 /*-----------------------------------------------------------------*/
1953 /* genUminusFloat - unary minus for floating points                */
1954 /*-----------------------------------------------------------------*/
1955 static void genUminusFloat(operand *op,operand *result)
1956 {
1957     int size ,offset =0 ;
1958     char *l;
1959
1960     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1961     /* for this we just need to flip the 
1962     first it then copy the rest in place */
1963     size = AOP_SIZE(op) - 1;
1964     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
1965
1966     MOVA(l);    
1967
1968     pic16_emitcode("cpl","acc.7");
1969     pic16_aopPut(AOP(result),"a",3);    
1970
1971     while(size--) {
1972         pic16_aopPut(AOP(result),
1973                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
1974                offset);
1975         offset++;
1976     }          
1977 }
1978
1979 /*-----------------------------------------------------------------*/
1980 /* genUminus - unary minus code generation                         */
1981 /*-----------------------------------------------------------------*/
1982 static void genUminus (iCode *ic)
1983 {
1984   int size, i;
1985   sym_link *optype, *rtype;
1986
1987
1988   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1989   /* assign asmops */
1990   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
1991   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
1992
1993   /* if both in bit space then special
1994      case */
1995   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1996       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1997
1998     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1999     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2000     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2001
2002     goto release; 
2003   } 
2004
2005   optype = operandType(IC_LEFT(ic));
2006   rtype = operandType(IC_RESULT(ic));
2007
2008   /* if float then do float stuff */
2009   if (IS_FLOAT(optype)) {
2010     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2011     goto release;
2012   }
2013
2014   /* otherwise subtract from zero by taking the 2's complement */
2015   size = AOP_SIZE(IC_LEFT(ic));
2016
2017   for(i=0; i<size; i++) {
2018     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2019       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2020     else {
2021       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2023     }
2024   }
2025
2026   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2027   for(i=1; i<size; i++) {
2028     emitSKPNZ;
2029     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2030   }
2031
2032  release:
2033   /* release the aops */
2034   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2035   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2036 }
2037
2038 /*-----------------------------------------------------------------*/
2039 /* saveRegisters - will look for a call and save the registers     */
2040 /*-----------------------------------------------------------------*/
2041 static void saveRegisters(iCode *lic) 
2042 {
2043     int i;
2044     iCode *ic;
2045     bitVect *rsave;
2046     sym_link *dtype;
2047
2048     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2049     /* look for call */
2050     for (ic = lic ; ic ; ic = ic->next) 
2051         if (ic->op == CALL || ic->op == PCALL)
2052             break;
2053
2054     if (!ic) {
2055         fprintf(stderr,"found parameter push with no function call\n");
2056         return ;
2057     }
2058
2059     /* if the registers have been saved already then
2060     do nothing */
2061     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2062         return ;
2063
2064     /* find the registers in use at this time 
2065     and push them away to safety */
2066     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2067                           ic->rUsed);
2068
2069     ic->regsSaved = 1;
2070     if (options.useXstack) {
2071         if (bitVectBitValue(rsave,R0_IDX))
2072             pic16_emitcode("mov","b,r0");
2073         pic16_emitcode("mov","r0,%s",spname);
2074         for (i = 0 ; i < pic16_nRegs ; i++) {
2075             if (bitVectBitValue(rsave,i)) {
2076                 if (i == R0_IDX)
2077                     pic16_emitcode("mov","a,b");
2078                 else
2079                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2080                 pic16_emitcode("movx","@r0,a");
2081                 pic16_emitcode("inc","r0");
2082             }
2083         }
2084         pic16_emitcode("mov","%s,r0",spname);
2085         if (bitVectBitValue(rsave,R0_IDX))
2086             pic16_emitcode("mov","r0,b");           
2087     }// else
2088     //for (i = 0 ; i < pic16_nRegs ; i++) {
2089     //    if (bitVectBitValue(rsave,i))
2090     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2091     //}
2092
2093     dtype = operandType(IC_LEFT(ic));
2094     if (currFunc && dtype && 
2095         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2096         IFFUNC_ISISR(currFunc->type) &&
2097         !ic->bankSaved) 
2098
2099         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2100
2101 }
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers                      */
2104 /*-----------------------------------------------------------------*/
2105 static void unsaveRegisters (iCode *ic)
2106 {
2107     int i;
2108     bitVect *rsave;
2109
2110     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2111     /* find the registers in use at this time 
2112     and push them away to safety */
2113     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2114                           ic->rUsed);
2115     
2116     if (options.useXstack) {
2117         pic16_emitcode("mov","r0,%s",spname);   
2118         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2119             if (bitVectBitValue(rsave,i)) {
2120                 pic16_emitcode("dec","r0");
2121                 pic16_emitcode("movx","a,@r0");
2122                 if (i == R0_IDX)
2123                     pic16_emitcode("mov","b,a");
2124                 else
2125                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2126             }       
2127
2128         }
2129         pic16_emitcode("mov","%s,r0",spname);
2130         if (bitVectBitValue(rsave,R0_IDX))
2131             pic16_emitcode("mov","r0,b");
2132     } //else
2133     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2134     //    if (bitVectBitValue(rsave,i))
2135     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2136     //}
2137
2138 }  
2139
2140
2141 /*-----------------------------------------------------------------*/
2142 /* pushSide -                                                      */
2143 /*-----------------------------------------------------------------*/
2144 static void pushSide(operand * oper, int size)
2145 {
2146 #if 0
2147         int offset = 0;
2148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2149         while (size--) {
2150                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2151                 if (AOP_TYPE(oper) != AOP_REG &&
2152                     AOP_TYPE(oper) != AOP_DIR &&
2153                     strcmp(l,"a") ) {
2154                         pic16_emitcode("mov","a,%s",l);
2155                         pic16_emitcode("push","acc");
2156                 } else
2157                         pic16_emitcode("push","%s",l);
2158         }
2159 #endif
2160 }
2161
2162 /*-----------------------------------------------------------------*/
2163 /* assignResultValue -                                             */
2164 /*-----------------------------------------------------------------*/
2165 static void assignResultValue(operand * oper)
2166 {
2167   int size = AOP_SIZE(oper);
2168
2169   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2170
2171   DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2172
2173   if(!GpsuedoStkPtr) {
2174     /* The last byte in the assignment is in W */
2175     size--;
2176     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2177     GpsuedoStkPtr++;
2178   }
2179
2180   while (size--) {
2181     pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2182     GpsuedoStkPtr++;
2183     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2184   }
2185 }
2186
2187
2188 /*-----------------------------------------------------------------*/
2189 /* genIpush - genrate code for pushing this gets a little complex  */
2190 /*-----------------------------------------------------------------*/
2191 static void genIpush (iCode *ic)
2192 {
2193
2194   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2195 #if 0
2196     int size, offset = 0 ;
2197     char *l;
2198
2199
2200     /* if this is not a parm push : ie. it is spill push 
2201     and spill push is always done on the local stack */
2202     if (!ic->parmPush) {
2203
2204         /* and the item is spilt then do nothing */
2205         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2206             return ;
2207
2208         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2209         size = AOP_SIZE(IC_LEFT(ic));
2210         /* push it on the stack */
2211         while(size--) {
2212             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2213             if (*l == '#') {
2214                 MOVA(l);
2215                 l = "acc";
2216             }
2217             pic16_emitcode("push","%s",l);
2218         }
2219         return ;        
2220     }
2221
2222     /* this is a paramter push: in this case we call
2223     the routine to find the call and save those
2224     registers that need to be saved */   
2225     saveRegisters(ic);
2226
2227     /* then do the push */
2228     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2229
2230
2231         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2232     size = AOP_SIZE(IC_LEFT(ic));
2233
2234     while (size--) {
2235         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2236         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2237             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2238             strcmp(l,"a") ) {
2239             pic16_emitcode("mov","a,%s",l);
2240             pic16_emitcode("push","acc");
2241         } else
2242             pic16_emitcode("push","%s",l);
2243     }       
2244
2245     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2246 #endif
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* genIpop - recover the registers: can happen only for spilling   */
2251 /*-----------------------------------------------------------------*/
2252 static void genIpop (iCode *ic)
2253 {
2254   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2255 #if 0
2256     int size,offset ;
2257
2258
2259     /* if the temp was not pushed then */
2260     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2261         return ;
2262
2263     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2264     size = AOP_SIZE(IC_LEFT(ic));
2265     offset = (size-1);
2266     while (size--) 
2267         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2268                                    FALSE,TRUE));
2269
2270     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2271 #endif
2272 }
2273
2274 /*-----------------------------------------------------------------*/
2275 /* unsaverbank - restores the resgister bank from stack            */
2276 /*-----------------------------------------------------------------*/
2277 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2278 {
2279   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2280 #if 0
2281     int i;
2282     asmop *aop ;
2283     regs *r = NULL;
2284
2285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2286     if (popPsw) {
2287         if (options.useXstack) {
2288             aop = newAsmop(0);
2289             r = getFreePtr(ic,&aop,FALSE);
2290             
2291             
2292             pic16_emitcode("mov","%s,_spx",r->name);
2293             pic16_emitcode("movx","a,@%s",r->name);
2294             pic16_emitcode("mov","psw,a");
2295             pic16_emitcode("dec","%s",r->name);
2296             
2297         }else
2298             pic16_emitcode ("pop","psw");
2299     }
2300
2301     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2302         if (options.useXstack) {       
2303             pic16_emitcode("movx","a,@%s",r->name);
2304             //pic16_emitcode("mov","(%s+%d),a",
2305             //       regspic16[i].base,8*bank+regspic16[i].offset);
2306             pic16_emitcode("dec","%s",r->name);
2307
2308         } else 
2309           pic16_emitcode("pop",""); //"(%s+%d)",
2310         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2311     }
2312
2313     if (options.useXstack) {
2314
2315         pic16_emitcode("mov","_spx,%s",r->name);
2316         pic16_freeAsmop(NULL,aop,ic,TRUE);
2317
2318     }
2319 #endif 
2320 }
2321
2322 /*-----------------------------------------------------------------*/
2323 /* saverbank - saves an entire register bank on the stack          */
2324 /*-----------------------------------------------------------------*/
2325 static void saverbank (int bank, iCode *ic, bool pushPsw)
2326 {
2327   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2328 #if 0
2329     int i;
2330     asmop *aop ;
2331     regs *r = NULL;
2332
2333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334     if (options.useXstack) {
2335
2336         aop = newAsmop(0);
2337         r = getFreePtr(ic,&aop,FALSE);  
2338         pic16_emitcode("mov","%s,_spx",r->name);
2339
2340     }
2341
2342     for (i = 0 ; i < pic16_nRegs ;i++) {
2343         if (options.useXstack) {
2344             pic16_emitcode("inc","%s",r->name);
2345             //pic16_emitcode("mov","a,(%s+%d)",
2346             //         regspic16[i].base,8*bank+regspic16[i].offset);
2347             pic16_emitcode("movx","@%s,a",r->name);           
2348         } else 
2349           pic16_emitcode("push","");// "(%s+%d)",
2350                      //regspic16[i].base,8*bank+regspic16[i].offset);
2351     }
2352     
2353     if (pushPsw) {
2354         if (options.useXstack) {
2355             pic16_emitcode("mov","a,psw");
2356             pic16_emitcode("movx","@%s,a",r->name);     
2357             pic16_emitcode("inc","%s",r->name);
2358             pic16_emitcode("mov","_spx,%s",r->name);       
2359             pic16_freeAsmop (NULL,aop,ic,TRUE);
2360             
2361         } else
2362             pic16_emitcode("push","psw");
2363         
2364         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2365     }
2366     ic->bankSaved = 1;
2367 #endif
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* genCall - generates a call statement                            */
2372 /*-----------------------------------------------------------------*/
2373 static void genCall (iCode *ic)
2374 {
2375   sym_link *dtype;   
2376
2377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2378
2379   /* if caller saves & we have not saved then */
2380   if (!ic->regsSaved)
2381     saveRegisters(ic);
2382
2383   /* if we are calling a function that is not using
2384      the same register bank then we need to save the
2385      destination registers on the stack */
2386   dtype = operandType(IC_LEFT(ic));
2387   if (currFunc && dtype && 
2388       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2389       IFFUNC_ISISR(currFunc->type) &&
2390       !ic->bankSaved) 
2391
2392     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2393
2394   /* if send set is not empty the assign */
2395   if (_G.sendSet) {
2396     iCode *sic;
2397     /* For the Pic port, there is no data stack.
2398      * So parameters passed to functions are stored
2399      * in registers. (The pCode optimizer will get
2400      * rid of most of these :).
2401      */
2402     int psuedoStkPtr=-1; 
2403     int firstTimeThruLoop = 1;
2404
2405     _G.sendSet = reverseSet(_G.sendSet);
2406
2407     /* First figure how many parameters are getting passed */
2408     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2409          sic = setNextItem(_G.sendSet)) {
2410
2411       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2412       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2413       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2414     }
2415
2416     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2417          sic = setNextItem(_G.sendSet)) {
2418       int size, offset = 0;
2419
2420       pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2421       size = AOP_SIZE(IC_LEFT(sic));
2422
2423       while (size--) {
2424         DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2425                              pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2426
2427         if(!firstTimeThruLoop) {
2428           /* If this is not the first time we've been through the loop
2429            * then we need to save the parameter in a temporary
2430            * register. The last byte of the last parameter is
2431            * passed in W. */
2432           pic16_emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2433
2434         }
2435         firstTimeThruLoop=0;
2436
2437         //if (strcmp(l,fReturn[offset])) {
2438         mov2w (AOP(IC_LEFT(sic)),  offset);
2439 /*
2440         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2441              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2442           pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2443         else
2444           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_LEFT(sic)),offset));
2445 */
2446         //}
2447         offset++;
2448       }
2449       pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2450     }
2451     _G.sendSet = NULL;
2452   }
2453   /* make the call */
2454   pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2455                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2456                                       OP_SYMBOL(IC_LEFT(ic))->name));
2457
2458   GpsuedoStkPtr=0;
2459   /* if we need assign a result value */
2460   if ((IS_ITEMP(IC_RESULT(ic)) && 
2461        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2462         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2463       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2464
2465     _G.accInUse++;
2466     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2467     _G.accInUse--;
2468
2469     assignResultValue(IC_RESULT(ic));
2470
2471     DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2472                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2473                 
2474     pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2475   }
2476
2477   /* adjust the stack for parameters if 
2478      required */
2479   if (ic->parmBytes) {
2480     int i;
2481     if (ic->parmBytes > 3) {
2482       pic16_emitcode("mov","a,%s",spname);
2483       pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2484       pic16_emitcode("mov","%s,a",spname);
2485     } else 
2486       for ( i = 0 ; i <  ic->parmBytes ;i++)
2487         pic16_emitcode("dec","%s",spname);
2488
2489   }
2490
2491   /* if register bank was saved then pop them */
2492   if (ic->bankSaved)
2493     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2494
2495   /* if we hade saved some registers then unsave them */
2496   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497     unsaveRegisters (ic);
2498
2499
2500 }
2501
2502 /*-----------------------------------------------------------------*/
2503 /* genPcall - generates a call by pointer statement                */
2504 /*-----------------------------------------------------------------*/
2505 static void genPcall (iCode *ic)
2506 {
2507     sym_link *dtype;
2508     symbol *rlbl = newiTempLabel(NULL);
2509
2510
2511     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2512     /* if caller saves & we have not saved then */
2513     if (!ic->regsSaved)
2514         saveRegisters(ic);
2515
2516     /* if we are calling a function that is not using
2517     the same register bank then we need to save the
2518     destination registers on the stack */
2519     dtype = operandType(IC_LEFT(ic));
2520     if (currFunc && dtype && 
2521         IFFUNC_ISISR(currFunc->type) &&
2522         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2523         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2524
2525
2526     /* push the return address on to the stack */
2527     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2528     pic16_emitcode("push","acc");    
2529     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2530     pic16_emitcode("push","acc");
2531     
2532     if (options.model == MODEL_FLAT24)
2533     {
2534         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2535         pic16_emitcode("push","acc");    
2536     }
2537
2538     /* now push the calling address */
2539     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2540
2541     pushSide(IC_LEFT(ic), FPTRSIZE);
2542
2543     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2544
2545     /* if send set is not empty the assign */
2546     if (_G.sendSet) {
2547         iCode *sic ;
2548
2549         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2550              sic = setNextItem(_G.sendSet)) {
2551             int size, offset = 0;
2552             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2553             size = AOP_SIZE(IC_LEFT(sic));
2554             while (size--) {
2555                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2556                                 FALSE,FALSE);
2557                 if (strcmp(l,fReturn[offset]))
2558                     pic16_emitcode("mov","%s,%s",
2559                              fReturn[offset],
2560                              l);
2561                 offset++;
2562             }
2563             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2564         }
2565         _G.sendSet = NULL;
2566     }
2567
2568     pic16_emitcode("ret","");
2569     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2570
2571
2572     /* if we need assign a result value */
2573     if ((IS_ITEMP(IC_RESULT(ic)) &&
2574          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2575           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2576         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2577
2578         _G.accInUse++;
2579         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2580         _G.accInUse--;
2581         
2582         assignResultValue(IC_RESULT(ic));
2583
2584         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2585     }
2586
2587     /* adjust the stack for parameters if 
2588     required */
2589     if (ic->parmBytes) {
2590         int i;
2591         if (ic->parmBytes > 3) {
2592             pic16_emitcode("mov","a,%s",spname);
2593             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2594             pic16_emitcode("mov","%s,a",spname);
2595         } else 
2596             for ( i = 0 ; i <  ic->parmBytes ;i++)
2597                 pic16_emitcode("dec","%s",spname);
2598
2599     }
2600
2601     /* if register bank was saved then unsave them */
2602     if (currFunc && dtype && 
2603         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2604         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2605
2606     /* if we hade saved some registers then
2607     unsave them */
2608     if (ic->regsSaved)
2609         unsaveRegisters (ic);
2610
2611 }
2612
2613 /*-----------------------------------------------------------------*/
2614 /* resultRemat - result  is rematerializable                       */
2615 /*-----------------------------------------------------------------*/
2616 static int resultRemat (iCode *ic)
2617 {
2618   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2619   if (SKIP_IC(ic) || ic->op == IFX)
2620     return 0;
2621
2622   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2623     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2624     if (sym->remat && !POINTER_SET(ic)) 
2625       return 1;
2626   }
2627
2628   return 0;
2629 }
2630
2631 #if defined(__BORLANDC__) || defined(_MSC_VER)
2632 #define STRCASECMP stricmp
2633 #else
2634 #define STRCASECMP strcasecmp
2635 #endif
2636
2637 #if 0
2638 /*-----------------------------------------------------------------*/
2639 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2640 /*-----------------------------------------------------------------*/
2641 static bool inExcludeList(char *s)
2642 {
2643   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2644     int i =0;
2645     
2646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647     if (options.excludeRegs[i] &&
2648     STRCASECMP(options.excludeRegs[i],"none") == 0)
2649         return FALSE ;
2650
2651     for ( i = 0 ; options.excludeRegs[i]; i++) {
2652         if (options.excludeRegs[i] &&
2653         STRCASECMP(s,options.excludeRegs[i]) == 0)
2654             return TRUE;
2655     }
2656     return FALSE ;
2657 }
2658 #endif
2659
2660 /*-----------------------------------------------------------------*/
2661 /* genFunction - generated code for function entry                 */
2662 /*-----------------------------------------------------------------*/
2663 static void genFunction (iCode *ic)
2664 {
2665     symbol *sym;
2666     sym_link *ftype;
2667
2668     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2669
2670     labelOffset += (max_key+4);
2671     max_key=0;
2672     GpsuedoStkPtr=0;
2673     _G.nRegsSaved = 0;
2674     /* create the function header */
2675     pic16_emitcode(";","-----------------------------------------");
2676     pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2677     pic16_emitcode(";","-----------------------------------------");
2678
2679     pic16_emitcode("","%s:",sym->rname);
2680     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,sym->rname));
2681
2682     ftype = operandType(IC_LEFT(ic));
2683
2684     /* if critical function then turn interrupts off */
2685     if (IFFUNC_ISCRITICAL(ftype))
2686         pic16_emitcode("clr","ea");
2687
2688     /* here we need to generate the equates for the
2689        register bank if required */
2690 #if 0
2691     if (FUNC_REGBANK(ftype) != rbank) {
2692         int i ;
2693
2694         rbank = FUNC_REGBANK(ftype);
2695         for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2696             if (strcmp(regspic16[i].base,"0") == 0)
2697                 pic16_emitcode("","%s = 0x%02x",
2698                          regspic16[i].dname,
2699                          8*rbank+regspic16[i].offset);
2700             else
2701                 pic16_emitcode ("","%s = %s + 0x%02x",
2702                           regspic16[i].dname,
2703                           regspic16[i].base,
2704                           8*rbank+regspic16[i].offset);
2705         }
2706     }
2707 #endif
2708
2709     /* if this is an interrupt service routine then
2710     save acc, b, dpl, dph  */
2711     if (IFFUNC_ISISR(sym->type)) {
2712
2713 #if 0
2714         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_BRA,pic16_newpCodeOp("END_OF_INTERRUPT+2",PO_STR)));
2715         
2716         /* what is the reason of having these 3 NOPS? VR - 030701 */
2717         pic16_emitpcodeNULLop(POC_NOP);
2718         pic16_emitpcodeNULLop(POC_NOP);
2719         pic16_emitpcodeNULLop(POC_NOP);
2720 #endif
2721
2722       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2723       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2724       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2725       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2726
2727       pic16_pBlockConvert2ISR(pb);
2728 #if 0  
2729         if (!inExcludeList("acc"))          
2730             pic16_emitcode ("push","acc");      
2731         if (!inExcludeList("b"))
2732             pic16_emitcode ("push","b");
2733         if (!inExcludeList("dpl"))
2734             pic16_emitcode ("push","dpl");
2735         if (!inExcludeList("dph"))
2736             pic16_emitcode ("push","dph");
2737         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2738         {
2739             pic16_emitcode ("push", "dpx");
2740             /* Make sure we're using standard DPTR */
2741             pic16_emitcode ("push", "dps");
2742             pic16_emitcode ("mov", "dps, #0x00");
2743             if (options.stack10bit)
2744             {   
2745                 /* This ISR could conceivably use DPTR2. Better save it. */
2746                 pic16_emitcode ("push", "dpl1");
2747                 pic16_emitcode ("push", "dph1");
2748                 pic16_emitcode ("push", "dpx1");
2749             }
2750         }
2751         /* if this isr has no bank i.e. is going to
2752            run with bank 0 , then we need to save more
2753            registers :-) */
2754         if (!FUNC_REGBANK(sym->type)) {
2755
2756             /* if this function does not call any other
2757                function then we can be economical and
2758                save only those registers that are used */
2759             if (! IFFUNC_HASFCALL(sym->type)) {
2760                 int i;
2761
2762                 /* if any registers used */
2763                 if (sym->regsUsed) {
2764                     /* save the registers used */
2765                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2766                         if (bitVectBitValue(sym->regsUsed,i) ||
2767                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2768                           pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                         
2769                     }
2770                 }
2771                 
2772             } else {
2773                 /* this function has  a function call cannot
2774                    determines register usage so we will have the
2775                    entire bank */
2776                 saverbank(0,ic,FALSE);
2777             }       
2778         }
2779 #endif
2780     } else {
2781         /* if callee-save to be used for this function
2782            then save the registers being used in this function */
2783         if (IFFUNC_CALLEESAVES(sym->type)) {
2784             int i;
2785             
2786             /* if any registers used */
2787             if (sym->regsUsed) {
2788                 /* save the registers used */
2789                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2790                     if (bitVectBitValue(sym->regsUsed,i) ||
2791                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2792                       //pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2793                         _G.nRegsSaved++;
2794                     }
2795                 }
2796             }
2797         }
2798     }
2799
2800     /* set the register bank to the desired value */
2801     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2802         pic16_emitcode("push","psw");
2803         pic16_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2804     }
2805
2806     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2807
2808         if (options.useXstack) {
2809             pic16_emitcode("mov","r0,%s",spname);
2810             pic16_emitcode("mov","a,_bp");
2811             pic16_emitcode("movx","@r0,a");
2812             pic16_emitcode("inc","%s",spname);
2813         }
2814         else
2815         {
2816             /* set up the stack */
2817             pic16_emitcode ("push","_bp");     /* save the callers stack  */
2818         }
2819         pic16_emitcode ("mov","_bp,%s",spname);
2820     }
2821
2822     /* adjust the stack for the function */
2823     if (sym->stack) {
2824
2825         int i = sym->stack;
2826         if (i > 256 ) 
2827             werror(W_STACK_OVERFLOW,sym->name);
2828
2829         if (i > 3 && sym->recvSize < 4) {              
2830
2831             pic16_emitcode ("mov","a,sp");
2832             pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2833             pic16_emitcode ("mov","sp,a");
2834            
2835         }
2836         else
2837             while(i--)
2838                 pic16_emitcode("inc","sp");
2839     }
2840
2841      if (sym->xstack) {
2842
2843         pic16_emitcode ("mov","a,_spx");
2844         pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2845         pic16_emitcode ("mov","_spx,a");
2846     }    
2847
2848 }
2849
2850 /*-----------------------------------------------------------------*/
2851 /* genEndFunction - generates epilogue for functions               */
2852 /*-----------------------------------------------------------------*/
2853 static void genEndFunction (iCode *ic)
2854 {
2855     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2856
2857     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2858
2859     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2860     {
2861         pic16_emitcode ("mov","%s,_bp",spname);
2862     }
2863
2864     /* if use external stack but some variables were
2865     added to the local stack then decrement the
2866     local stack */
2867     if (options.useXstack && sym->stack) {      
2868         pic16_emitcode("mov","a,sp");
2869         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2870         pic16_emitcode("mov","sp,a");
2871     }
2872
2873
2874     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2875         if (options.useXstack) {
2876             pic16_emitcode("mov","r0,%s",spname);
2877             pic16_emitcode("movx","a,@r0");
2878             pic16_emitcode("mov","_bp,a");
2879             pic16_emitcode("dec","%s",spname);
2880         }
2881         else
2882         {
2883             pic16_emitcode ("pop","_bp");
2884         }
2885     }
2886
2887     /* restore the register bank  */    
2888     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2889         pic16_emitcode ("pop","psw");
2890
2891     if (IFFUNC_ISISR(sym->type)) {
2892
2893         /* now we need to restore the registers */
2894         /* if this isr has no bank i.e. is going to
2895            run with bank 0 , then we need to save more
2896            registers :-) */
2897         if (!FUNC_REGBANK(sym->type)) {
2898             
2899             /* if this function does not call any other
2900                function then we can be economical and
2901                save only those registers that are used */
2902             if (! IFFUNC_HASFCALL(sym->type)) {
2903                 int i;
2904                 
2905                 /* if any registers used */
2906                 if (sym->regsUsed) {
2907                     /* save the registers used */
2908                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2909                         if (bitVectBitValue(sym->regsUsed,i) ||
2910                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2911                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2912                     }
2913                 }
2914                 
2915             } else {
2916                 /* this function has  a function call cannot
2917                    determines register usage so we will have the
2918                    entire bank */
2919                 unsaverbank(0,ic,FALSE);
2920             }       
2921         }
2922 #if 0
2923         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2924         {
2925             if (options.stack10bit)
2926             {
2927                 pic16_emitcode ("pop", "dpx1");
2928                 pic16_emitcode ("pop", "dph1");
2929                 pic16_emitcode ("pop", "dpl1");
2930             }   
2931             pic16_emitcode ("pop", "dps");
2932             pic16_emitcode ("pop", "dpx");
2933         }
2934         if (!inExcludeList("dph"))
2935             pic16_emitcode ("pop","dph");
2936         if (!inExcludeList("dpl"))
2937             pic16_emitcode ("pop","dpl");
2938         if (!inExcludeList("b"))
2939             pic16_emitcode ("pop","b");
2940         if (!inExcludeList("acc"))
2941             pic16_emitcode ("pop","acc");
2942
2943         if (IFFUNC_ISCRITICAL(sym->type))
2944             pic16_emitcode("setb","ea");
2945 #endif
2946
2947         /* if debug then send end of function */
2948 /*      if (options.debug && currFunc) { */
2949         if (currFunc) {
2950             _G.debugLine = 1;
2951             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
2952                      FileBaseName(ic->filename),currFunc->lastLine,
2953                      ic->level,ic->block); 
2954             if (IS_STATIC(currFunc->etype))         
2955                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2956             else
2957                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2958             _G.debugLine = 0;
2959         }
2960         
2961 //      pic16_emitcode ("reti","");
2962
2963         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2964         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
2965         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
2966         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
2967         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
2968
2969 #if 0
2970         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
2971 #endif
2972
2973         pic16_emitpcodeNULLop(POC_RETFIE);
2974
2975     }
2976     else {
2977         if (IFFUNC_ISCRITICAL(sym->type))
2978             pic16_emitcode("setb","ea");
2979         
2980         if (IFFUNC_CALLEESAVES(sym->type)) {
2981             int i;
2982             
2983             /* if any registers used */
2984             if (sym->regsUsed) {
2985                 /* save the registers used */
2986                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2987                     if (bitVectBitValue(sym->regsUsed,i) ||
2988                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2989                       pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
2990                 }
2991             }
2992             
2993         }
2994
2995         /* if debug then send end of function */
2996         if (currFunc) {
2997             _G.debugLine = 1;
2998             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
2999                      FileBaseName(ic->filename),currFunc->lastLine,
3000                      ic->level,ic->block); 
3001             if (IS_STATIC(currFunc->etype))         
3002                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3003             else
3004                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3005             _G.debugLine = 0;
3006         }
3007
3008         pic16_emitcode ("return","");
3009         pic16_emitpcodeNULLop(POC_RETURN);
3010
3011         /* Mark the end of a function */
3012         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3013     }
3014
3015 }
3016
3017 /*-----------------------------------------------------------------*/
3018 /* genRet - generate code for return statement                     */
3019 /*-----------------------------------------------------------------*/
3020 static void genRet (iCode *ic)
3021 {
3022   int size,offset = 0 , pushed = 0;
3023     
3024   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3025   /* if we have no return value then
3026      just generate the "ret" */
3027   if (!IC_LEFT(ic)) 
3028     goto jumpret;       
3029     
3030   /* we have something to return then
3031      move the return value into place */
3032   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3033   size = AOP_SIZE(IC_LEFT(ic));
3034     
3035   while (size--) {
3036     char *l ;
3037     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3038       /* #NOCHANGE */
3039       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3040                  FALSE,TRUE);
3041       pic16_emitcode("push","%s",l);
3042       pushed++;
3043     } else {
3044       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3045                  FALSE,FALSE);
3046       if (strcmp(fReturn[offset],l)) {
3047         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3048             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3049           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3050         }else {
3051           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3052         }
3053         if(size) {
3054           pic16_emitpcode(POC_MOVWF,popRegFromIdx(offset + pic16_Gstack_base_addr));
3055         }
3056         offset++;
3057       }
3058     }
3059   }    
3060
3061   if (pushed) {
3062     while(pushed) {
3063       pushed--;
3064       if (strcmp(fReturn[pushed],"a"))
3065         pic16_emitcode("pop",fReturn[pushed]);
3066       else
3067         pic16_emitcode("pop","acc");
3068     }
3069   }
3070   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3071     
3072  jumpret:
3073   /* generate a jump to the return label
3074      if the next is not the return statement */
3075   if (!(ic->next && ic->next->op == LABEL &&
3076         IC_LABEL(ic->next) == returnLabel)) {
3077         
3078     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3079     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3080   }
3081     
3082 }
3083
3084 /*-----------------------------------------------------------------*/
3085 /* genLabel - generates a label                                    */
3086 /*-----------------------------------------------------------------*/
3087 static void genLabel (iCode *ic)
3088 {
3089     /* special case never generate */
3090     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3091     if (IC_LABEL(ic) == entryLabel)
3092         return ;
3093
3094     pic16_emitpLabel(IC_LABEL(ic)->key);
3095     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3096 }
3097
3098 /*-----------------------------------------------------------------*/
3099 /* genGoto - generates a goto                                      */
3100 /*-----------------------------------------------------------------*/
3101 //tsd
3102 static void genGoto (iCode *ic)
3103 {
3104   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3105   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3106 }
3107
3108
3109 /*-----------------------------------------------------------------*/
3110 /* genMultbits :- multiplication of bits                           */
3111 /*-----------------------------------------------------------------*/
3112 static void genMultbits (operand *left, 
3113                          operand *right, 
3114                          operand *result)
3115 {
3116   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3117
3118   if(!pic16_sameRegs(AOP(result),AOP(right)))
3119     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3120
3121   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3122   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3123   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3124
3125 }
3126
3127
3128 /*-----------------------------------------------------------------*/
3129 /* genMultOneByte : 8 bit multiplication & division                */
3130 /*-----------------------------------------------------------------*/
3131 static void genMultOneByte (operand *left,
3132                             operand *right,
3133                             operand *result)
3134 {
3135   sym_link *opetype = operandType(result);
3136
3137   // symbol *lbl ;
3138   int size,offset;
3139
3140   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3141   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3142   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3143
3144   /* (if two literals, the value is computed before) */
3145   /* if one literal, literal on the right */
3146   if (AOP_TYPE(left) == AOP_LIT){
3147     operand *t = right;
3148     right = left;
3149     left = t;
3150   }
3151
3152   size = AOP_SIZE(result);
3153   if(size == 1) {
3154
3155     if (AOP_TYPE(right) == AOP_LIT){
3156       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3157                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3158                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3159                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3160       pic16_emitcode("call","genMultLit");
3161     } else {
3162       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3163                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3164                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3165                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3166       pic16_emitcode("call","pic16_genMult8X8_8");
3167
3168     }
3169     pic16_genMult8X8_8 (left, right,result);
3170
3171
3172     /* signed or unsigned */
3173     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3174     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3175     //MOVA(l);       
3176     //pic16_emitcode("mul","ab");
3177     /* if result size = 1, mul signed = mul unsigned */
3178     //pic16_aopPut(AOP(result),"a",0);
3179
3180   } else {  // (size > 1)
3181
3182     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3183                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3184                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3185                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3186
3187     if (SPEC_USIGN(opetype)){
3188       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3189       pic16_genUMult8X8_16 (left, right, result, NULL);
3190
3191       if (size > 2) {
3192         /* for filling the MSBs */
3193         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3194         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3195       }
3196     }
3197     else{
3198       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3199
3200       pic16_emitcode("mov","a,b");
3201
3202       /* adjust the MSB if left or right neg */
3203
3204       /* if one literal */
3205       if (AOP_TYPE(right) == AOP_LIT){
3206         pic16_emitcode("multiply ","right is a lit");
3207         /* AND literal negative */
3208         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3209           /* adjust MSB (c==0 after mul) */
3210           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3211         }
3212       }
3213       else{
3214         pic16_genSMult8X8_16 (left, right, result, NULL);
3215       }
3216
3217       if(size > 2){
3218         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3219         /* get the sign */
3220         pic16_emitcode("rlc","a");
3221         pic16_emitcode("subb","a,acc");
3222       }
3223     }
3224
3225     size -= 2;   
3226     offset = 2;
3227     if (size > 0)
3228       while (size--)
3229         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3230     //pic16_aopPut(AOP(result),"a",offset++);
3231   }
3232 }
3233
3234 /*-----------------------------------------------------------------*/
3235 /* genMult - generates code for multiplication                     */
3236 /*-----------------------------------------------------------------*/
3237 static void genMult (iCode *ic)
3238 {
3239     operand *left = IC_LEFT(ic);
3240     operand *right = IC_RIGHT(ic);
3241     operand *result= IC_RESULT(ic);   
3242
3243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3244     /* assign the amsops */
3245     pic16_aopOp (left,ic,FALSE);
3246     pic16_aopOp (right,ic,FALSE);
3247     pic16_aopOp (result,ic,TRUE);
3248
3249   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3250
3251     /* special cases first */
3252     /* both are bits */
3253     if (AOP_TYPE(left) == AOP_CRY &&
3254         AOP_TYPE(right)== AOP_CRY) {
3255         genMultbits(left,right,result);
3256         goto release ;
3257     }
3258
3259     /* if both are of size == 1 */
3260     if (AOP_SIZE(left) == 1 &&
3261         AOP_SIZE(right) == 1 ) {
3262         genMultOneByte(left,right,result);
3263         goto release ;
3264     }
3265
3266     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3267
3268     /* should have been converted to function call */
3269     //assert(0) ;
3270
3271 release :
3272     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3273     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3274     pic16_freeAsmop(result,NULL,ic,TRUE); 
3275 }
3276
3277 /*-----------------------------------------------------------------*/
3278 /* genDivbits :- division of bits                                  */
3279 /*-----------------------------------------------------------------*/
3280 static void genDivbits (operand *left, 
3281                         operand *right, 
3282                         operand *result)
3283 {
3284
3285     char *l;
3286
3287     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3288     /* the result must be bit */    
3289     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3290     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3291
3292     MOVA(l);    
3293
3294     pic16_emitcode("div","ab");
3295     pic16_emitcode("rrc","a");
3296     pic16_aopPut(AOP(result),"c",0);
3297 }
3298
3299 /*-----------------------------------------------------------------*/
3300 /* genDivOneByte : 8 bit division                                  */
3301 /*-----------------------------------------------------------------*/
3302 static void genDivOneByte (operand *left,
3303                            operand *right,
3304                            operand *result)
3305 {
3306     sym_link *opetype = operandType(result);
3307     char *l ;
3308     symbol *lbl ;
3309     int size,offset;
3310
3311     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3312     size = AOP_SIZE(result) - 1;
3313     offset = 1;
3314     /* signed or unsigned */
3315     if (SPEC_USIGN(opetype)) {
3316         /* unsigned is easy */
3317         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3318         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3319         MOVA(l);        
3320         pic16_emitcode("div","ab");
3321         pic16_aopPut(AOP(result),"a",0);
3322         while (size--)
3323             pic16_aopPut(AOP(result),zero,offset++);
3324         return ;
3325     }
3326
3327     /* signed is a little bit more difficult */
3328
3329     /* save the signs of the operands */
3330     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3331     MOVA(l);    
3332     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3333     pic16_emitcode("push","acc"); /* save it on the stack */
3334
3335     /* now sign adjust for both left & right */
3336     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3337     MOVA(l);       
3338     lbl = newiTempLabel(NULL);
3339     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3340     pic16_emitcode("cpl","a");   
3341     pic16_emitcode("inc","a");
3342     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3343     pic16_emitcode("mov","b,a");
3344
3345     /* sign adjust left side */
3346     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3347     MOVA(l);
3348
3349     lbl = newiTempLabel(NULL);
3350     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3351     pic16_emitcode("cpl","a");
3352     pic16_emitcode("inc","a");
3353     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3354
3355     /* now the division */
3356     pic16_emitcode("div","ab");
3357     /* we are interested in the lower order
3358     only */
3359     pic16_emitcode("mov","b,a");
3360     lbl = newiTempLabel(NULL);
3361     pic16_emitcode("pop","acc");   
3362     /* if there was an over flow we don't 
3363     adjust the sign of the result */
3364     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3365     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3366     CLRC;
3367     pic16_emitcode("clr","a");
3368     pic16_emitcode("subb","a,b");
3369     pic16_emitcode("mov","b,a");
3370     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3371
3372     /* now we are done */
3373     pic16_aopPut(AOP(result),"b",0);
3374     if(size > 0){
3375         pic16_emitcode("mov","c,b.7");
3376         pic16_emitcode("subb","a,acc");   
3377     }
3378     while (size--)
3379         pic16_aopPut(AOP(result),"a",offset++);
3380
3381 }
3382
3383 /*-----------------------------------------------------------------*/
3384 /* genDiv - generates code for division                            */
3385 /*-----------------------------------------------------------------*/
3386 static void genDiv (iCode *ic)
3387 {
3388     operand *left = IC_LEFT(ic);
3389     operand *right = IC_RIGHT(ic);
3390     operand *result= IC_RESULT(ic);   
3391
3392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3393     /* assign the amsops */
3394     pic16_aopOp (left,ic,FALSE);
3395     pic16_aopOp (right,ic,FALSE);
3396     pic16_aopOp (result,ic,TRUE);
3397
3398     /* special cases first */
3399     /* both are bits */
3400     if (AOP_TYPE(left) == AOP_CRY &&
3401         AOP_TYPE(right)== AOP_CRY) {
3402         genDivbits(left,right,result);
3403         goto release ;
3404     }
3405
3406     /* if both are of size == 1 */
3407     if (AOP_SIZE(left) == 1 &&
3408         AOP_SIZE(right) == 1 ) {
3409         genDivOneByte(left,right,result);
3410         goto release ;
3411     }
3412
3413     /* should have been converted to function call */
3414     assert(0);
3415 release :
3416     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3417     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3418     pic16_freeAsmop(result,NULL,ic,TRUE); 
3419 }
3420
3421 /*-----------------------------------------------------------------*/
3422 /* genModbits :- modulus of bits                                   */
3423 /*-----------------------------------------------------------------*/
3424 static void genModbits (operand *left, 
3425                         operand *right, 
3426                         operand *result)
3427 {
3428
3429     char *l;
3430
3431     /* the result must be bit */    
3432     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3433     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3434
3435     MOVA(l);       
3436
3437     pic16_emitcode("div","ab");
3438     pic16_emitcode("mov","a,b");
3439     pic16_emitcode("rrc","a");
3440     pic16_aopPut(AOP(result),"c",0);
3441 }
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genModOneByte : 8 bit modulus                                   */
3445 /*-----------------------------------------------------------------*/
3446 static void genModOneByte (operand *left,
3447                            operand *right,
3448                            operand *result)
3449 {
3450     sym_link *opetype = operandType(result);
3451     char *l ;
3452     symbol *lbl ;
3453
3454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3455     /* signed or unsigned */
3456     if (SPEC_USIGN(opetype)) {
3457         /* unsigned is easy */
3458         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3459         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3460         MOVA(l);    
3461         pic16_emitcode("div","ab");
3462         pic16_aopPut(AOP(result),"b",0);
3463         return ;
3464     }
3465
3466     /* signed is a little bit more difficult */
3467
3468     /* save the signs of the operands */
3469     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3470     MOVA(l);
3471
3472     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3473     pic16_emitcode("push","acc"); /* save it on the stack */
3474
3475     /* now sign adjust for both left & right */
3476     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3477     MOVA(l);
3478
3479     lbl = newiTempLabel(NULL);
3480     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3481     pic16_emitcode("cpl","a");   
3482     pic16_emitcode("inc","a");
3483     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3484     pic16_emitcode("mov","b,a"); 
3485
3486     /* sign adjust left side */
3487     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3488     MOVA(l);
3489
3490     lbl = newiTempLabel(NULL);
3491     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3492     pic16_emitcode("cpl","a");   
3493     pic16_emitcode("inc","a");
3494     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3495
3496     /* now the multiplication */
3497     pic16_emitcode("div","ab");
3498     /* we are interested in the lower order
3499     only */
3500     lbl = newiTempLabel(NULL);
3501     pic16_emitcode("pop","acc");   
3502     /* if there was an over flow we don't 
3503     adjust the sign of the result */
3504     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3505     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3506     CLRC ;
3507     pic16_emitcode("clr","a");
3508     pic16_emitcode("subb","a,b");
3509     pic16_emitcode("mov","b,a");
3510     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3511
3512     /* now we are done */
3513     pic16_aopPut(AOP(result),"b",0);
3514
3515 }
3516
3517 /*-----------------------------------------------------------------*/
3518 /* genMod - generates code for division                            */
3519 /*-----------------------------------------------------------------*/
3520 static void genMod (iCode *ic)
3521 {
3522     operand *left = IC_LEFT(ic);
3523     operand *right = IC_RIGHT(ic);
3524     operand *result= IC_RESULT(ic);  
3525
3526     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3527     /* assign the amsops */
3528     pic16_aopOp (left,ic,FALSE);
3529     pic16_aopOp (right,ic,FALSE);
3530     pic16_aopOp (result,ic,TRUE);
3531
3532     /* special cases first */
3533     /* both are bits */
3534     if (AOP_TYPE(left) == AOP_CRY &&
3535         AOP_TYPE(right)== AOP_CRY) {
3536         genModbits(left,right,result);
3537         goto release ;
3538     }
3539
3540     /* if both are of size == 1 */
3541     if (AOP_SIZE(left) == 1 &&
3542         AOP_SIZE(right) == 1 ) {
3543         genModOneByte(left,right,result);
3544         goto release ;
3545     }
3546
3547     /* should have been converted to function call */
3548     assert(0);
3549
3550 release :
3551     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3552     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553     pic16_freeAsmop(result,NULL,ic,TRUE); 
3554 }
3555
3556 /*-----------------------------------------------------------------*/
3557 /* genIfxJump :- will create a jump depending on the ifx           */
3558 /*-----------------------------------------------------------------*/
3559 /*
3560   note: May need to add parameter to indicate when a variable is in bit space.
3561 */
3562 static void genIfxJump (iCode *ic, char *jval)
3563 {
3564
3565     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3566     /* if true label then we jump if condition
3567     supplied is true */
3568     if ( IC_TRUE(ic) ) {
3569
3570         if(strcmp(jval,"a") == 0)
3571           emitSKPZ;
3572         else if (strcmp(jval,"c") == 0)
3573           emitSKPC;
3574         else {
3575           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3576           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3577         }
3578
3579         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3580         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3581
3582     }
3583     else {
3584         /* false label is present */
3585         if(strcmp(jval,"a") == 0)
3586           emitSKPNZ;
3587         else if (strcmp(jval,"c") == 0)
3588           emitSKPNC;
3589         else {
3590           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3591           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3592         }
3593
3594         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3595         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3596
3597     }
3598
3599
3600     /* mark the icode as generated */
3601     ic->generated = 1;
3602 }
3603
3604 /*-----------------------------------------------------------------*/
3605 /* genSkip                                                         */
3606 /*-----------------------------------------------------------------*/
3607 static void genSkip(iCode *ifx,int status_bit)
3608 {
3609   if(!ifx)
3610     return;
3611
3612   if ( IC_TRUE(ifx) ) {
3613     switch(status_bit) {
3614     case 'z':
3615       emitSKPNZ;
3616       break;
3617
3618     case 'c':
3619       emitSKPNC;
3620       break;
3621
3622     case 'd':
3623       emitSKPDC;
3624       break;
3625
3626     }
3627
3628     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3629     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3630
3631   } else {
3632
3633     switch(status_bit) {
3634
3635     case 'z':
3636       emitSKPZ;
3637       break;
3638
3639     case 'c':
3640       emitSKPC;
3641       break;
3642
3643     case 'd':
3644       emitSKPDC;
3645       break;
3646     }
3647     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3648     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3649
3650   }
3651
3652 }
3653
3654 /*-----------------------------------------------------------------*/
3655 /* genSkipc                                                        */
3656 /*-----------------------------------------------------------------*/
3657 static void genSkipc(resolvedIfx *rifx)
3658 {
3659   if(!rifx)
3660     return;
3661
3662   if(rifx->condition)
3663     emitSKPC;
3664   else
3665     emitSKPNC;
3666
3667   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3668   rifx->generated = 1;
3669 }
3670
3671 /*-----------------------------------------------------------------*/
3672 /* genSkipz2                                                       */
3673 /*-----------------------------------------------------------------*/
3674 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3675 {
3676   if(!rifx)
3677     return;
3678
3679   if( (rifx->condition ^ invert_condition) & 1)
3680     emitSKPZ;
3681   else
3682     emitSKPNZ;
3683
3684   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3685   rifx->generated = 1;
3686 }
3687
3688 /*-----------------------------------------------------------------*/
3689 /* genSkipz                                                        */
3690 /*-----------------------------------------------------------------*/
3691 static void genSkipz(iCode *ifx, int condition)
3692 {
3693   if(!ifx)
3694     return;
3695
3696   if(condition)
3697     emitSKPNZ;
3698   else
3699     emitSKPZ;
3700
3701   if ( IC_TRUE(ifx) )
3702     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3703   else
3704     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3705
3706   if ( IC_TRUE(ifx) )
3707     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3708   else
3709     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3710
3711 }
3712 /*-----------------------------------------------------------------*/
3713 /* genSkipCond                                                     */
3714 /*-----------------------------------------------------------------*/
3715 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3716 {
3717   if(!rifx)
3718     return;
3719
3720   if(rifx->condition)
3721     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3722   else
3723     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3724
3725
3726   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3727   rifx->generated = 1;
3728 }
3729
3730 #if 0
3731 /*-----------------------------------------------------------------*/
3732 /* genChkZeroes :- greater or less than comparison                 */
3733 /*     For each byte in a literal that is zero, inclusive or the   */
3734 /*     the corresponding byte in the operand with W                */
3735 /*     returns true if any of the bytes are zero                   */
3736 /*-----------------------------------------------------------------*/
3737 static int genChkZeroes(operand *op, int lit,  int size)
3738 {
3739
3740   int i;
3741   int flag =1;
3742
3743   while(size--) {
3744     i = (lit >> (size*8)) & 0xff;
3745
3746     if(i==0) {
3747       if(flag) 
3748         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3749       else
3750         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3751       flag = 0;
3752     }
3753   }
3754
3755   return (flag==0);
3756 }
3757 #endif
3758
3759 /*-----------------------------------------------------------------*/
3760 /* genCmp :- greater or less than comparison                       */
3761 /*-----------------------------------------------------------------*/
3762 static void genCmp (operand *left,operand *right,
3763                     operand *result, iCode *ifx, int sign)
3764 {
3765   int size; //, offset = 0 ;
3766   unsigned long lit = 0L,i = 0;
3767   resolvedIfx rFalseIfx;
3768   //  resolvedIfx rTrueIfx;
3769   symbol *truelbl;
3770   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3771 /*
3772   if(ifx) {
3773     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3774     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3775   }
3776 */
3777
3778   resolveIfx(&rFalseIfx,ifx);
3779   truelbl  = newiTempLabel(NULL);
3780   size = max(AOP_SIZE(left),AOP_SIZE(right));
3781
3782   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3783
3784 #define _swapp
3785
3786   /* if literal is on the right then swap with left */
3787   if ((AOP_TYPE(right) == AOP_LIT)) {
3788     operand *tmp = right ;
3789     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3790     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3791 #ifdef _swapp
3792
3793     lit = (lit - 1) & mask;
3794     right = left;
3795     left = tmp;
3796     rFalseIfx.condition ^= 1;
3797 #endif
3798
3799   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3800     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3801   }
3802
3803
3804   //if(IC_TRUE(ifx) == NULL)
3805   /* if left & right are bit variables */
3806   if (AOP_TYPE(left) == AOP_CRY &&
3807       AOP_TYPE(right) == AOP_CRY ) {
3808     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3809     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3810   } else {
3811     /* subtract right from left if at the
3812        end the carry flag is set then we know that
3813        left is greater than right */
3814
3815     //    {
3816
3817     symbol *lbl  = newiTempLabel(NULL);
3818
3819 #ifndef _swapp
3820     if(AOP_TYPE(right) == AOP_LIT) {
3821
3822       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3823
3824       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3825
3826       /* special cases */
3827
3828       if(lit == 0) {
3829
3830         if(sign != 0) 
3831           genSkipCond(&rFalseIfx,left,size-1,7);
3832         else 
3833           /* no need to compare to 0...*/
3834           /* NOTE: this is a de-generate compare that most certainly 
3835            *       creates some dead code. */
3836           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
3837
3838         if(ifx) ifx->generated = 1;
3839         return;
3840
3841       }
3842       size--;
3843
3844       if(size == 0) {
3845         //i = (lit >> (size*8)) & 0xff;
3846         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3847         
3848         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3849
3850         i = ((0-lit) & 0xff);
3851         if(sign) {
3852           if( i == 0x81) { 
3853             /* lit is 0x7f, all signed chars are less than
3854              * this except for 0x7f itself */
3855             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
3856             genSkipz2(&rFalseIfx,0);
3857           } else {
3858             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
3859             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
3860             genSkipc(&rFalseIfx);
3861           }
3862
3863         } else {
3864           if(lit == 1) {
3865             genSkipz2(&rFalseIfx,1);
3866           } else {
3867             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
3868             genSkipc(&rFalseIfx);
3869           }
3870         }
3871
3872         if(ifx) ifx->generated = 1;
3873         return;
3874       }
3875
3876       /* chars are out of the way. now do ints and longs */
3877
3878
3879       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3880         
3881       /* special cases */
3882
3883       if(sign) {
3884
3885         if(lit == 0) {
3886           genSkipCond(&rFalseIfx,left,size,7);
3887           if(ifx) ifx->generated = 1;
3888           return;
3889         }
3890
3891         if(lit <0x100) {
3892           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3893
3894           //rFalseIfx.condition ^= 1;
3895           //genSkipCond(&rFalseIfx,left,size,7);
3896           //rFalseIfx.condition ^= 1;
3897
3898           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3899           if(rFalseIfx.condition)
3900             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3901           else
3902             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3903
3904           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
3905           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3906           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
3907
3908           while(size > 1)
3909             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
3910
3911           if(rFalseIfx.condition) {
3912             emitSKPZ;
3913             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3914
3915           } else {
3916             emitSKPNZ;
3917           }
3918
3919           genSkipc(&rFalseIfx);
3920           pic16_emitpLabel(truelbl->key);
3921           if(ifx) ifx->generated = 1;
3922           return;
3923
3924         }
3925
3926         if(size == 1) {
3927
3928           if( (lit & 0xff) == 0) {
3929             /* lower byte is zero */
3930             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3931             i = ((lit >> 8) & 0xff) ^0x80;
3932             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3933             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3934             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3935             genSkipc(&rFalseIfx);
3936
3937
3938             if(ifx) ifx->generated = 1;
3939             return;
3940
3941           }
3942         } else {
3943           /* Special cases for signed longs */
3944           if( (lit & 0xffffff) == 0) {
3945             /* lower byte is zero */
3946             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3947             i = ((lit >> 8*3) & 0xff) ^0x80;
3948             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3949             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
3950             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
3951             genSkipc(&rFalseIfx);
3952
3953
3954             if(ifx) ifx->generated = 1;
3955             return;
3956
3957           }
3958
3959         }
3960
3961
3962         if(lit & (0x80 << (size*8))) {
3963           /* lit is negative */
3964           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3965
3966           //genSkipCond(&rFalseIfx,left,size,7);
3967
3968           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3969
3970           if(rFalseIfx.condition)
3971             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3972           else
3973             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3974
3975
3976         } else {
3977           /* lit is positive */
3978           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3979           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
3980           if(rFalseIfx.condition)
3981             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
3982           else
3983             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
3984
3985         }
3986
3987         /*
3988           This works, but is only good for ints.
3989           It also requires a "known zero" register.
3990           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
3991           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
3992           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
3993           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
3994           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
3995           genSkipc(&rFalseIfx);
3996
3997           pic16_emitpLabel(truelbl->key);
3998           if(ifx) ifx->generated = 1;
3999           return;
4000         **/
4001           
4002         /* There are no more special cases, so perform a general compare */
4003   
4004         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4005         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4006
4007         while(size--) {
4008
4009           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4010           emitSKPNZ;
4011           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4012         }
4013         //rFalseIfx.condition ^= 1;
4014         genSkipc(&rFalseIfx);
4015
4016         pic16_emitpLabel(truelbl->key);
4017
4018         if(ifx) ifx->generated = 1;
4019         return;
4020
4021
4022       }
4023
4024
4025       /* sign is out of the way. So now do an unsigned compare */
4026       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4027
4028
4029       /* General case - compare to an unsigned literal on the right.*/
4030
4031       i = (lit >> (size*8)) & 0xff;
4032       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4033       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4034       while(size--) {
4035         i = (lit >> (size*8)) & 0xff;
4036
4037         if(i) {
4038           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4039           emitSKPNZ;
4040           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4041         } else {
4042           /* this byte of the lit is zero, 
4043            *if it's not the last then OR in the variable */
4044           if(size)
4045             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4046         }
4047       }
4048
4049
4050       pic16_emitpLabel(lbl->key);
4051       //if(emitFinalCheck)
4052       genSkipc(&rFalseIfx);
4053       if(sign)
4054         pic16_emitpLabel(truelbl->key);
4055
4056       if(ifx) ifx->generated = 1;
4057       return;
4058
4059
4060     }
4061 #endif  // _swapp
4062
4063     if(AOP_TYPE(left) == AOP_LIT) {
4064       //symbol *lbl = newiTempLabel(NULL);
4065
4066       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4067
4068
4069       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4070
4071       /* Special cases */
4072       if((lit == 0) && (sign == 0)){
4073
4074         size--;
4075         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4076         while(size) 
4077           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4078
4079         genSkipz2(&rFalseIfx,0);
4080         if(ifx) ifx->generated = 1;
4081         return;
4082       }
4083
4084       if(size==1) {
4085         /* Special cases */
4086         lit &= 0xff;
4087         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4088           /* degenerate compare can never be true */
4089           if(rFalseIfx.condition == 0)
4090             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4091
4092           if(ifx) ifx->generated = 1;
4093           return;
4094         }
4095
4096         if(sign) {
4097           /* signed comparisons to a literal byte */
4098
4099           int lp1 = (lit+1) & 0xff;
4100
4101           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4102           switch (lp1) {
4103           case 0:
4104             rFalseIfx.condition ^= 1;
4105             genSkipCond(&rFalseIfx,right,0,7);
4106             break;
4107           case 0x7f:
4108             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4109             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4110             genSkipz2(&rFalseIfx,1);
4111             break;
4112           default:
4113             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4114             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4115             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4116             rFalseIfx.condition ^= 1;
4117             genSkipc(&rFalseIfx);
4118             break;
4119           }
4120         } else {
4121           /* unsigned comparisons to a literal byte */
4122
4123           switch(lit & 0xff ) {
4124           case 0:
4125             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4126             genSkipz2(&rFalseIfx,0);
4127             break;
4128           case 0x7f:
4129             rFalseIfx.condition ^= 1;
4130             genSkipCond(&rFalseIfx,right,0,7);
4131             break;
4132
4133           default:
4134             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4135             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4136             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4137             rFalseIfx.condition ^= 1;
4138             if (AOP_TYPE(result) == AOP_CRY)
4139               genSkipc(&rFalseIfx);
4140             else {
4141               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4142               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4143             }         
4144             break;
4145           }
4146         }
4147
4148         if(ifx) ifx->generated = 1;
4149         //goto check_carry;
4150         return;
4151
4152       } else {
4153
4154         /* Size is greater than 1 */
4155
4156         if(sign) {
4157           int lp1 = lit+1;
4158
4159           size--;
4160
4161           if(lp1 == 0) {
4162             /* this means lit = 0xffffffff, or -1 */
4163
4164
4165             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4166             rFalseIfx.condition ^= 1;
4167             genSkipCond(&rFalseIfx,right,size,7);
4168             if(ifx) ifx->generated = 1;
4169             return;
4170           }
4171
4172           if(lit == 0) {
4173             int s = size;
4174
4175             if(rFalseIfx.condition) {
4176               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4177               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4178             }
4179
4180             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4181             while(size--)
4182               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4183
4184
4185             emitSKPZ;
4186             if(rFalseIfx.condition) {
4187               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4188               pic16_emitpLabel(truelbl->key);
4189             }else {
4190               rFalseIfx.condition ^= 1;
4191               genSkipCond(&rFalseIfx,right,s,7);
4192             }
4193
4194             if(ifx) ifx->generated = 1;
4195             return;
4196           }
4197
4198           if((size == 1) &&  (0 == (lp1&0xff))) {
4199             /* lower byte of signed word is zero */
4200             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4201             i = ((lp1 >> 8) & 0xff) ^0x80;
4202             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4203             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4204             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4205             rFalseIfx.condition ^= 1;
4206             genSkipc(&rFalseIfx);
4207
4208
4209             if(ifx) ifx->generated = 1;
4210             return;
4211           }
4212
4213           if(lit & (0x80 << (size*8))) {
4214             /* Lit is less than zero */
4215             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4216             //rFalseIfx.condition ^= 1;
4217             //genSkipCond(&rFalseIfx,left,size,7);
4218             //rFalseIfx.condition ^= 1;
4219             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4220             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4221
4222             if(rFalseIfx.condition)
4223               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4224             else
4225               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4226
4227
4228           } else {
4229             /* Lit is greater than or equal to zero */
4230             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4231             //rFalseIfx.condition ^= 1;
4232             //genSkipCond(&rFalseIfx,right,size,7);
4233             //rFalseIfx.condition ^= 1;
4234
4235             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4236             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4237
4238             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4239             if(rFalseIfx.condition)
4240               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4241             else
4242               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4243
4244           }
4245
4246
4247           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4248           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4249
4250           while(size--) {
4251
4252             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4253             emitSKPNZ;
4254             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4255           }
4256           rFalseIfx.condition ^= 1;
4257           //rFalseIfx.condition = 1;
4258           genSkipc(&rFalseIfx);
4259
4260           pic16_emitpLabel(truelbl->key);
4261
4262           if(ifx) ifx->generated = 1;
4263           return;
4264           // end of if (sign)
4265         } else {
4266
4267           /* compare word or long to an unsigned literal on the right.*/
4268
4269
4270           size--;
4271           if(lit < 0xff) {
4272             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4273             switch (lit) {
4274             case 0:
4275               break; /* handled above */
4276 /*
4277             case 0xff:
4278               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4279               while(size--)
4280                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4281               genSkipz2(&rFalseIfx,0);
4282               break;
4283 */
4284             default:
4285               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4286               while(--size)
4287                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4288
4289               emitSKPZ;
4290               if(rFalseIfx.condition)
4291                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4292               else
4293                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4294
4295
4296               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4297               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4298
4299               rFalseIfx.condition ^= 1;
4300               genSkipc(&rFalseIfx);
4301             }
4302
4303             pic16_emitpLabel(truelbl->key);
4304
4305             if(ifx) ifx->generated = 1;
4306             return;
4307           }
4308
4309
4310           lit++;
4311           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4312           i = (lit >> (size*8)) & 0xff;
4313
4314           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4315           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4316
4317           while(size--) {
4318             i = (lit >> (size*8)) & 0xff;
4319
4320             if(i) {
4321               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4322               emitSKPNZ;
4323               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4324             } else {
4325               /* this byte of the lit is zero, 
4326                *if it's not the last then OR in the variable */
4327               if(size)
4328                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4329             }
4330           }
4331
4332
4333           pic16_emitpLabel(lbl->key);
4334
4335           rFalseIfx.condition ^= 1;
4336           genSkipc(&rFalseIfx);
4337         }
4338
4339         if(sign)
4340           pic16_emitpLabel(truelbl->key);
4341         if(ifx) ifx->generated = 1;
4342         return;
4343       }
4344     }
4345     /* Compare two variables */
4346
4347     DEBUGpic16_emitcode(";sign","%d",sign);
4348
4349     size--;
4350     if(sign) {
4351       /* Sigh. thus sucks... */
4352       if(size) {
4353         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4354         pic16_emitpcode(POC_MOVWF, popRegFromIdx(pic16_Gstack_base_addr));
4355         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4356         pic16_emitpcode(POC_XORWF, popRegFromIdx(pic16_Gstack_base_addr));
4357         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4358         pic16_emitpcode(POC_SUBFW, popRegFromIdx(pic16_Gstack_base_addr));
4359       } else {
4360         /* Signed char comparison */
4361         /* Special thanks to Nikolai Golovchenko for this snippet */
4362         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4363         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4364         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4365         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4366         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4367         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4368
4369         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4370         genSkipc(&rFalseIfx);
4371           
4372         if(ifx) ifx->generated = 1;
4373         return;
4374       }
4375
4376     } else {
4377
4378       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4379       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4380     }
4381
4382
4383     /* The rest of the bytes of a multi-byte compare */
4384     while (size) {
4385
4386       emitSKPZ;
4387       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4388       size--;
4389
4390       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4391       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4392
4393
4394     }
4395
4396     pic16_emitpLabel(lbl->key);
4397
4398     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4399     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4400         (AOP_TYPE(result) == AOP_REG)) {
4401       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4402       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4403     } else {
4404       genSkipc(&rFalseIfx);
4405     }         
4406     //genSkipc(&rFalseIfx);
4407     if(ifx) ifx->generated = 1;
4408
4409     return;
4410
4411   }
4412
4413   // check_carry:
4414   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4415     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4416     pic16_outBitC(result);
4417   } else {
4418     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4419     /* if the result is used in the next
4420        ifx conditional branch then generate
4421        code a little differently */
4422     if (ifx )
4423       genIfxJump (ifx,"c");
4424     else
4425       pic16_outBitC(result);
4426     /* leave the result in acc */
4427   }
4428
4429 }
4430
4431 /*-----------------------------------------------------------------*/
4432 /* genCmpGt :- greater than comparison                             */
4433 /*-----------------------------------------------------------------*/
4434 static void genCmpGt (iCode *ic, iCode *ifx)
4435 {
4436     operand *left, *right, *result;
4437     sym_link *letype , *retype;
4438     int sign ;
4439
4440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4441     left = IC_LEFT(ic);
4442     right= IC_RIGHT(ic);
4443     result = IC_RESULT(ic);
4444
4445     letype = getSpec(operandType(left));
4446     retype =getSpec(operandType(right));
4447     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4448     /* assign the amsops */
4449     pic16_aopOp (left,ic,FALSE);
4450     pic16_aopOp (right,ic,FALSE);
4451     pic16_aopOp (result,ic,TRUE);
4452
4453     genCmp(right, left, result, ifx, sign);
4454
4455     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4456     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4457     pic16_freeAsmop(result,NULL,ic,TRUE); 
4458 }
4459
4460 /*-----------------------------------------------------------------*/
4461 /* genCmpLt - less than comparisons                                */
4462 /*-----------------------------------------------------------------*/
4463 static void genCmpLt (iCode *ic, iCode *ifx)
4464 {
4465     operand *left, *right, *result;
4466     sym_link *letype , *retype;
4467     int sign ;
4468
4469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4470     left = IC_LEFT(ic);
4471     right= IC_RIGHT(ic);
4472     result = IC_RESULT(ic);
4473
4474     letype = getSpec(operandType(left));
4475     retype =getSpec(operandType(right));
4476     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4477
4478     /* assign the amsops */
4479     pic16_aopOp (left,ic,FALSE);
4480     pic16_aopOp (right,ic,FALSE);
4481     pic16_aopOp (result,ic,TRUE);
4482
4483     genCmp(left, right, result, ifx, sign);
4484
4485     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4486     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487     pic16_freeAsmop(result,NULL,ic,TRUE); 
4488 }
4489
4490 /*-----------------------------------------------------------------*/
4491 /* genc16bit2lit - compare a 16 bit value to a literal             */
4492 /*-----------------------------------------------------------------*/
4493 static void genc16bit2lit(operand *op, int lit, int offset)
4494 {
4495   int i;
4496
4497   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4498   if( (lit&0xff) == 0) 
4499     i=1;
4500   else
4501     i=0;
4502
4503   switch( BYTEofLONG(lit,i)) { 
4504   case 0:
4505     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4506     break;
4507   case 1:
4508     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4509     break;
4510   case 0xff:
4511     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4512     break;
4513   default:
4514     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4515     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4516   }
4517
4518   i ^= 1;
4519
4520   switch( BYTEofLONG(lit,i)) { 
4521   case 0:
4522     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4523     break;
4524   case 1:
4525     emitSKPNZ;
4526     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4527     break;
4528   case 0xff:
4529     emitSKPNZ;
4530     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4531     break;
4532   default:
4533     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4534     emitSKPNZ;
4535     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4536
4537   }
4538
4539 }
4540
4541 /*-----------------------------------------------------------------*/
4542 /* gencjneshort - compare and jump if not equal                    */
4543 /*-----------------------------------------------------------------*/
4544 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4545 {
4546   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4547   int offset = 0;
4548   int res_offset = 0;  /* the result may be a different size then left or right */
4549   int res_size = AOP_SIZE(result);
4550   resolvedIfx rIfx;
4551   symbol *lbl;
4552
4553   unsigned long lit = 0L;
4554   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4555   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4556   if(result)
4557     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4558   resolveIfx(&rIfx,ifx);
4559   lbl =  newiTempLabel(NULL);
4560
4561
4562   /* if the left side is a literal or 
4563      if the right is in a pointer register and left 
4564      is not */
4565   if ((AOP_TYPE(left) == AOP_LIT) || 
4566       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4567     operand *t = right;
4568     right = left;
4569     left = t;
4570   }
4571   if(AOP_TYPE(right) == AOP_LIT)
4572     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4573
4574   /* if the right side is a literal then anything goes */
4575   if (AOP_TYPE(right) == AOP_LIT &&
4576       AOP_TYPE(left) != AOP_DIR ) {
4577     switch(size) {
4578     case 2:
4579       genc16bit2lit(left, lit, 0);
4580       emitSKPNZ;
4581       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4582       break;
4583     default:
4584       while (size--) {
4585         if(lit & 0xff) {
4586           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4587           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4588         } else {
4589           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4590         }
4591
4592         emitSKPNZ;
4593         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4594         offset++;
4595         if(res_offset < res_size-1)
4596           res_offset++;
4597         lit >>= 8;
4598       }
4599       break;
4600     }
4601   }
4602
4603   /* if the right side is in a register or in direct space or
4604      if the left is a pointer register & right is not */    
4605   else if (AOP_TYPE(right) == AOP_REG ||
4606            AOP_TYPE(right) == AOP_DIR || 
4607            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4608            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4609     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4610     int lbl_key = lbl->key;
4611
4612     if(result) {
4613       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4614       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4615     }else {
4616       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4617       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4618               __FUNCTION__,__LINE__);
4619       return;
4620     }
4621
4622 /*     switch(size) { */
4623 /*     case 2: */
4624 /*       genc16bit2lit(left, lit, 0); */
4625 /*       emitSKPNZ; */
4626 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4627 /*       break; */
4628 /*     default: */
4629     while (size--) {
4630       int emit_skip=1;
4631       if((AOP_TYPE(left) == AOP_DIR) && 
4632          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4633
4634         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4635         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4636
4637       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4638             
4639         switch (lit & 0xff) {
4640         case 0:
4641           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4642           break;
4643         case 1:
4644           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4645           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4646           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4647           emit_skip=0;
4648           break;
4649         case 0xff:
4650           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4651           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4652           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4653           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4654           emit_skip=0;
4655           break;
4656         default:
4657           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4658           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4659         }
4660         lit >>= 8;
4661
4662       } else {
4663         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4664       }
4665       if(emit_skip) {
4666         if(AOP_TYPE(result) == AOP_CRY) {
4667           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4668           if(rIfx.condition)
4669             emitSKPNZ;
4670           else
4671             emitSKPZ;
4672           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4673         } else {
4674           /* fix me. probably need to check result size too */
4675           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4676           if(rIfx.condition)
4677             emitSKPZ;
4678           else
4679             emitSKPNZ;
4680           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4681           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4682         }
4683         if(ifx)
4684           ifx->generated=1;
4685       }
4686       emit_skip++;
4687       offset++;
4688       if(res_offset < res_size-1)
4689         res_offset++;
4690     }
4691 /*       break; */
4692 /*     } */
4693   } else if(AOP_TYPE(right) == AOP_REG &&
4694             AOP_TYPE(left) != AOP_DIR){
4695
4696     while(size--) {
4697       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4698       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4699       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4700       if(rIfx.condition)
4701         emitSKPNZ;
4702       else
4703         emitSKPZ;
4704       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4705       offset++;
4706       if(res_offset < res_size-1)
4707         res_offset++;
4708     }
4709       
4710   }else{
4711     /* right is a pointer reg need both a & b */
4712     while(size--) {
4713       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4714       if(strcmp(l,"b"))
4715         pic16_emitcode("mov","b,%s",l);
4716       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4717       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4718       offset++;
4719     }
4720   }
4721
4722   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4723   if(!rIfx.condition)
4724     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4725
4726   pic16_emitpLabel(lbl->key);
4727
4728   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4729
4730   if(ifx)
4731     ifx->generated = 1;
4732 }
4733
4734 #if 0
4735 /*-----------------------------------------------------------------*/
4736 /* gencjne - compare and jump if not equal                         */
4737 /*-----------------------------------------------------------------*/
4738 static void gencjne(operand *left, operand *right, iCode *ifx)
4739 {
4740     symbol *tlbl  = newiTempLabel(NULL);
4741
4742     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4743     gencjneshort(left, right, lbl);
4744
4745     pic16_emitcode("mov","a,%s",one);
4746     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4747     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4748     pic16_emitcode("clr","a");
4749     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4750
4751     pic16_emitpLabel(lbl->key);
4752     pic16_emitpLabel(tlbl->key);
4753
4754 }
4755 #endif
4756
4757 /*-----------------------------------------------------------------*/
4758 /* genCmpEq - generates code for equal to                          */
4759 /*-----------------------------------------------------------------*/
4760 static void genCmpEq (iCode *ic, iCode *ifx)
4761 {
4762     operand *left, *right, *result;
4763     unsigned long lit = 0L;
4764     int size,offset=0;
4765
4766     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4767
4768     if(ifx)
4769       DEBUGpic16_emitcode ("; ifx is non-null","");
4770     else
4771       DEBUGpic16_emitcode ("; ifx is null","");
4772
4773     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4774     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4775     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4776
4777     size = max(AOP_SIZE(left),AOP_SIZE(right));
4778
4779     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4780
4781     /* if literal, literal on the right or 
4782     if the right is in a pointer register and left 
4783     is not */
4784     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4785         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4786       operand *tmp = right ;
4787       right = left;
4788       left = tmp;
4789     }
4790
4791
4792     if(ifx && !AOP_SIZE(result)){
4793         symbol *tlbl;
4794         /* if they are both bit variables */
4795         if (AOP_TYPE(left) == AOP_CRY &&
4796             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4797             if(AOP_TYPE(right) == AOP_LIT){
4798                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4799                 if(lit == 0L){
4800                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4801                     pic16_emitcode("cpl","c");
4802                 } else if(lit == 1L) {
4803                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4804                 } else {
4805                     pic16_emitcode("clr","c");
4806                 }
4807                 /* AOP_TYPE(right) == AOP_CRY */
4808             } else {
4809                 symbol *lbl = newiTempLabel(NULL);
4810                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4811                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4812                 pic16_emitcode("cpl","c");
4813                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4814             }
4815             /* if true label then we jump if condition
4816             supplied is true */
4817             tlbl = newiTempLabel(NULL);
4818             if ( IC_TRUE(ifx) ) {
4819                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4820                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4821             } else {
4822                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4823                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4824             }
4825             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4826
4827             {
4828               /* left and right are both bit variables, result is carry */
4829               resolvedIfx rIfx;
4830               
4831               resolveIfx(&rIfx,ifx);
4832
4833               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4834               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4835               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4836               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4837               genSkipz2(&rIfx,0);
4838             }
4839         } else {
4840
4841           /* They're not both bit variables. Is the right a literal? */
4842           if(AOP_TYPE(right) == AOP_LIT) {
4843             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4844             
4845             switch(size) {
4846
4847             case 1:
4848               switch(lit & 0xff) {
4849               case 1:
4850                 if ( IC_TRUE(ifx) ) {
4851                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4852                   emitSKPNZ;
4853                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4854                 } else {
4855                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4856                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4857                 }
4858                 break;
4859               case 0xff:
4860                 if ( IC_TRUE(ifx) ) {
4861                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4862                   emitSKPNZ;
4863                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4864                 } else {
4865                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4866                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4867                 }
4868                 break;
4869               default:
4870                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4871                 if(lit)
4872                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4873                 genSkip(ifx,'z');
4874               }
4875
4876
4877               /* end of size == 1 */
4878               break;
4879               
4880             case 2:
4881               genc16bit2lit(left,lit,offset);
4882               genSkip(ifx,'z');
4883               break;
4884               /* end of size == 2 */
4885
4886             default:
4887               /* size is 4 */
4888               if(lit==0) {
4889                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4890                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4891                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4892                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4893
4894               } else {
4895
4896                 /* search for patterns that can be optimized */
4897
4898                 genc16bit2lit(left,lit,0);
4899                 lit >>= 16;
4900                 if(lit) {
4901                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4902                   //genSkip(ifx,'z');
4903                   genc16bit2lit(left,lit,2);
4904                 } else {
4905                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4906                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4907
4908                 }
4909                 
4910               }
4911
4912               genSkip(ifx,'z');
4913             }
4914           
4915             ifx->generated = 1;
4916             goto release ;
4917             
4918
4919           } else if(AOP_TYPE(right) == AOP_CRY ) {
4920             /* we know the left is not a bit, but that the right is */
4921             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4922             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4923                       pic16_popGet(AOP(right),offset));
4924             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4925
4926             /* if the two are equal, then W will be 0 and the Z bit is set
4927              * we could test Z now, or go ahead and check the high order bytes if
4928              * the variable we're comparing is larger than a byte. */
4929
4930             while(--size)
4931               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4932
4933             if ( IC_TRUE(ifx) ) {
4934               emitSKPNZ;
4935               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4936               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4937             } else {
4938               emitSKPZ;
4939               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4940               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4941             }
4942
4943           } else {
4944             /* They're both variables that are larger than bits */
4945             int s = size;
4946
4947             tlbl = newiTempLabel(NULL);
4948
4949             while(size--) {
4950               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4951               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4952
4953               if ( IC_TRUE(ifx) ) {
4954                 if(size) {
4955                   emitSKPZ;
4956                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4957                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4958                 } else {
4959                   emitSKPNZ;
4960                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4961                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4962                 }
4963               } else {
4964                 emitSKPZ;
4965                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4966                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4967               }
4968               offset++;
4969             }
4970             if(s>1 && IC_TRUE(ifx)) {
4971               pic16_emitpLabel(tlbl->key);
4972               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4973             }
4974           }
4975         }
4976         /* mark the icode as generated */
4977         ifx->generated = 1;
4978         goto release ;
4979     }
4980
4981     /* if they are both bit variables */
4982     if (AOP_TYPE(left) == AOP_CRY &&
4983         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4984         if(AOP_TYPE(right) == AOP_LIT){
4985             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4986             if(lit == 0L){
4987                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4988                 pic16_emitcode("cpl","c");
4989             } else if(lit == 1L) {
4990                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4991             } else {
4992                 pic16_emitcode("clr","c");
4993             }
4994             /* AOP_TYPE(right) == AOP_CRY */
4995         } else {
4996             symbol *lbl = newiTempLabel(NULL);
4997             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4998             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4999             pic16_emitcode("cpl","c");
5000             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5001         }
5002         /* c = 1 if egal */
5003         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5004             pic16_outBitC(result);
5005             goto release ;
5006         }
5007         if (ifx) {
5008             genIfxJump (ifx,"c");
5009             goto release ;
5010         }
5011         /* if the result is used in an arithmetic operation
5012         then put the result in place */
5013         pic16_outBitC(result);
5014     } else {
5015       
5016       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5017       gencjne(left,right,result,ifx);
5018 /*
5019       if(ifx) 
5020         gencjne(left,right,newiTempLabel(NULL));
5021       else {
5022         if(IC_TRUE(ifx)->key)
5023           gencjne(left,right,IC_TRUE(ifx)->key);
5024         else
5025           gencjne(left,right,IC_FALSE(ifx)->key);
5026         ifx->generated = 1;
5027         goto release ;
5028       }
5029       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5030         pic16_aopPut(AOP(result),"a",0);
5031         goto release ;
5032       }
5033
5034       if (ifx) {
5035         genIfxJump (ifx,"a");
5036         goto release ;
5037       }
5038 */
5039       /* if the result is used in an arithmetic operation
5040          then put the result in place */
5041 /*
5042       if (AOP_TYPE(result) != AOP_CRY) 
5043         pic16_outAcc(result);
5044 */
5045       /* leave the result in acc */
5046     }
5047
5048 release:
5049     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5050     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5051     pic16_freeAsmop(result,NULL,ic,TRUE);
5052 }
5053
5054 /*-----------------------------------------------------------------*/
5055 /* ifxForOp - returns the icode containing the ifx for operand     */
5056 /*-----------------------------------------------------------------*/
5057 static iCode *ifxForOp ( operand *op, iCode *ic )
5058 {
5059     /* if true symbol then needs to be assigned */
5060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5061     if (IS_TRUE_SYMOP(op))
5062         return NULL ;
5063
5064     /* if this has register type condition and
5065     the next instruction is ifx with the same operand
5066     and live to of the operand is upto the ifx only then */
5067     if (ic->next &&
5068         ic->next->op == IFX &&
5069         IC_COND(ic->next)->key == op->key &&
5070         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5071         return ic->next;
5072
5073     if (ic->next &&
5074         ic->next->op == IFX &&
5075         IC_COND(ic->next)->key == op->key) {
5076       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5077       return ic->next;
5078     }
5079
5080     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5081     if (ic->next &&
5082         ic->next->op == IFX)
5083       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5084
5085     if (ic->next &&
5086         ic->next->op == IFX &&
5087         IC_COND(ic->next)->key == op->key) {
5088       DEBUGpic16_emitcode ("; "," key is okay");
5089       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5090                            OP_SYMBOL(op)->liveTo,
5091                            ic->next->seq);
5092     }
5093
5094
5095     return NULL;
5096 }
5097 /*-----------------------------------------------------------------*/
5098 /* genAndOp - for && operation                                     */
5099 /*-----------------------------------------------------------------*/
5100 static void genAndOp (iCode *ic)
5101 {
5102     operand *left,*right, *result;
5103 /*     symbol *tlbl; */
5104
5105     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5106     /* note here that && operations that are in an
5107     if statement are taken away by backPatchLabels
5108     only those used in arthmetic operations remain */
5109     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5110     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5111     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5112
5113     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5114
5115     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5116     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5117     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5118
5119     /* if both are bit variables */
5120 /*     if (AOP_TYPE(left) == AOP_CRY && */
5121 /*         AOP_TYPE(right) == AOP_CRY ) { */
5122 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5123 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5124 /*         pic16_outBitC(result); */
5125 /*     } else { */
5126 /*         tlbl = newiTempLabel(NULL); */
5127 /*         pic16_toBoolean(left);     */
5128 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5129 /*         pic16_toBoolean(right); */
5130 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5131 /*         pic16_outBitAcc(result); */
5132 /*     } */
5133
5134     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5135     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5136     pic16_freeAsmop(result,NULL,ic,TRUE);
5137 }
5138
5139
5140 /*-----------------------------------------------------------------*/
5141 /* genOrOp - for || operation                                      */
5142 /*-----------------------------------------------------------------*/
5143 /*
5144   tsd pic port -
5145   modified this code, but it doesn't appear to ever get called
5146 */
5147
5148 static void genOrOp (iCode *ic)
5149 {
5150     operand *left,*right, *result;
5151     symbol *tlbl;
5152
5153     /* note here that || operations that are in an
5154     if statement are taken away by backPatchLabels
5155     only those used in arthmetic operations remain */
5156     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5157     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5158     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5159     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5160
5161     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5162
5163     /* if both are bit variables */
5164     if (AOP_TYPE(left) == AOP_CRY &&
5165         AOP_TYPE(right) == AOP_CRY ) {
5166       pic16_emitcode("clrc","");
5167       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5168                AOP(left)->aopu.aop_dir,
5169                AOP(left)->aopu.aop_dir);
5170       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5171                AOP(right)->aopu.aop_dir,
5172                AOP(right)->aopu.aop_dir);
5173       pic16_emitcode("setc","");
5174
5175     } else {
5176         tlbl = newiTempLabel(NULL);
5177         pic16_toBoolean(left);
5178         emitSKPZ;
5179         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5180         pic16_toBoolean(right);
5181         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5182
5183         pic16_outBitAcc(result);
5184     }
5185
5186     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5187     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5188     pic16_freeAsmop(result,NULL,ic,TRUE);            
5189 }
5190
5191 /*-----------------------------------------------------------------*/
5192 /* isLiteralBit - test if lit == 2^n                               */
5193 /*-----------------------------------------------------------------*/
5194 static int isLiteralBit(unsigned long lit)
5195 {
5196     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5197     0x100L,0x200L,0x400L,0x800L,
5198     0x1000L,0x2000L,0x4000L,0x8000L,
5199     0x10000L,0x20000L,0x40000L,0x80000L,
5200     0x100000L,0x200000L,0x400000L,0x800000L,
5201     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5202     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5203     int idx;
5204     
5205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206     for(idx = 0; idx < 32; idx++)
5207         if(lit == pw[idx])
5208             return idx+1;
5209     return 0;
5210 }
5211
5212 /*-----------------------------------------------------------------*/
5213 /* continueIfTrue -                                                */
5214 /*-----------------------------------------------------------------*/
5215 static void continueIfTrue (iCode *ic)
5216 {
5217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5218     if(IC_TRUE(ic))
5219         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5220     ic->generated = 1;
5221 }
5222
5223 /*-----------------------------------------------------------------*/
5224 /* jmpIfTrue -                                                     */
5225 /*-----------------------------------------------------------------*/
5226 static void jumpIfTrue (iCode *ic)
5227 {
5228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5229     if(!IC_TRUE(ic))
5230         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5231     ic->generated = 1;
5232 }
5233
5234 /*-----------------------------------------------------------------*/
5235 /* jmpTrueOrFalse -                                                */
5236 /*-----------------------------------------------------------------*/
5237 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5238 {
5239     // ugly but optimized by peephole
5240     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5241     if(IC_TRUE(ic)){
5242         symbol *nlbl = newiTempLabel(NULL);
5243         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5244         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5245         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5246         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5247     }
5248     else{
5249         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5250         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5251     }
5252     ic->generated = 1;
5253 }
5254
5255 /*-----------------------------------------------------------------*/
5256 /* genAnd  - code for and                                          */
5257 /*-----------------------------------------------------------------*/
5258 static void genAnd (iCode *ic, iCode *ifx)
5259 {
5260   operand *left, *right, *result;
5261   int size, offset=0;  
5262   unsigned long lit = 0L;
5263   int bytelit = 0;
5264   resolvedIfx rIfx;
5265
5266
5267   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5268   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5269   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5270   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5271
5272   resolveIfx(&rIfx,ifx);
5273
5274   /* if left is a literal & right is not then exchange them */
5275   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5276       AOP_NEEDSACC(left)) {
5277     operand *tmp = right ;
5278     right = left;
5279     left = tmp;
5280   }
5281
5282   /* if result = right then exchange them */
5283   if(pic16_sameRegs(AOP(result),AOP(right))){
5284     operand *tmp = right ;
5285     right = left;
5286     left = tmp;
5287   }
5288
5289   /* if right is bit then exchange them */
5290   if (AOP_TYPE(right) == AOP_CRY &&
5291       AOP_TYPE(left) != AOP_CRY){
5292     operand *tmp = right ;
5293     right = left;
5294     left = tmp;
5295   }
5296   if(AOP_TYPE(right) == AOP_LIT)
5297     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5298
5299   size = AOP_SIZE(result);
5300
5301   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5302
5303   // if(bit & yy)
5304   // result = bit & yy;
5305   if (AOP_TYPE(left) == AOP_CRY){
5306     // c = bit & literal;
5307     if(AOP_TYPE(right) == AOP_LIT){
5308       if(lit & 1) {
5309         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5310           // no change
5311           goto release;
5312         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5313       } else {
5314         // bit(result) = 0;
5315         if(size && (AOP_TYPE(result) == AOP_CRY)){
5316           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5317           goto release;
5318         }
5319         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5320           jumpIfTrue(ifx);
5321           goto release;
5322         }
5323         pic16_emitcode("clr","c");
5324       }
5325     } else {
5326       if (AOP_TYPE(right) == AOP_CRY){
5327         // c = bit & bit;
5328         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5329         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5330       } else {
5331         // c = bit & val;
5332         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5333         // c = lsb
5334         pic16_emitcode("rrc","a");
5335         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5336       }
5337     }
5338     // bit = c
5339     // val = c
5340     if(size)
5341       pic16_outBitC(result);
5342     // if(bit & ...)
5343     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5344       genIfxJump(ifx, "c");           
5345     goto release ;
5346   }
5347
5348   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5349   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5350   if((AOP_TYPE(right) == AOP_LIT) &&
5351      (AOP_TYPE(result) == AOP_CRY) &&
5352      (AOP_TYPE(left) != AOP_CRY)){
5353     int posbit = isLiteralBit(lit);
5354     /* left &  2^n */
5355     if(posbit){
5356       posbit--;
5357       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5358       // bit = left & 2^n
5359       if(size)
5360         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5361       // if(left &  2^n)
5362       else{
5363         if(ifx){
5364 /*
5365           if(IC_TRUE(ifx)) {
5366             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5367             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5368           } else {
5369             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5370             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5371           }
5372 */
5373           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5374                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5375           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5376           
5377           ifx->generated = 1;
5378         }
5379         goto release;
5380       }
5381     } else {
5382       symbol *tlbl = newiTempLabel(NULL);
5383       int sizel = AOP_SIZE(left);
5384       if(size)
5385         pic16_emitcode("setb","c");
5386       while(sizel--){
5387         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5388           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5389           // byte ==  2^n ?
5390           if((posbit = isLiteralBit(bytelit)) != 0)
5391             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5392           else{
5393             if(bytelit != 0x0FFL)
5394               pic16_emitcode("anl","a,%s",
5395                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5396             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5397           }
5398         }
5399         offset++;
5400       }
5401       // bit = left & literal
5402       if(size){
5403         pic16_emitcode("clr","c");
5404         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5405       }
5406       // if(left & literal)
5407       else{
5408         if(ifx)
5409           jmpTrueOrFalse(ifx, tlbl);
5410         goto release ;
5411       }
5412     }
5413     pic16_outBitC(result);
5414     goto release ;
5415   }
5416
5417   /* if left is same as result */
5418   if(pic16_sameRegs(AOP(result),AOP(left))){
5419     int know_W = -1;
5420     for(;size--; offset++,lit>>=8) {
5421       if(AOP_TYPE(right) == AOP_LIT){
5422         switch(lit & 0xff) {
5423         case 0x00:
5424           /*  and'ing with 0 has clears the result */
5425 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5426           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5427           break;
5428         case 0xff:
5429           /* and'ing with 0xff is a nop when the result and left are the same */
5430           break;
5431
5432         default:
5433           {
5434             int p = my_powof2( (~lit) & 0xff );
5435             if(p>=0) {
5436               /* only one bit is set in the literal, so use a bcf instruction */
5437 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5438               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5439
5440             } else {
5441               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5442               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5443               if(know_W != (lit&0xff))
5444                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5445               know_W = lit &0xff;
5446               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5447             }
5448           }    
5449         }
5450       } else {
5451         if (AOP_TYPE(left) == AOP_ACC) {
5452           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5453         } else {                    
5454           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5455           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5456
5457         }
5458       }
5459     }
5460
5461   } else {
5462     // left & result in different registers
5463     if(AOP_TYPE(result) == AOP_CRY){
5464       // result = bit
5465       // if(size), result in bit
5466       // if(!size && ifx), conditional oper: if(left & right)
5467       symbol *tlbl = newiTempLabel(NULL);
5468       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5469       if(size)
5470         pic16_emitcode("setb","c");
5471       while(sizer--){
5472         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5473         pic16_emitcode("anl","a,%s",
5474                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5475         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5476         offset++;
5477       }
5478       if(size){
5479         CLRC;
5480         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5481         pic16_outBitC(result);
5482       } else if(ifx)
5483         jmpTrueOrFalse(ifx, tlbl);
5484     } else {
5485       for(;(size--);offset++) {
5486         // normal case
5487         // result = left & right
5488         if(AOP_TYPE(right) == AOP_LIT){
5489           int t = (lit >> (offset*8)) & 0x0FFL;
5490           switch(t) { 
5491           case 0x00:
5492             pic16_emitcode("clrf","%s",
5493                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5494             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5495             break;
5496           case 0xff:
5497             pic16_emitcode("movf","%s,w",
5498                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5499             pic16_emitcode("movwf","%s",
5500                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5501             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5502             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5503             break;
5504           default:
5505             pic16_emitcode("movlw","0x%x",t);
5506             pic16_emitcode("andwf","%s,w",
5507                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5508             pic16_emitcode("movwf","%s",
5509                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5510               
5511             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5512             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5513             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5514           }
5515           continue;
5516         }
5517
5518         if (AOP_TYPE(left) == AOP_ACC) {
5519           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5520           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5521         } else {
5522           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5523           pic16_emitcode("andwf","%s,w",
5524                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5525           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5526           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5527         }
5528         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5529         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5530       }
5531     }
5532   }
5533
5534   release :
5535     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5536   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5537   pic16_freeAsmop(result,NULL,ic,TRUE);     
5538 }
5539
5540 /*-----------------------------------------------------------------*/
5541 /* genOr  - code for or                                            */
5542 /*-----------------------------------------------------------------*/
5543 static void genOr (iCode *ic, iCode *ifx)
5544 {
5545     operand *left, *right, *result;
5546     int size, offset=0;
5547     unsigned long lit = 0L;
5548
5549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5550
5551     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5552     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5553     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5554
5555     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5556
5557     /* if left is a literal & right is not then exchange them */
5558     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5559         AOP_NEEDSACC(left)) {
5560         operand *tmp = right ;
5561         right = left;
5562         left = tmp;
5563     }
5564
5565     /* if result = right then exchange them */
5566     if(pic16_sameRegs(AOP(result),AOP(right))){
5567         operand *tmp = right ;
5568         right = left;
5569         left = tmp;
5570     }
5571
5572     /* if right is bit then exchange them */
5573     if (AOP_TYPE(right) == AOP_CRY &&
5574         AOP_TYPE(left) != AOP_CRY){
5575         operand *tmp = right ;
5576         right = left;
5577         left = tmp;
5578     }
5579
5580     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5581
5582     if(AOP_TYPE(right) == AOP_LIT)
5583         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5584
5585     size = AOP_SIZE(result);
5586
5587     // if(bit | yy)
5588     // xx = bit | yy;
5589     if (AOP_TYPE(left) == AOP_CRY){
5590         if(AOP_TYPE(right) == AOP_LIT){
5591             // c = bit & literal;
5592             if(lit){
5593                 // lit != 0 => result = 1
5594                 if(AOP_TYPE(result) == AOP_CRY){
5595                   if(size)
5596                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5597                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5598                   //     AOP(result)->aopu.aop_dir,
5599                   //     AOP(result)->aopu.aop_dir);
5600                     else if(ifx)
5601                         continueIfTrue(ifx);
5602                     goto release;
5603                 }
5604             } else {
5605                 // lit == 0 => result = left
5606                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5607                     goto release;
5608                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5609             }
5610         } else {
5611             if (AOP_TYPE(right) == AOP_CRY){
5612               if(pic16_sameRegs(AOP(result),AOP(left))){
5613                 // c = bit | bit;
5614                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5615                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5616                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5617
5618                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5619                          AOP(result)->aopu.aop_dir,
5620                          AOP(result)->aopu.aop_dir);
5621                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5622                          AOP(right)->aopu.aop_dir,
5623                          AOP(right)->aopu.aop_dir);
5624                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5625                          AOP(result)->aopu.aop_dir,
5626                          AOP(result)->aopu.aop_dir);
5627               } else {
5628                 if( AOP_TYPE(result) == AOP_ACC) {
5629                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5630                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5631                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5632                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5633
5634                 } else {
5635
5636                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5637                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5638                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5639                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5640
5641                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5642                                  AOP(result)->aopu.aop_dir,
5643                                  AOP(result)->aopu.aop_dir);
5644                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5645                                  AOP(right)->aopu.aop_dir,
5646                                  AOP(right)->aopu.aop_dir);
5647                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5648                                  AOP(left)->aopu.aop_dir,
5649                                  AOP(left)->aopu.aop_dir);
5650                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5651                                  AOP(result)->aopu.aop_dir,
5652                                  AOP(result)->aopu.aop_dir);
5653                 }
5654               }
5655             } else {
5656                 // c = bit | val;
5657                 symbol *tlbl = newiTempLabel(NULL);
5658                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5659
5660
5661                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5662                 if( AOP_TYPE(right) == AOP_ACC) {
5663                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5664                   emitSKPNZ;
5665                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5666                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5667                 }
5668
5669
5670
5671                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5672                     pic16_emitcode(";XXX setb","c");
5673                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5674                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5675                 pic16_toBoolean(right);
5676                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5677                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5678                     jmpTrueOrFalse(ifx, tlbl);
5679                     goto release;
5680                 } else {
5681                     CLRC;
5682                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5683                 }
5684             }
5685         }
5686         // bit = c
5687         // val = c
5688         if(size)
5689             pic16_outBitC(result);
5690         // if(bit | ...)
5691         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5692             genIfxJump(ifx, "c");           
5693         goto release ;
5694     }
5695
5696     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5697     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5698     if((AOP_TYPE(right) == AOP_LIT) &&
5699        (AOP_TYPE(result) == AOP_CRY) &&
5700        (AOP_TYPE(left) != AOP_CRY)){
5701         if(lit){
5702           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5703             // result = 1
5704             if(size)
5705                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5706             else 
5707                 continueIfTrue(ifx);
5708             goto release;
5709         } else {
5710           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5711             // lit = 0, result = boolean(left)
5712             if(size)
5713                 pic16_emitcode(";XXX setb","c");
5714             pic16_toBoolean(right);
5715             if(size){
5716                 symbol *tlbl = newiTempLabel(NULL);
5717                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5718                 CLRC;
5719                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5720             } else {
5721                 genIfxJump (ifx,"a");
5722                 goto release;
5723             }
5724         }
5725         pic16_outBitC(result);
5726         goto release ;
5727     }
5728
5729     /* if left is same as result */
5730     if(pic16_sameRegs(AOP(result),AOP(left))){
5731       int know_W = -1;
5732       for(;size--; offset++,lit>>=8) {
5733         if(AOP_TYPE(right) == AOP_LIT){
5734           if((lit & 0xff) == 0)
5735             /*  or'ing with 0 has no effect */
5736             continue;
5737           else {
5738             int p = my_powof2(lit & 0xff);
5739             if(p>=0) {
5740               /* only one bit is set in the literal, so use a bsf instruction */
5741               pic16_emitpcode(POC_BSF,
5742                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5743             } else {
5744               if(know_W != (lit & 0xff))
5745                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5746               know_W = lit & 0xff;
5747               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5748             }
5749                     
5750           }
5751         } else {
5752           if (AOP_TYPE(left) == AOP_ACC) {
5753             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5754             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5755           } else {                  
5756             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5757             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5758
5759             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5760             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5761
5762           }
5763         }
5764       }
5765     } else {
5766         // left & result in different registers
5767         if(AOP_TYPE(result) == AOP_CRY){
5768             // result = bit
5769             // if(size), result in bit
5770             // if(!size && ifx), conditional oper: if(left | right)
5771             symbol *tlbl = newiTempLabel(NULL);
5772             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5773             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5774
5775
5776             if(size)
5777                 pic16_emitcode(";XXX setb","c");
5778             while(sizer--){
5779                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5780                 pic16_emitcode(";XXX orl","a,%s",
5781                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5782                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5783                 offset++;
5784             }
5785             if(size){
5786                 CLRC;
5787                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5788                 pic16_outBitC(result);
5789             } else if(ifx)
5790                 jmpTrueOrFalse(ifx, tlbl);
5791         } else for(;(size--);offset++){
5792           // normal case
5793           // result = left & right
5794           if(AOP_TYPE(right) == AOP_LIT){
5795             int t = (lit >> (offset*8)) & 0x0FFL;
5796             switch(t) { 
5797             case 0x00:
5798               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5799               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5800
5801               pic16_emitcode("movf","%s,w",
5802                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5803               pic16_emitcode("movwf","%s",
5804                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5805               break;
5806             default:
5807               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5808               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5809               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5810
5811               pic16_emitcode("movlw","0x%x",t);
5812               pic16_emitcode("iorwf","%s,w",
5813                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5814               pic16_emitcode("movwf","%s",
5815                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5816               
5817             }
5818             continue;
5819           }
5820
5821           // faster than result <- left, anl result,right
5822           // and better if result is SFR
5823           if (AOP_TYPE(left) == AOP_ACC) {
5824             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5825             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5826           } else {
5827             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5828             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5829
5830             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5831             pic16_emitcode("iorwf","%s,w",
5832                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5833           }
5834           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5835           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5836         }
5837     }
5838
5839 release :
5840     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5841     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5842     pic16_freeAsmop(result,NULL,ic,TRUE);     
5843 }
5844
5845 /*-----------------------------------------------------------------*/
5846 /* genXor - code for xclusive or                                   */
5847 /*-----------------------------------------------------------------*/
5848 static void genXor (iCode *ic, iCode *ifx)
5849 {
5850   operand *left, *right, *result;
5851   int size, offset=0;
5852   unsigned long lit = 0L;
5853
5854   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5855
5856   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5857   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5858   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5859
5860   /* if left is a literal & right is not ||
5861      if left needs acc & right does not */
5862   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5863       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5864     operand *tmp = right ;
5865     right = left;
5866     left = tmp;
5867   }
5868
5869   /* if result = right then exchange them */
5870   if(pic16_sameRegs(AOP(result),AOP(right))){
5871     operand *tmp = right ;
5872     right = left;
5873     left = tmp;
5874   }
5875
5876   /* if right is bit then exchange them */
5877   if (AOP_TYPE(right) == AOP_CRY &&
5878       AOP_TYPE(left) != AOP_CRY){
5879     operand *tmp = right ;
5880     right = left;
5881     left = tmp;
5882   }
5883   if(AOP_TYPE(right) == AOP_LIT)
5884     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5885
5886   size = AOP_SIZE(result);
5887
5888   // if(bit ^ yy)
5889   // xx = bit ^ yy;
5890   if (AOP_TYPE(left) == AOP_CRY){
5891     if(AOP_TYPE(right) == AOP_LIT){
5892       // c = bit & literal;
5893       if(lit>>1){
5894         // lit>>1  != 0 => result = 1
5895         if(AOP_TYPE(result) == AOP_CRY){
5896           if(size)
5897             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
5898             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5899           else if(ifx)
5900             continueIfTrue(ifx);
5901           goto release;
5902         }
5903         pic16_emitcode("setb","c");
5904       } else{
5905         // lit == (0 or 1)
5906         if(lit == 0){
5907           // lit == 0, result = left
5908           if(size && pic16_sameRegs(AOP(result),AOP(left)))
5909             goto release;
5910           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5911         } else{
5912           // lit == 1, result = not(left)
5913           if(size && pic16_sameRegs(AOP(result),AOP(left))){
5914             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
5915             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
5916             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5917             goto release;
5918           } else {
5919             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5920             pic16_emitcode("cpl","c");
5921           }
5922         }
5923       }
5924
5925     } else {
5926       // right != literal
5927       symbol *tlbl = newiTempLabel(NULL);
5928       if (AOP_TYPE(right) == AOP_CRY){
5929         // c = bit ^ bit;
5930         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5931       }
5932       else{
5933         int sizer = AOP_SIZE(right);
5934         // c = bit ^ val
5935         // if val>>1 != 0, result = 1
5936         pic16_emitcode("setb","c");
5937         while(sizer){
5938           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
5939           if(sizer == 1)
5940             // test the msb of the lsb
5941             pic16_emitcode("anl","a,#0xfe");
5942           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5943           sizer--;
5944         }
5945         // val = (0,1)
5946         pic16_emitcode("rrc","a");
5947       }
5948       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5949       pic16_emitcode("cpl","c");
5950       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
5951     }
5952     // bit = c
5953     // val = c
5954     if(size)
5955       pic16_outBitC(result);
5956     // if(bit | ...)
5957     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5958       genIfxJump(ifx, "c");           
5959     goto release ;
5960   }
5961
5962   if(pic16_sameRegs(AOP(result),AOP(left))){
5963     /* if left is same as result */
5964     for(;size--; offset++) {
5965       if(AOP_TYPE(right) == AOP_LIT){
5966         int t  = (lit >> (offset*8)) & 0x0FFL;
5967         if(t == 0x00L)
5968           continue;
5969         else
5970           if (IS_AOP_PREG(left)) {
5971             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5972             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5973             pic16_aopPut(AOP(result),"a",offset);
5974           } else {
5975             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5976             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5977             pic16_emitcode("xrl","%s,%s",
5978                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
5979                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5980           }
5981       } else {
5982         if (AOP_TYPE(left) == AOP_ACC)
5983           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5984         else {
5985           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5986           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
5987 /*
5988           if (IS_AOP_PREG(left)) {
5989             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5990             pic16_aopPut(AOP(result),"a",offset);
5991           } else
5992             pic16_emitcode("xrl","%s,a",
5993                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5994 */
5995         }
5996       }
5997     }
5998   } else {
5999     // left & result in different registers
6000     if(AOP_TYPE(result) == AOP_CRY){
6001       // result = bit
6002       // if(size), result in bit
6003       // if(!size && ifx), conditional oper: if(left ^ right)
6004       symbol *tlbl = newiTempLabel(NULL);
6005       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6006       if(size)
6007         pic16_emitcode("setb","c");
6008       while(sizer--){
6009         if((AOP_TYPE(right) == AOP_LIT) &&
6010            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6011           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6012         } else {
6013           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6014           pic16_emitcode("xrl","a,%s",
6015                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6016         }
6017         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6018         offset++;
6019       }
6020       if(size){
6021         CLRC;
6022         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6023         pic16_outBitC(result);
6024       } else if(ifx)
6025         jmpTrueOrFalse(ifx, tlbl);
6026     } else for(;(size--);offset++){
6027       // normal case
6028       // result = left & right
6029       if(AOP_TYPE(right) == AOP_LIT){
6030         int t = (lit >> (offset*8)) & 0x0FFL;
6031         switch(t) { 
6032         case 0x00:
6033           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6034           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6035           pic16_emitcode("movf","%s,w",
6036                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6037           pic16_emitcode("movwf","%s",
6038                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6039           break;
6040         case 0xff:
6041           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6042           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6043           pic16_emitcode("comf","%s,w",
6044                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6045           pic16_emitcode("movwf","%s",
6046                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6047           break;
6048         default:
6049           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6050           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6051           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6052           pic16_emitcode("movlw","0x%x",t);
6053           pic16_emitcode("xorwf","%s,w",
6054                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6055           pic16_emitcode("movwf","%s",
6056                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6057
6058         }
6059         continue;
6060       }
6061
6062       // faster than result <- left, anl result,right
6063       // and better if result is SFR
6064       if (AOP_TYPE(left) == AOP_ACC) {
6065         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6066         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6067       } else {
6068         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6069         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6070         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6071         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6072       }
6073       if ( AOP_TYPE(result) != AOP_ACC){
6074         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6075         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6076       }
6077     }
6078   }
6079
6080   release :
6081     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6082   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6083   pic16_freeAsmop(result,NULL,ic,TRUE);     
6084 }
6085
6086 /*-----------------------------------------------------------------*/
6087 /* genInline - write the inline code out                           */
6088 /*-----------------------------------------------------------------*/
6089 static void genInline (iCode *ic)
6090 {
6091     char *buffer, *bp, *bp1;
6092     
6093     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6094
6095     _G.inLine += (!options.asmpeep);
6096
6097     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6098     strcpy(buffer,IC_INLINE(ic));
6099
6100     /* emit each line as a code */
6101     while (*bp) {
6102         if (*bp == '\n') {
6103             *bp++ = '\0';
6104
6105             if(*bp1)
6106               pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6107             bp1 = bp;
6108         } else {
6109             if (*bp == ':') {
6110                 bp++;
6111                 *bp = '\0';
6112                 bp++;
6113                 pic16_emitcode(bp1,"");
6114                 bp1 = bp;
6115             } else
6116                 bp++;
6117         }
6118     }
6119     if ((bp1 != bp) && *bp1)
6120       pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6121
6122     Safe_free(buffer);
6123
6124     _G.inLine -= (!options.asmpeep);
6125 }
6126
6127 /*-----------------------------------------------------------------*/
6128 /* genRRC - rotate right with carry                                */
6129 /*-----------------------------------------------------------------*/
6130 static void genRRC (iCode *ic)
6131 {
6132   operand *left , *result ;
6133   int size, offset = 0, same;
6134
6135   /* rotate right with carry */
6136   left = IC_LEFT(ic);
6137   result=IC_RESULT(ic);
6138   pic16_aopOp (left,ic,FALSE);
6139   pic16_aopOp (result,ic,FALSE);
6140
6141   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6142
6143   same = pic16_sameRegs(AOP(result),AOP(left));
6144
6145   size = AOP_SIZE(result);    
6146
6147   /* get the lsb and put it into the carry */
6148   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6149
6150   offset = 0 ;
6151
6152   while(size--) {
6153
6154     if(same) {
6155       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6156     } else {
6157       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6158       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6159     }
6160
6161     offset++;
6162   }
6163
6164   pic16_freeAsmop(left,NULL,ic,TRUE);
6165   pic16_freeAsmop(result,NULL,ic,TRUE);
6166 }
6167
6168 /*-----------------------------------------------------------------*/
6169 /* genRLC - generate code for rotate left with carry               */
6170 /*-----------------------------------------------------------------*/
6171 static void genRLC (iCode *ic)
6172 {    
6173   operand *left , *result ;
6174   int size, offset = 0;
6175   int same;
6176
6177   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6178   /* rotate right with carry */
6179   left = IC_LEFT(ic);
6180   result=IC_RESULT(ic);
6181   pic16_aopOp (left,ic,FALSE);
6182   pic16_aopOp (result,ic,FALSE);
6183
6184   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6185
6186   same = pic16_sameRegs(AOP(result),AOP(left));
6187
6188   /* move it to the result */
6189   size = AOP_SIZE(result);    
6190
6191   /* get the msb and put it into the carry */
6192   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6193
6194   offset = 0 ;
6195
6196   while(size--) {
6197
6198     if(same) {
6199       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6200     } else {
6201       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6202       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6203     }
6204
6205     offset++;
6206   }
6207
6208
6209   pic16_freeAsmop(left,NULL,ic,TRUE);
6210   pic16_freeAsmop(result,NULL,ic,TRUE);
6211 }
6212
6213 /*-----------------------------------------------------------------*/
6214 /* genGetHbit - generates code get highest order bit               */
6215 /*-----------------------------------------------------------------*/
6216 static void genGetHbit (iCode *ic)
6217 {
6218     operand *left, *result;
6219     left = IC_LEFT(ic);
6220     result=IC_RESULT(ic);
6221     pic16_aopOp (left,ic,FALSE);
6222     pic16_aopOp (result,ic,FALSE);
6223
6224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6225     /* get the highest order byte into a */
6226     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6227     if(AOP_TYPE(result) == AOP_CRY){
6228         pic16_emitcode("rlc","a");
6229         pic16_outBitC(result);
6230     }
6231     else{
6232         pic16_emitcode("rl","a");
6233         pic16_emitcode("anl","a,#0x01");
6234         pic16_outAcc(result);
6235     }
6236
6237
6238     pic16_freeAsmop(left,NULL,ic,TRUE);
6239     pic16_freeAsmop(result,NULL,ic,TRUE);
6240 }
6241
6242 /*-----------------------------------------------------------------*/
6243 /* AccRol - rotate left accumulator by known count                 */
6244 /*-----------------------------------------------------------------*/
6245 static void AccRol (int shCount)
6246 {
6247     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6248     shCount &= 0x0007;              // shCount : 0..7
6249     switch(shCount){
6250         case 0 :
6251             break;
6252         case 1 :
6253             pic16_emitcode("rl","a");
6254             break;
6255         case 2 :
6256             pic16_emitcode("rl","a");
6257             pic16_emitcode("rl","a");
6258             break;
6259         case 3 :
6260             pic16_emitcode("swap","a");
6261             pic16_emitcode("rr","a");
6262             break;
6263         case 4 :
6264             pic16_emitcode("swap","a");
6265             break;
6266         case 5 :
6267             pic16_emitcode("swap","a");
6268             pic16_emitcode("rl","a");
6269             break;
6270         case 6 :
6271             pic16_emitcode("rr","a");
6272             pic16_emitcode("rr","a");
6273             break;
6274         case 7 :
6275             pic16_emitcode("rr","a");
6276             break;
6277     }
6278 }
6279
6280 /*-----------------------------------------------------------------*/
6281 /* AccLsh - left shift accumulator by known count                  */
6282 /*-----------------------------------------------------------------*/
6283 static void AccLsh (int shCount)
6284 {
6285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6286     if(shCount != 0){
6287         if(shCount == 1)
6288             pic16_emitcode("add","a,acc");
6289         else 
6290             if(shCount == 2) {
6291             pic16_emitcode("add","a,acc");
6292             pic16_emitcode("add","a,acc");
6293         } else {
6294             /* rotate left accumulator */
6295             AccRol(shCount);
6296             /* and kill the lower order bits */
6297             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6298         }
6299     }
6300 }
6301
6302 /*-----------------------------------------------------------------*/
6303 /* AccRsh - right shift accumulator by known count                 */
6304 /*-----------------------------------------------------------------*/
6305 static void AccRsh (int shCount)
6306 {
6307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6308     if(shCount != 0){
6309         if(shCount == 1){
6310             CLRC;
6311             pic16_emitcode("rrc","a");
6312         } else {
6313             /* rotate right accumulator */
6314             AccRol(8 - shCount);
6315             /* and kill the higher order bits */
6316             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6317         }
6318     }
6319 }
6320
6321 #if 0
6322 /*-----------------------------------------------------------------*/
6323 /* AccSRsh - signed right shift accumulator by known count                 */
6324 /*-----------------------------------------------------------------*/
6325 static void AccSRsh (int shCount)
6326 {
6327     symbol *tlbl ;
6328     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6329     if(shCount != 0){
6330         if(shCount == 1){
6331             pic16_emitcode("mov","c,acc.7");
6332             pic16_emitcode("rrc","a");
6333         } else if(shCount == 2){
6334             pic16_emitcode("mov","c,acc.7");
6335             pic16_emitcode("rrc","a");
6336             pic16_emitcode("mov","c,acc.7");
6337             pic16_emitcode("rrc","a");
6338         } else {
6339             tlbl = newiTempLabel(NULL);
6340             /* rotate right accumulator */
6341             AccRol(8 - shCount);
6342             /* and kill the higher order bits */
6343             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6344             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6345             pic16_emitcode("orl","a,#0x%02x",
6346                      (unsigned char)~SRMask[shCount]);
6347             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6348         }
6349     }
6350 }
6351 #endif
6352 /*-----------------------------------------------------------------*/
6353 /* shiftR1Left2Result - shift right one byte from left to result   */
6354 /*-----------------------------------------------------------------*/
6355 static void shiftR1Left2ResultSigned (operand *left, int offl,
6356                                 operand *result, int offr,
6357                                 int shCount)
6358 {
6359   int same;
6360
6361   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6362
6363   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6364
6365   switch(shCount) {
6366   case 1:
6367     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6368     if(same) 
6369       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6370     else {
6371       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6372       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6373     }
6374
6375     break;
6376   case 2:
6377
6378     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6379     if(same) 
6380       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6381     else {
6382       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6383       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6384     }
6385     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6386     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6387
6388     break;
6389
6390   case 3:
6391     if(same)
6392       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6393     else {
6394       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6395       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6396     }
6397
6398     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6399     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6400     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6401
6402     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6403     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6404
6405     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6406     break;
6407
6408   case 4:
6409     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6410     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6411     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6412     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6413     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6414     break;
6415   case 5:
6416     if(same) {
6417       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6418     } else {
6419       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6420       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6421     }
6422     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6423     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6424     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6425     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6426     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6427     break;
6428
6429   case 6:
6430     if(same) {
6431       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6432       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6433       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6434       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6435       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6436       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6437     } else {
6438       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6439       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6440       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6441       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6442       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6443     }
6444     break;
6445
6446   case 7:
6447     if(same) {
6448       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6449       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6450       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6451       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6452     } else {
6453       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6454       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6455       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6456     }
6457
6458   default:
6459     break;
6460   }
6461 }
6462
6463 /*-----------------------------------------------------------------*/
6464 /* shiftR1Left2Result - shift right one byte from left to result   */
6465 /*-----------------------------------------------------------------*/
6466 static void shiftR1Left2Result (operand *left, int offl,
6467                                 operand *result, int offr,
6468                                 int shCount, int sign)
6469 {
6470   int same;
6471
6472   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6473
6474   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6475
6476   /* Copy the msb into the carry if signed. */
6477   if(sign) {
6478     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6479     return;
6480   }
6481
6482
6483
6484   switch(shCount) {
6485   case 1:
6486     emitCLRC;
6487     if(same) 
6488       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6489     else {
6490       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6491       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6492     }
6493     break;
6494   case 2:
6495     emitCLRC;
6496     if(same) {
6497       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6498     } else {
6499       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6500       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6501     }
6502     emitCLRC;
6503     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6504
6505     break;
6506   case 3:
6507     if(same)
6508       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6509     else {
6510       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6511       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6512     }
6513
6514     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6515     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6516     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6517     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6518     break;
6519       
6520   case 4:
6521     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6522     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6523     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6524     break;
6525
6526   case 5:
6527     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6528     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6529     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6530     emitCLRC;
6531     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6532
6533     break;
6534   case 6:
6535
6536     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6537     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6538     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6539     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6540     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6541     break;
6542
6543   case 7:
6544
6545     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6546     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6547     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6548
6549     break;
6550
6551   default:
6552     break;
6553   }
6554 }
6555
6556 /*-----------------------------------------------------------------*/
6557 /* shiftL1Left2Result - shift left one byte from left to result    */
6558 /*-----------------------------------------------------------------*/
6559 static void shiftL1Left2Result (operand *left, int offl,
6560                                 operand *result, int offr, int shCount)
6561 {
6562   int same;
6563
6564   //    char *l;
6565   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6566
6567   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6568   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6569     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6570     //    MOVA(l);
6571     /* shift left accumulator */
6572     //AccLsh(shCount); // don't comment out just yet...
6573   //    pic16_aopPut(AOP(result),"a",offr);
6574
6575   switch(shCount) {
6576   case 1:
6577     /* Shift left 1 bit position */
6578     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6579     if(same) {
6580       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6581     } else {
6582       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6583       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6584     }
6585     break;
6586   case 2:
6587     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6588     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6589     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6590     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6591     break;
6592   case 3:
6593     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6594     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6595     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6596     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6597     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6598     break;
6599   case 4:
6600     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6601     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6602     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6603     break;
6604   case 5:
6605     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6606     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6607     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6608     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6609     break;
6610   case 6:
6611     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6612     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6613     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6614     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6615     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6616     break;
6617   case 7:
6618     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6619     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6620     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6621     break;
6622
6623   default:
6624     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6625   }
6626
6627 }
6628
6629 /*-----------------------------------------------------------------*/
6630 /* movLeft2Result - move byte from left to result                  */
6631 /*-----------------------------------------------------------------*/
6632 static void movLeft2Result (operand *left, int offl,
6633                             operand *result, int offr)
6634 {
6635   char *l;
6636   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6637   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6638     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6639
6640     if (*l == '@' && (IS_AOP_PREG(result))) {
6641       pic16_emitcode("mov","a,%s",l);
6642       pic16_aopPut(AOP(result),"a",offr);
6643     } else {
6644       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6646     }
6647   }
6648 }
6649
6650 /*-----------------------------------------------------------------*/
6651 /* shiftL2Left2Result - shift left two bytes from left to result   */
6652 /*-----------------------------------------------------------------*/
6653 static void shiftL2Left2Result (operand *left, int offl,
6654                                 operand *result, int offr, int shCount)
6655 {
6656
6657
6658   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6659
6660   if(pic16_sameRegs(AOP(result), AOP(left))) {
6661     switch(shCount) {
6662     case 0:
6663       break;
6664     case 1:
6665     case 2:
6666     case 3:
6667
6668       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6669       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6670       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6671
6672       while(--shCount) {
6673         emitCLRC;
6674         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6675         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6676       }
6677
6678       break;
6679     case 4:
6680     case 5:
6681       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6682       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6683       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6684       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6685       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6686       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6687       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6688       if(shCount >=5) {
6689         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6690         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6691       }
6692       break;
6693     case 6:
6694       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6695       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6696       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6697       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6698       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6699       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6700       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6701       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6702       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6703       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6704       break;
6705     case 7:
6706       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6707       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6708       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6709       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6710       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6711     }
6712
6713   } else {
6714     switch(shCount) {
6715     case 0:
6716       break;
6717     case 1:
6718     case 2:
6719     case 3:
6720       /* note, use a mov/add for the shift since the mov has a
6721          chance of getting optimized out */
6722       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6723       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6724       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6725       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6726       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6727
6728       while(--shCount) {
6729         emitCLRC;
6730         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6731         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6732       }
6733       break;
6734
6735     case 4:
6736     case 5:
6737       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6738       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6739       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6740       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6741       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6742       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6743       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6744       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6745
6746
6747       if(shCount == 5) {
6748         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6749         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6750       }
6751       break;
6752     case 6:
6753       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6754       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6755       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6756       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6757
6758       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6759       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6760       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6761       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6762       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6763       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6764       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6765       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6766       break;
6767     case 7:
6768       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6769       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6770       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6771       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6772       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6773     }
6774   }
6775
6776 }
6777 /*-----------------------------------------------------------------*/
6778 /* shiftR2Left2Result - shift right two bytes from left to result  */
6779 /*-----------------------------------------------------------------*/
6780 static void shiftR2Left2Result (operand *left, int offl,
6781                                 operand *result, int offr,
6782                                 int shCount, int sign)
6783 {
6784   int same=0;
6785
6786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6787   same = pic16_sameRegs(AOP(result), AOP(left));
6788
6789   if(same && ((offl + MSB16) == offr)){
6790     same=1;
6791     /* don't crash result[offr] */
6792     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6793     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6794   }
6795 /* else {
6796     movLeft2Result(left,offl, result, offr);
6797     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6798   }
6799 */
6800   /* a:x >> shCount (x = lsb(result))*/
6801 /*
6802   if(sign)
6803     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6804   else {
6805     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6806 */
6807   switch(shCount) {
6808   case 0:
6809     break;
6810   case 1:
6811   case 2:
6812   case 3:
6813     if(sign)
6814       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6815     else
6816       emitCLRC;
6817
6818     if(same) {
6819       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6820       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6821     } else {
6822       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6823       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6824       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6825       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6826     }
6827
6828     while(--shCount) {
6829       if(sign)
6830         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6831       else
6832         emitCLRC;
6833       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6834       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6835     }
6836     break;
6837   case 4:
6838   case 5:
6839     if(same) {
6840
6841       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
6842       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
6843       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6844
6845       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6846       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
6847       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6848       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6849     } else {
6850       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6851       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6852       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6853
6854       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6855       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6856       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6857       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6858       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6859     }
6860
6861     if(shCount >=5) {
6862       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6863       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6864     }
6865
6866     if(sign) {
6867       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
6868       pic16_emitpcode(POC_BTFSC, 
6869                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6870       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6871     }
6872
6873     break;
6874
6875   case 6:
6876     if(same) {
6877
6878       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6879       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6880
6881       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6882       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6883       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6884       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6885       if(sign) {
6886         pic16_emitpcode(POC_BTFSC, 
6887                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6888         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6889       }
6890       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6891       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
6892       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
6893       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6894     } else {
6895       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6896       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6897       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6898       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6899       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6900       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6901       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
6902       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
6903       if(sign) {
6904         pic16_emitpcode(POC_BTFSC, 
6905                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6906         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
6907       }
6908       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6909       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6910
6911         
6912     }
6913
6914     break;
6915   case 7:
6916     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6917     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
6918     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6919     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
6920     if(sign) {
6921       emitSKPNC;
6922       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
6923     } else 
6924       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6925   }
6926 }
6927
6928
6929 /*-----------------------------------------------------------------*/
6930 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6931 /*-----------------------------------------------------------------*/
6932 static void shiftLLeftOrResult (operand *left, int offl,
6933                                 operand *result, int offr, int shCount)
6934 {
6935     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6936     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6937     /* shift left accumulator */
6938     AccLsh(shCount);
6939     /* or with result */
6940     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6941     /* back to result */
6942     pic16_aopPut(AOP(result),"a",offr);
6943 }
6944
6945 /*-----------------------------------------------------------------*/
6946 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6947 /*-----------------------------------------------------------------*/
6948 static void shiftRLeftOrResult (operand *left, int offl,
6949                                 operand *result, int offr, int shCount)
6950 {
6951     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6952     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6953     /* shift right accumulator */
6954     AccRsh(shCount);
6955     /* or with result */
6956     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
6957     /* back to result */
6958     pic16_aopPut(AOP(result),"a",offr);
6959 }
6960
6961 /*-----------------------------------------------------------------*/
6962 /* genlshOne - left shift a one byte quantity by known count       */
6963 /*-----------------------------------------------------------------*/
6964 static void genlshOne (operand *result, operand *left, int shCount)
6965 {       
6966     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6967     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6968 }
6969
6970 /*-----------------------------------------------------------------*/
6971 /* genlshTwo - left shift two bytes by known amount != 0           */
6972 /*-----------------------------------------------------------------*/
6973 static void genlshTwo (operand *result,operand *left, int shCount)
6974 {
6975     int size;
6976     
6977     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6978     size = pic16_getDataSize(result);
6979
6980     /* if shCount >= 8 */
6981     if (shCount >= 8) {
6982         shCount -= 8 ;
6983
6984         if (size > 1){
6985             if (shCount)
6986                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6987             else 
6988                 movLeft2Result(left, LSB, result, MSB16);
6989         }
6990         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
6991     }
6992
6993     /*  1 <= shCount <= 7 */
6994     else {  
6995         if(size == 1)
6996             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6997         else 
6998             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6999     }
7000 }
7001
7002 /*-----------------------------------------------------------------*/
7003 /* shiftLLong - shift left one long from left to result            */
7004 /* offl = LSB or MSB16                                             */
7005 /*-----------------------------------------------------------------*/
7006 static void shiftLLong (operand *left, operand *result, int offr )
7007 {
7008     char *l;
7009     int size = AOP_SIZE(result);
7010
7011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7012     if(size >= LSB+offr){
7013         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7014         MOVA(l);
7015         pic16_emitcode("add","a,acc");
7016         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7017             size >= MSB16+offr && offr != LSB )
7018             pic16_emitcode("xch","a,%s",
7019                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7020         else        
7021             pic16_aopPut(AOP(result),"a",LSB+offr);
7022     }
7023
7024     if(size >= MSB16+offr){
7025         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7026             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7027             MOVA(l);
7028         }
7029         pic16_emitcode("rlc","a");
7030         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7031             size >= MSB24+offr && offr != LSB)
7032             pic16_emitcode("xch","a,%s",
7033                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7034         else        
7035             pic16_aopPut(AOP(result),"a",MSB16+offr);
7036     }
7037
7038     if(size >= MSB24+offr){
7039         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7040             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7041             MOVA(l);
7042         }
7043         pic16_emitcode("rlc","a");
7044         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7045             size >= MSB32+offr && offr != LSB )
7046             pic16_emitcode("xch","a,%s",
7047                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7048         else        
7049             pic16_aopPut(AOP(result),"a",MSB24+offr);
7050     }
7051
7052     if(size > MSB32+offr){
7053         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7054             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7055             MOVA(l);    
7056         }
7057         pic16_emitcode("rlc","a");
7058         pic16_aopPut(AOP(result),"a",MSB32+offr);
7059     }
7060     if(offr != LSB)
7061         pic16_aopPut(AOP(result),zero,LSB);       
7062 }
7063
7064 /*-----------------------------------------------------------------*/
7065 /* genlshFour - shift four byte by a known amount != 0             */
7066 /*-----------------------------------------------------------------*/
7067 static void genlshFour (operand *result, operand *left, int shCount)
7068 {
7069     int size;
7070
7071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7072     size = AOP_SIZE(result);
7073
7074     /* if shifting more that 3 bytes */
7075     if (shCount >= 24 ) {
7076         shCount -= 24;
7077         if (shCount)
7078             /* lowest order of left goes to the highest
7079             order of the destination */
7080             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7081         else
7082             movLeft2Result(left, LSB, result, MSB32);
7083         pic16_aopPut(AOP(result),zero,LSB);
7084         pic16_aopPut(AOP(result),zero,MSB16);
7085         pic16_aopPut(AOP(result),zero,MSB32);
7086         return;
7087     }
7088
7089     /* more than two bytes */
7090     else if ( shCount >= 16 ) {
7091         /* lower order two bytes goes to higher order two bytes */
7092         shCount -= 16;
7093         /* if some more remaining */
7094         if (shCount)
7095             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7096         else {
7097             movLeft2Result(left, MSB16, result, MSB32);
7098             movLeft2Result(left, LSB, result, MSB24);
7099         }
7100         pic16_aopPut(AOP(result),zero,MSB16);
7101         pic16_aopPut(AOP(result),zero,LSB);
7102         return;
7103     }    
7104
7105     /* if more than 1 byte */
7106     else if ( shCount >= 8 ) {
7107         /* lower order three bytes goes to higher order  three bytes */
7108         shCount -= 8;
7109         if(size == 2){
7110             if(shCount)
7111                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7112             else
7113                 movLeft2Result(left, LSB, result, MSB16);
7114         }
7115         else{   /* size = 4 */
7116             if(shCount == 0){
7117                 movLeft2Result(left, MSB24, result, MSB32);
7118                 movLeft2Result(left, MSB16, result, MSB24);
7119                 movLeft2Result(left, LSB, result, MSB16);
7120                 pic16_aopPut(AOP(result),zero,LSB);
7121             }
7122             else if(shCount == 1)
7123                 shiftLLong(left, result, MSB16);
7124             else{
7125                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7126                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7127                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7128                 pic16_aopPut(AOP(result),zero,LSB);
7129             }
7130         }
7131     }
7132
7133     /* 1 <= shCount <= 7 */
7134     else if(shCount <= 2){
7135         shiftLLong(left, result, LSB);
7136         if(shCount == 2)
7137             shiftLLong(result, result, LSB);
7138     }
7139     /* 3 <= shCount <= 7, optimize */
7140     else{
7141         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7142         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7143         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7144     }
7145 }
7146
7147 /*-----------------------------------------------------------------*/
7148 /* genLeftShiftLiteral - left shifting by known count              */
7149 /*-----------------------------------------------------------------*/
7150 static void genLeftShiftLiteral (operand *left,
7151                                  operand *right,
7152                                  operand *result,
7153                                  iCode *ic)
7154 {    
7155     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7156     int size;
7157
7158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7159     pic16_freeAsmop(right,NULL,ic,TRUE);
7160
7161     pic16_aopOp(left,ic,FALSE);
7162     pic16_aopOp(result,ic,FALSE);
7163
7164     size = getSize(operandType(result));
7165
7166 #if VIEW_SIZE
7167     pic16_emitcode("; shift left ","result %d, left %d",size,
7168              AOP_SIZE(left));
7169 #endif
7170
7171     /* I suppose that the left size >= result size */
7172     if(shCount == 0){
7173         while(size--){
7174             movLeft2Result(left, size, result, size);
7175         }
7176     }
7177
7178     else if(shCount >= (size * 8))
7179         while(size--)
7180             pic16_aopPut(AOP(result),zero,size);
7181     else{
7182         switch (size) {
7183             case 1:
7184                 genlshOne (result,left,shCount);
7185                 break;
7186
7187             case 2:
7188             case 3:
7189                 genlshTwo (result,left,shCount);
7190                 break;
7191
7192             case 4:
7193                 genlshFour (result,left,shCount);
7194                 break;
7195         }
7196     }
7197     pic16_freeAsmop(left,NULL,ic,TRUE);
7198     pic16_freeAsmop(result,NULL,ic,TRUE);
7199 }
7200
7201 /*-----------------------------------------------------------------*
7202  * genMultiAsm - repeat assembly instruction for size of register.
7203  * if endian == 1, then the high byte (i.e base address + size of 
7204  * register) is used first else the low byte is used first;
7205  *-----------------------------------------------------------------*/
7206 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7207 {
7208
7209   int offset = 0;
7210
7211   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7212
7213   if(!reg)
7214     return;
7215
7216   if(!endian) {
7217     endian = 1;
7218   } else {
7219     endian = -1;
7220     offset = size-1;
7221   }
7222
7223   while(size--) {
7224     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7225     offset += endian;
7226   }
7227
7228 }
7229 /*-----------------------------------------------------------------*/
7230 /* genLeftShift - generates code for left shifting                 */
7231 /*-----------------------------------------------------------------*/
7232 static void genLeftShift (iCode *ic)
7233 {
7234   operand *left,*right, *result;
7235   int size, offset;
7236   char *l;
7237   symbol *tlbl , *tlbl1;
7238   pCodeOp *pctemp;
7239
7240   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7241
7242   right = IC_RIGHT(ic);
7243   left  = IC_LEFT(ic);
7244   result = IC_RESULT(ic);
7245
7246   pic16_aopOp(right,ic,FALSE);
7247
7248   /* if the shift count is known then do it 
7249      as efficiently as possible */
7250   if (AOP_TYPE(right) == AOP_LIT) {
7251     genLeftShiftLiteral (left,right,result,ic);
7252     return ;
7253   }
7254
7255   /* shift count is unknown then we have to form 
7256      a loop get the loop count in B : Note: we take
7257      only the lower order byte since shifting
7258      more that 32 bits make no sense anyway, ( the
7259      largest size of an object can be only 32 bits ) */  
7260
7261     
7262   pic16_aopOp(left,ic,FALSE);
7263   pic16_aopOp(result,ic,FALSE);
7264
7265   /* now move the left to the result if they are not the
7266      same */
7267   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7268       AOP_SIZE(result) > 1) {
7269
7270     size = AOP_SIZE(result);
7271     offset=0;
7272     while (size--) {
7273       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7274       if (*l == '@' && (IS_AOP_PREG(result))) {
7275
7276         pic16_emitcode("mov","a,%s",l);
7277         pic16_aopPut(AOP(result),"a",offset);
7278       } else {
7279         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7280         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7281         //pic16_aopPut(AOP(result),l,offset);
7282       }
7283       offset++;
7284     }
7285   }
7286
7287   size = AOP_SIZE(result);
7288
7289   /* if it is only one byte then */
7290   if (size == 1) {
7291     if(optimized_for_speed) {
7292       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7293       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7294       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7295       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7296       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7297       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7298       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7299       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7300       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7301       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7302       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7303       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7304     } else {
7305
7306       tlbl = newiTempLabel(NULL);
7307       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7308         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7309         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7310       }
7311
7312       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7313       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7314       pic16_emitpLabel(tlbl->key);
7315       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7316       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7317       emitSKPC;
7318       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7319     }
7320     goto release ;
7321   }
7322     
7323   if (pic16_sameRegs(AOP(left),AOP(result))) {
7324
7325     tlbl = newiTempLabel(NULL);
7326     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7327     genMultiAsm(POC_RRCF, result, size,1);
7328     pic16_emitpLabel(tlbl->key);
7329     genMultiAsm(POC_RLCF, result, size,0);
7330     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7331     emitSKPC;
7332     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7333     goto release;
7334   }
7335
7336   //tlbl = newiTempLabel(NULL);
7337   //offset = 0 ;   
7338   //tlbl1 = newiTempLabel(NULL);
7339
7340   //reAdjustPreg(AOP(result));    
7341     
7342   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7343   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7344   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7345   //MOVA(l);
7346   //pic16_emitcode("add","a,acc");         
7347   //pic16_aopPut(AOP(result),"a",offset++);
7348   //while (--size) {
7349   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7350   //  MOVA(l);
7351   //  pic16_emitcode("rlc","a");         
7352   //  pic16_aopPut(AOP(result),"a",offset++);
7353   //}
7354   //reAdjustPreg(AOP(result));
7355
7356   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7357   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7358
7359
7360   tlbl = newiTempLabel(NULL);
7361   tlbl1= newiTempLabel(NULL);
7362
7363   size = AOP_SIZE(result);
7364   offset = 1;
7365
7366   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7367
7368   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7369
7370   /* offset should be 0, 1 or 3 */
7371   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7372   emitSKPNZ;
7373   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7374
7375   pic16_emitpcode(POC_MOVWF, pctemp);
7376
7377
7378   pic16_emitpLabel(tlbl->key);
7379
7380   emitCLRC;
7381   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7382   while(--size)
7383     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7384
7385   pic16_emitpcode(POC_DECFSZ,  pctemp);
7386   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7387   pic16_emitpLabel(tlbl1->key);
7388
7389   pic16_popReleaseTempReg(pctemp);
7390
7391
7392  release:
7393   pic16_freeAsmop (right,NULL,ic,TRUE);
7394   pic16_freeAsmop(left,NULL,ic,TRUE);
7395   pic16_freeAsmop(result,NULL,ic,TRUE);
7396 }
7397
7398 /*-----------------------------------------------------------------*/
7399 /* genrshOne - right shift a one byte quantity by known count      */
7400 /*-----------------------------------------------------------------*/
7401 static void genrshOne (operand *result, operand *left,
7402                        int shCount, int sign)
7403 {
7404     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7405     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7406 }
7407
7408 /*-----------------------------------------------------------------*/
7409 /* genrshTwo - right shift two bytes by known amount != 0          */
7410 /*-----------------------------------------------------------------*/
7411 static void genrshTwo (operand *result,operand *left,
7412                        int shCount, int sign)
7413 {
7414   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7415   /* if shCount >= 8 */
7416   if (shCount >= 8) {
7417     shCount -= 8 ;
7418     if (shCount)
7419       shiftR1Left2Result(left, MSB16, result, LSB,
7420                          shCount, sign);
7421     else
7422       movLeft2Result(left, MSB16, result, LSB);
7423
7424     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7425
7426     if(sign) {
7427       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7428       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7429     }
7430   }
7431
7432   /*  1 <= shCount <= 7 */
7433   else
7434     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7435 }
7436
7437 /*-----------------------------------------------------------------*/
7438 /* shiftRLong - shift right one long from left to result           */
7439 /* offl = LSB or MSB16                                             */
7440 /*-----------------------------------------------------------------*/
7441 static void shiftRLong (operand *left, int offl,
7442                         operand *result, int sign)
7443 {
7444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7445     if(!sign)
7446         pic16_emitcode("clr","c");
7447     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7448     if(sign)
7449         pic16_emitcode("mov","c,acc.7");
7450     pic16_emitcode("rrc","a");
7451     pic16_aopPut(AOP(result),"a",MSB32-offl);
7452     if(offl == MSB16)
7453         /* add sign of "a" */
7454         pic16_addSign(result, MSB32, sign);
7455
7456     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7457     pic16_emitcode("rrc","a");
7458     pic16_aopPut(AOP(result),"a",MSB24-offl);
7459
7460     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7461     pic16_emitcode("rrc","a");
7462     pic16_aopPut(AOP(result),"a",MSB16-offl);
7463
7464     if(offl == LSB){
7465         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7466         pic16_emitcode("rrc","a");
7467         pic16_aopPut(AOP(result),"a",LSB);
7468     }
7469 }
7470
7471 /*-----------------------------------------------------------------*/
7472 /* genrshFour - shift four byte by a known amount != 0             */
7473 /*-----------------------------------------------------------------*/
7474 static void genrshFour (operand *result, operand *left,
7475                         int shCount, int sign)
7476 {
7477   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7478   /* if shifting more that 3 bytes */
7479   if(shCount >= 24 ) {
7480     shCount -= 24;
7481     if(shCount)
7482       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7483     else
7484       movLeft2Result(left, MSB32, result, LSB);
7485
7486     pic16_addSign(result, MSB16, sign);
7487   }
7488   else if(shCount >= 16){
7489     shCount -= 16;
7490     if(shCount)
7491       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7492     else{
7493       movLeft2Result(left, MSB24, result, LSB);
7494       movLeft2Result(left, MSB32, result, MSB16);
7495     }
7496     pic16_addSign(result, MSB24, sign);
7497   }
7498   else if(shCount >= 8){
7499     shCount -= 8;
7500     if(shCount == 1)
7501       shiftRLong(left, MSB16, result, sign);
7502     else if(shCount == 0){
7503       movLeft2Result(left, MSB16, result, LSB);
7504       movLeft2Result(left, MSB24, result, MSB16);
7505       movLeft2Result(left, MSB32, result, MSB24);
7506       pic16_addSign(result, MSB32, sign);
7507     }
7508     else{
7509       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7510       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7511       /* the last shift is signed */
7512       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7513       pic16_addSign(result, MSB32, sign);
7514     }
7515   }
7516   else{   /* 1 <= shCount <= 7 */
7517     if(shCount <= 2){
7518       shiftRLong(left, LSB, result, sign);
7519       if(shCount == 2)
7520         shiftRLong(result, LSB, result, sign);
7521     }
7522     else{
7523       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7524       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7525       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7526     }
7527   }
7528 }
7529
7530 /*-----------------------------------------------------------------*/
7531 /* genRightShiftLiteral - right shifting by known count            */
7532 /*-----------------------------------------------------------------*/
7533 static void genRightShiftLiteral (operand *left,
7534                                   operand *right,
7535                                   operand *result,
7536                                   iCode *ic,
7537                                   int sign)
7538 {    
7539   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7540   int lsize,res_size;
7541
7542   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7543   pic16_freeAsmop(right,NULL,ic,TRUE);
7544
7545   pic16_aopOp(left,ic,FALSE);
7546   pic16_aopOp(result,ic,FALSE);
7547
7548 #if VIEW_SIZE
7549   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7550                  AOP_SIZE(left));
7551 #endif
7552
7553   lsize = pic16_getDataSize(left);
7554   res_size = pic16_getDataSize(result);
7555   /* test the LEFT size !!! */
7556
7557   /* I suppose that the left size >= result size */
7558   if(shCount == 0){
7559     while(res_size--)
7560       movLeft2Result(left, lsize, result, res_size);
7561   }
7562
7563   else if(shCount >= (lsize * 8)){
7564
7565     if(res_size == 1) {
7566       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7567       if(sign) {
7568         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7569         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7570       }
7571     } else {
7572
7573       if(sign) {
7574         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7575         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7576         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7577         while(res_size--)
7578           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7579
7580       } else {
7581
7582         while(res_size--)
7583           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7584       }
7585     }
7586   } else {
7587
7588     switch (res_size) {
7589     case 1:
7590       genrshOne (result,left,shCount,sign);
7591       break;
7592
7593     case 2:
7594       genrshTwo (result,left,shCount,sign);
7595       break;
7596
7597     case 4:
7598       genrshFour (result,left,shCount,sign);
7599       break;
7600     default :
7601       break;
7602     }
7603
7604   }
7605
7606   pic16_freeAsmop(left,NULL,ic,TRUE);
7607   pic16_freeAsmop(result,NULL,ic,TRUE);
7608 }
7609
7610 /*-----------------------------------------------------------------*/
7611 /* genSignedRightShift - right shift of signed number              */
7612 /*-----------------------------------------------------------------*/
7613 static void genSignedRightShift (iCode *ic)
7614 {
7615   operand *right, *left, *result;
7616   int size, offset;
7617   //  char *l;
7618   symbol *tlbl, *tlbl1 ;
7619   pCodeOp *pctemp;
7620
7621   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7622
7623   /* we do it the hard way put the shift count in b
7624      and loop thru preserving the sign */
7625   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7626
7627   right = IC_RIGHT(ic);
7628   left  = IC_LEFT(ic);
7629   result = IC_RESULT(ic);
7630
7631   pic16_aopOp(right,ic,FALSE);  
7632   pic16_aopOp(left,ic,FALSE);
7633   pic16_aopOp(result,ic,FALSE);
7634
7635
7636   if ( AOP_TYPE(right) == AOP_LIT) {
7637     genRightShiftLiteral (left,right,result,ic,1);
7638     return ;
7639   }
7640   /* shift count is unknown then we have to form 
7641      a loop get the loop count in B : Note: we take
7642      only the lower order byte since shifting
7643      more that 32 bits make no sense anyway, ( the
7644      largest size of an object can be only 32 bits ) */  
7645
7646   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7647   //pic16_emitcode("inc","b");
7648   //pic16_freeAsmop (right,NULL,ic,TRUE);
7649   //pic16_aopOp(left,ic,FALSE);
7650   //pic16_aopOp(result,ic,FALSE);
7651
7652   /* now move the left to the result if they are not the
7653      same */
7654   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7655       AOP_SIZE(result) > 1) {
7656
7657     size = AOP_SIZE(result);
7658     offset=0;
7659     while (size--) { 
7660       /*
7661         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7662         if (*l == '@' && IS_AOP_PREG(result)) {
7663
7664         pic16_emitcode("mov","a,%s",l);
7665         pic16_aopPut(AOP(result),"a",offset);
7666         } else
7667         pic16_aopPut(AOP(result),l,offset);
7668       */
7669       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7670       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7671
7672       offset++;
7673     }
7674   }
7675
7676   /* mov the highest order bit to OVR */    
7677   tlbl = newiTempLabel(NULL);
7678   tlbl1= newiTempLabel(NULL);
7679
7680   size = AOP_SIZE(result);
7681   offset = size - 1;
7682
7683   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7684
7685   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7686
7687   /* offset should be 0, 1 or 3 */
7688   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7689   emitSKPNZ;
7690   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7691
7692   pic16_emitpcode(POC_MOVWF, pctemp);
7693
7694
7695   pic16_emitpLabel(tlbl->key);
7696
7697   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7698   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7699
7700   while(--size) {
7701     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7702   }
7703
7704   pic16_emitpcode(POC_DECFSZ,  pctemp);
7705   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7706   pic16_emitpLabel(tlbl1->key);
7707
7708   pic16_popReleaseTempReg(pctemp);
7709 #if 0
7710   size = AOP_SIZE(result);
7711   offset = size - 1;
7712   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7713   pic16_emitcode("rlc","a");
7714   pic16_emitcode("mov","ov,c");
7715   /* if it is only one byte then */
7716   if (size == 1) {
7717     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7718     MOVA(l);
7719     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7720     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7721     pic16_emitcode("mov","c,ov");
7722     pic16_emitcode("rrc","a");
7723     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7724     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7725     pic16_aopPut(AOP(result),"a",0);
7726     goto release ;
7727   }
7728
7729   reAdjustPreg(AOP(result));
7730   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7731   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7732   pic16_emitcode("mov","c,ov");
7733   while (size--) {
7734     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7735     MOVA(l);
7736     pic16_emitcode("rrc","a");         
7737     pic16_aopPut(AOP(result),"a",offset--);
7738   }
7739   reAdjustPreg(AOP(result));
7740   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7741   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7742
7743  release:
7744 #endif
7745
7746   pic16_freeAsmop(left,NULL,ic,TRUE);
7747   pic16_freeAsmop(result,NULL,ic,TRUE);
7748   pic16_freeAsmop(right,NULL,ic,TRUE);
7749 }
7750
7751 /*-----------------------------------------------------------------*/
7752 /* genRightShift - generate code for right shifting                */
7753 /*-----------------------------------------------------------------*/
7754 static void genRightShift (iCode *ic)
7755 {
7756     operand *right, *left, *result;
7757     sym_link *retype ;
7758     int size, offset;
7759     char *l;
7760     symbol *tlbl, *tlbl1 ;
7761
7762     /* if signed then we do it the hard way preserve the
7763     sign bit moving it inwards */
7764     retype = getSpec(operandType(IC_RESULT(ic)));
7765     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7766
7767     if (!SPEC_USIGN(retype)) {
7768         genSignedRightShift (ic);
7769         return ;
7770     }
7771
7772     /* signed & unsigned types are treated the same : i.e. the
7773     signed is NOT propagated inwards : quoting from the
7774     ANSI - standard : "for E1 >> E2, is equivalent to division
7775     by 2**E2 if unsigned or if it has a non-negative value,
7776     otherwise the result is implementation defined ", MY definition
7777     is that the sign does not get propagated */
7778
7779     right = IC_RIGHT(ic);
7780     left  = IC_LEFT(ic);
7781     result = IC_RESULT(ic);
7782
7783     pic16_aopOp(right,ic,FALSE);
7784
7785     /* if the shift count is known then do it 
7786     as efficiently as possible */
7787     if (AOP_TYPE(right) == AOP_LIT) {
7788         genRightShiftLiteral (left,right,result,ic, 0);
7789         return ;
7790     }
7791
7792     /* shift count is unknown then we have to form 
7793     a loop get the loop count in B : Note: we take
7794     only the lower order byte since shifting
7795     more that 32 bits make no sense anyway, ( the
7796     largest size of an object can be only 32 bits ) */  
7797
7798     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7799     pic16_emitcode("inc","b");
7800     pic16_aopOp(left,ic,FALSE);
7801     pic16_aopOp(result,ic,FALSE);
7802
7803     /* now move the left to the result if they are not the
7804     same */
7805     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7806         AOP_SIZE(result) > 1) {
7807
7808         size = AOP_SIZE(result);
7809         offset=0;
7810         while (size--) {
7811             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7812             if (*l == '@' && IS_AOP_PREG(result)) {
7813
7814                 pic16_emitcode("mov","a,%s",l);
7815                 pic16_aopPut(AOP(result),"a",offset);
7816             } else
7817                 pic16_aopPut(AOP(result),l,offset);
7818             offset++;
7819         }
7820     }
7821
7822     tlbl = newiTempLabel(NULL);
7823     tlbl1= newiTempLabel(NULL);
7824     size = AOP_SIZE(result);
7825     offset = size - 1;
7826
7827     /* if it is only one byte then */
7828     if (size == 1) {
7829
7830       tlbl = newiTempLabel(NULL);
7831       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7832         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7833         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7834       }
7835
7836       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7837       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7838       pic16_emitpLabel(tlbl->key);
7839       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7840       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7841       emitSKPC;
7842       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7843
7844       goto release ;
7845     }
7846
7847     reAdjustPreg(AOP(result));
7848     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7849     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7850     CLRC;
7851     while (size--) {
7852         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7853         MOVA(l);
7854         pic16_emitcode("rrc","a");         
7855         pic16_aopPut(AOP(result),"a",offset--);
7856     }
7857     reAdjustPreg(AOP(result));
7858
7859     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7860     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7861
7862 release:
7863     pic16_freeAsmop(left,NULL,ic,TRUE);
7864     pic16_freeAsmop (right,NULL,ic,TRUE);
7865     pic16_freeAsmop(result,NULL,ic,TRUE);
7866 }
7867
7868 /*-----------------------------------------------------------------*/
7869 /* genUnpackBits - generates code for unpacking bits               */
7870 /*-----------------------------------------------------------------*/
7871 static void genUnpackBits (operand *result, char *rname, int ptype)
7872 {    
7873     int shCnt ;
7874     int rlen = 0 ;
7875     sym_link *etype;
7876     int offset = 0 ;
7877
7878     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7879     etype = getSpec(operandType(result));
7880
7881     /* read the first byte  */
7882     switch (ptype) {
7883
7884     case POINTER:
7885     case IPOINTER:
7886         pic16_emitcode("mov","a,@%s",rname);
7887         break;
7888         
7889     case PPOINTER:
7890         pic16_emitcode("movx","a,@%s",rname);
7891         break;
7892         
7893     case FPOINTER:
7894         pic16_emitcode("movx","a,@dptr");
7895         break;
7896
7897     case CPOINTER:
7898         pic16_emitcode("clr","a");
7899         pic16_emitcode("movc","a","@a+dptr");
7900         break;
7901
7902     case GPOINTER:
7903         pic16_emitcode("lcall","__gptrget");
7904         break;
7905     }
7906
7907     /* if we have bitdisplacement then it fits   */
7908     /* into this byte completely or if length is */
7909     /* less than a byte                          */
7910     if ((shCnt = SPEC_BSTR(etype)) || 
7911         (SPEC_BLEN(etype) <= 8))  {
7912
7913         /* shift right acc */
7914         AccRsh(shCnt);
7915
7916         pic16_emitcode("anl","a,#0x%02x",
7917                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7918         pic16_aopPut(AOP(result),"a",offset);
7919         return ;
7920     }
7921
7922     /* bit field did not fit in a byte  */
7923     rlen = SPEC_BLEN(etype) - 8;
7924     pic16_aopPut(AOP(result),"a",offset++);
7925
7926     while (1)  {
7927
7928         switch (ptype) {
7929         case POINTER:
7930         case IPOINTER:
7931             pic16_emitcode("inc","%s",rname);
7932             pic16_emitcode("mov","a,@%s",rname);
7933             break;
7934             
7935         case PPOINTER:
7936             pic16_emitcode("inc","%s",rname);
7937             pic16_emitcode("movx","a,@%s",rname);
7938             break;
7939
7940         case FPOINTER:
7941             pic16_emitcode("inc","dptr");
7942             pic16_emitcode("movx","a,@dptr");
7943             break;
7944             
7945         case CPOINTER:
7946             pic16_emitcode("clr","a");
7947             pic16_emitcode("inc","dptr");
7948             pic16_emitcode("movc","a","@a+dptr");
7949             break;
7950             
7951         case GPOINTER:
7952             pic16_emitcode("inc","dptr");
7953             pic16_emitcode("lcall","__gptrget");
7954             break;
7955         }
7956
7957         rlen -= 8;            
7958         /* if we are done */
7959         if ( rlen <= 0 )
7960             break ;
7961         
7962         pic16_aopPut(AOP(result),"a",offset++);
7963                               
7964     }
7965     
7966     if (rlen) {
7967         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7968         pic16_aopPut(AOP(result),"a",offset);          
7969     }
7970     
7971     return ;
7972 }
7973
7974 #if 0
7975 /*-----------------------------------------------------------------*/
7976 /* genDataPointerGet - generates code when ptr offset is known     */
7977 /*-----------------------------------------------------------------*/
7978 static void genDataPointerGet (operand *left, 
7979                                operand *result, 
7980                                iCode *ic)
7981 {
7982   int size , offset = 0;
7983
7984
7985   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7986
7987
7988   /* optimization - most of the time, left and result are the same
7989    * address, but different types. for the pic code, we could omit
7990    * the following
7991    */
7992
7993   pic16_aopOp(result,ic,TRUE);
7994
7995   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7996
7997   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
7998
7999   size = AOP_SIZE(result);
8000
8001   while (size--) {
8002     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8003     offset++;
8004   }
8005
8006   pic16_freeAsmop(left,NULL,ic,TRUE);
8007   pic16_freeAsmop(result,NULL,ic,TRUE);
8008 }
8009 #endif
8010 /*-----------------------------------------------------------------*/
8011 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8012 /*-----------------------------------------------------------------*/
8013 static void genNearPointerGet (operand *left, 
8014                                operand *result, 
8015                                iCode *ic)
8016 {
8017     asmop *aop = NULL;
8018     //regs *preg = NULL ;
8019     char *rname ;
8020     sym_link *rtype, *retype;
8021     sym_link *ltype = operandType(left);    
8022     //char buffer[80];
8023
8024     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8025
8026     rtype = operandType(result);
8027     retype= getSpec(rtype);
8028     
8029     pic16_aopOp(left,ic,FALSE);
8030     
8031     /* if left is rematerialisable and
8032        result is not bit variable type and
8033        the left is pointer to data space i.e
8034        lower 128 bytes of space */
8035     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8036         !IS_BITVAR(retype)         &&
8037         DCL_TYPE(ltype) == POINTER) {
8038       //genDataPointerGet (left,result,ic);
8039         return ;
8040     }
8041     
8042     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8043
8044         /* if the value is already in a pointer register
8045        then don't need anything more */
8046     if (!AOP_INPREG(AOP(left))) {
8047         /* otherwise get a free pointer register */
8048     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8049 /*
8050         aop = newAsmop(0);
8051         preg = getFreePtr(ic,&aop,FALSE);
8052         pic16_emitcode("mov","%s,%s",
8053                 preg->name,
8054                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8055         rname = preg->name ;
8056 */
8057     rname ="BAD";
8058     } else
8059         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8060     
8061     pic16_aopOp (result,ic,FALSE);
8062     
8063       /* if bitfield then unpack the bits */
8064     if (IS_BITVAR(retype)) 
8065         genUnpackBits (result,rname,POINTER);
8066     else {
8067         /* we have can just get the values */
8068       int size = AOP_SIZE(result);
8069       int offset = 0 ;  
8070         
8071       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8072
8073       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8074       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8075       while(size--) {
8076         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8077         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8078         if(size)
8079           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8080       }
8081 /*
8082         while (size--) {
8083             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8084
8085                 pic16_emitcode("mov","a,@%s",rname);
8086                 pic16_aopPut(AOP(result),"a",offset);
8087             } else {
8088                 sprintf(buffer,"@%s",rname);
8089                 pic16_aopPut(AOP(result),buffer,offset);
8090             }
8091             offset++ ;
8092             if (size)
8093                 pic16_emitcode("inc","%s",rname);
8094         }
8095 */
8096     }
8097
8098     /* now some housekeeping stuff */
8099     if (aop) {
8100         /* we had to allocate for this iCode */
8101     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8102         pic16_freeAsmop(NULL,aop,ic,TRUE);
8103     } else { 
8104         /* we did not allocate which means left
8105            already in a pointer register, then
8106            if size > 0 && this could be used again
8107            we have to point it back to where it 
8108            belongs */
8109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8110         if (AOP_SIZE(result) > 1 &&
8111             !OP_SYMBOL(left)->remat &&
8112             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8113               ic->depth )) {
8114             int size = AOP_SIZE(result) - 1;
8115             while (size--)
8116                 pic16_emitcode("dec","%s",rname);
8117         }
8118     }
8119
8120     /* done */
8121     pic16_freeAsmop(left,NULL,ic,TRUE);
8122     pic16_freeAsmop(result,NULL,ic,TRUE);
8123      
8124 }
8125
8126 /*-----------------------------------------------------------------*/
8127 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8128 /*-----------------------------------------------------------------*/
8129 static void genPagedPointerGet (operand *left, 
8130                                operand *result, 
8131                                iCode *ic)
8132 {
8133     asmop *aop = NULL;
8134     regs *preg = NULL ;
8135     char *rname ;
8136     sym_link *rtype, *retype;    
8137
8138     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8139
8140     rtype = operandType(result);
8141     retype= getSpec(rtype);
8142     
8143     pic16_aopOp(left,ic,FALSE);
8144
8145   /* if the value is already in a pointer register
8146        then don't need anything more */
8147     if (!AOP_INPREG(AOP(left))) {
8148         /* otherwise get a free pointer register */
8149         aop = newAsmop(0);
8150         preg = getFreePtr(ic,&aop,FALSE);
8151         pic16_emitcode("mov","%s,%s",
8152                 preg->name,
8153                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8154         rname = preg->name ;
8155     } else
8156         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8157     
8158     pic16_freeAsmop(left,NULL,ic,TRUE);
8159     pic16_aopOp (result,ic,FALSE);
8160
8161     /* if bitfield then unpack the bits */
8162     if (IS_BITVAR(retype)) 
8163         genUnpackBits (result,rname,PPOINTER);
8164     else {
8165         /* we have can just get the values */
8166         int size = AOP_SIZE(result);
8167         int offset = 0 ;        
8168         
8169         while (size--) {
8170             
8171             pic16_emitcode("movx","a,@%s",rname);
8172             pic16_aopPut(AOP(result),"a",offset);
8173             
8174             offset++ ;
8175             
8176             if (size)
8177                 pic16_emitcode("inc","%s",rname);
8178         }
8179     }
8180
8181     /* now some housekeeping stuff */
8182     if (aop) {
8183         /* we had to allocate for this iCode */
8184         pic16_freeAsmop(NULL,aop,ic,TRUE);
8185     } else { 
8186         /* we did not allocate which means left
8187            already in a pointer register, then
8188            if size > 0 && this could be used again
8189            we have to point it back to where it 
8190            belongs */
8191         if (AOP_SIZE(result) > 1 &&
8192             !OP_SYMBOL(left)->remat &&
8193             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8194               ic->depth )) {
8195             int size = AOP_SIZE(result) - 1;
8196             while (size--)
8197                 pic16_emitcode("dec","%s",rname);
8198         }
8199     }
8200
8201     /* done */
8202     pic16_freeAsmop(result,NULL,ic,TRUE);
8203     
8204         
8205 }
8206
8207 /*-----------------------------------------------------------------*/
8208 /* genFarPointerGet - gget value from far space                    */
8209 /*-----------------------------------------------------------------*/
8210 static void genFarPointerGet (operand *left,
8211                               operand *result, iCode *ic)
8212 {
8213     int size, offset ;
8214     sym_link *retype = getSpec(operandType(result));
8215
8216     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8217
8218     pic16_aopOp(left,ic,FALSE);
8219
8220     /* if the operand is already in dptr 
8221     then we do nothing else we move the value to dptr */
8222     if (AOP_TYPE(left) != AOP_STR) {
8223         /* if this is remateriazable */
8224         if (AOP_TYPE(left) == AOP_IMMD)
8225             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8226         else { /* we need to get it byte by byte */
8227             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8228             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8229             if (options.model == MODEL_FLAT24)
8230             {
8231                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8232             }
8233         }
8234     }
8235     /* so dptr know contains the address */
8236     pic16_freeAsmop(left,NULL,ic,TRUE);
8237     pic16_aopOp(result,ic,FALSE);
8238
8239     /* if bit then unpack */
8240     if (IS_BITVAR(retype)) 
8241         genUnpackBits(result,"dptr",FPOINTER);
8242     else {
8243         size = AOP_SIZE(result);
8244         offset = 0 ;
8245
8246         while (size--) {
8247             pic16_emitcode("movx","a,@dptr");
8248             pic16_aopPut(AOP(result),"a",offset++);
8249             if (size)
8250                 pic16_emitcode("inc","dptr");
8251         }
8252     }
8253
8254     pic16_freeAsmop(result,NULL,ic,TRUE);
8255 }
8256 #if 0
8257 /*-----------------------------------------------------------------*/
8258 /* genCodePointerGet - get value from code space                  */
8259 /*-----------------------------------------------------------------*/
8260 static void genCodePointerGet (operand *left,
8261                                 operand *result, iCode *ic)
8262 {
8263     int size, offset ;
8264     sym_link *retype = getSpec(operandType(result));
8265
8266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8267
8268     pic16_aopOp(left,ic,FALSE);
8269
8270     /* if the operand is already in dptr 
8271     then we do nothing else we move the value to dptr */
8272     if (AOP_TYPE(left) != AOP_STR) {
8273         /* if this is remateriazable */
8274         if (AOP_TYPE(left) == AOP_IMMD)
8275             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8276         else { /* we need to get it byte by byte */
8277             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8278             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8279             if (options.model == MODEL_FLAT24)
8280             {
8281                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8282             }
8283         }
8284     }
8285     /* so dptr know contains the address */
8286     pic16_freeAsmop(left,NULL,ic,TRUE);
8287     pic16_aopOp(result,ic,FALSE);
8288
8289     /* if bit then unpack */
8290     if (IS_BITVAR(retype)) 
8291         genUnpackBits(result,"dptr",CPOINTER);
8292     else {
8293         size = AOP_SIZE(result);
8294         offset = 0 ;
8295
8296         while (size--) {
8297             pic16_emitcode("clr","a");
8298             pic16_emitcode("movc","a,@a+dptr");
8299             pic16_aopPut(AOP(result),"a",offset++);
8300             if (size)
8301                 pic16_emitcode("inc","dptr");
8302         }
8303     }
8304
8305     pic16_freeAsmop(result,NULL,ic,TRUE);
8306 }
8307 #endif
8308 /*-----------------------------------------------------------------*/
8309 /* genGenPointerGet - gget value from generic pointer space        */
8310 /*-----------------------------------------------------------------*/
8311 static void genGenPointerGet (operand *left,
8312                               operand *result, iCode *ic)
8313 {
8314   int size, offset ;
8315   sym_link *retype = getSpec(operandType(result));
8316
8317   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8318   pic16_aopOp(left,ic,FALSE);
8319   pic16_aopOp(result,ic,FALSE);
8320
8321
8322   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8323
8324   /* if the operand is already in dptr 
8325      then we do nothing else we move the value to dptr */
8326   //  if (AOP_TYPE(left) != AOP_STR) {
8327     /* if this is remateriazable */
8328     if (AOP_TYPE(left) == AOP_IMMD) {
8329       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8330       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8331     }
8332     else { /* we need to get it byte by byte */
8333
8334       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8335       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8336
8337       size = AOP_SIZE(result);
8338       offset = 0 ;
8339
8340       while(size--) {
8341         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8342         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8343         if(size)
8344           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8345       }
8346       goto release;
8347     }
8348     //}
8349   /* so dptr know contains the address */
8350
8351   /* if bit then unpack */
8352   //if (IS_BITVAR(retype)) 
8353   //  genUnpackBits(result,"dptr",GPOINTER);
8354
8355  release:
8356   pic16_freeAsmop(left,NULL,ic,TRUE);
8357   pic16_freeAsmop(result,NULL,ic,TRUE);
8358
8359 }
8360
8361 /*-----------------------------------------------------------------*/
8362 /* genConstPointerGet - get value from const generic pointer space */
8363 /*-----------------------------------------------------------------*/
8364 static void genConstPointerGet (operand *left,
8365                                 operand *result, iCode *ic)
8366 {
8367   //sym_link *retype = getSpec(operandType(result));
8368   symbol *albl = newiTempLabel(NULL);
8369   symbol *blbl = newiTempLabel(NULL);
8370   PIC_OPCODE poc;
8371
8372   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8373   pic16_aopOp(left,ic,FALSE);
8374   pic16_aopOp(result,ic,FALSE);
8375
8376
8377   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8378
8379   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8380
8381   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8382   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8383   pic16_emitpLabel(albl->key);
8384
8385   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8386     
8387   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8388   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8389   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8390   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8391
8392   pic16_emitpLabel(blbl->key);
8393
8394   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8395
8396
8397   pic16_freeAsmop(left,NULL,ic,TRUE);
8398   pic16_freeAsmop(result,NULL,ic,TRUE);
8399
8400 }
8401 /*-----------------------------------------------------------------*/
8402 /* genPointerGet - generate code for pointer get                   */
8403 /*-----------------------------------------------------------------*/
8404 static void genPointerGet (iCode *ic)
8405 {
8406     operand *left, *result ;
8407     sym_link *type, *etype;
8408     int p_type;
8409
8410     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8411
8412     left = IC_LEFT(ic);
8413     result = IC_RESULT(ic) ;
8414
8415     /* depending on the type of pointer we need to
8416     move it to the correct pointer register */
8417     type = operandType(left);
8418     etype = getSpec(type);
8419
8420 #if 0
8421     if (IS_PTR_CONST(type))
8422 #else
8423     if (IS_CODEPTR(type))
8424 #endif
8425       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8426
8427     /* if left is of type of pointer then it is simple */
8428     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8429         p_type = DCL_TYPE(type);
8430     else {
8431         /* we have to go by the storage class */
8432         p_type = PTR_TYPE(SPEC_OCLS(etype));
8433
8434         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8435
8436         if (SPEC_OCLS(etype)->codesp ) {
8437           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8438           //p_type = CPOINTER ; 
8439         }
8440         else
8441             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8442               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8443                /*p_type = FPOINTER ;*/ 
8444             else
8445                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8446                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8447 /*                  p_type = PPOINTER; */
8448                 else
8449                     if (SPEC_OCLS(etype) == idata )
8450                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8451 /*                      p_type = IPOINTER; */
8452                     else
8453                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8454 /*                      p_type = POINTER ; */
8455     }
8456
8457     /* now that we have the pointer type we assign
8458     the pointer values */
8459     switch (p_type) {
8460
8461     case POINTER:       
8462     case IPOINTER:
8463         genNearPointerGet (left,result,ic);
8464         break;
8465
8466     case PPOINTER:
8467         genPagedPointerGet(left,result,ic);
8468         break;
8469
8470     case FPOINTER:
8471         genFarPointerGet (left,result,ic);
8472         break;
8473
8474     case CPOINTER:
8475         genConstPointerGet (left,result,ic);
8476         //pic16_emitcodePointerGet (left,result,ic);
8477         break;
8478
8479     case GPOINTER:
8480 #if 0
8481       if (IS_PTR_CONST(type))
8482         genConstPointerGet (left,result,ic);
8483       else
8484 #endif
8485         genGenPointerGet (left,result,ic);
8486       break;
8487     }
8488
8489 }
8490
8491 /*-----------------------------------------------------------------*/
8492 /* genPackBits - generates code for packed bit storage             */
8493 /*-----------------------------------------------------------------*/
8494 static void genPackBits (sym_link    *etype ,
8495                          operand *right ,
8496                          char *rname, int p_type)
8497 {
8498     int shCount = 0 ;
8499     int offset = 0  ;
8500     int rLen = 0 ;
8501     int blen, bstr ;   
8502     char *l ;
8503
8504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8505     blen = SPEC_BLEN(etype);
8506     bstr = SPEC_BSTR(etype);
8507
8508     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8509     MOVA(l);   
8510
8511     /* if the bit lenth is less than or    */
8512     /* it exactly fits a byte then         */
8513     if (SPEC_BLEN(etype) <= 8 )  {
8514         shCount = SPEC_BSTR(etype) ;
8515
8516         /* shift left acc */
8517         AccLsh(shCount);
8518
8519         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8520
8521
8522             switch (p_type) {
8523                 case POINTER:
8524                     pic16_emitcode ("mov","b,a");
8525                     pic16_emitcode("mov","a,@%s",rname);
8526                     break;
8527
8528                 case FPOINTER:
8529                     pic16_emitcode ("mov","b,a");
8530                     pic16_emitcode("movx","a,@dptr");
8531                     break;
8532
8533                 case GPOINTER:
8534                     pic16_emitcode ("push","b");
8535                     pic16_emitcode ("push","acc");
8536                     pic16_emitcode ("lcall","__gptrget");
8537                     pic16_emitcode ("pop","b");
8538                     break;
8539             }
8540
8541             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8542                       ((unsigned char)(0xFF << (blen+bstr)) | 
8543                        (unsigned char)(0xFF >> (8-bstr)) ) );
8544             pic16_emitcode ("orl","a,b");
8545             if (p_type == GPOINTER)
8546                 pic16_emitcode("pop","b");
8547         }
8548     }
8549
8550     switch (p_type) {
8551         case POINTER:
8552             pic16_emitcode("mov","@%s,a",rname);
8553             break;
8554
8555         case FPOINTER:
8556             pic16_emitcode("movx","@dptr,a");
8557             break;
8558
8559         case GPOINTER:
8560             DEBUGpic16_emitcode(";lcall","__gptrput");
8561             break;
8562     }
8563
8564     /* if we r done */
8565     if ( SPEC_BLEN(etype) <= 8 )
8566         return ;
8567
8568     pic16_emitcode("inc","%s",rname);
8569     rLen = SPEC_BLEN(etype) ;     
8570
8571     /* now generate for lengths greater than one byte */
8572     while (1) {
8573
8574         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8575
8576         rLen -= 8 ;
8577         if (rLen <= 0 )
8578             break ;
8579
8580         switch (p_type) {
8581             case POINTER:
8582                 if (*l == '@') {
8583                     MOVA(l);
8584                     pic16_emitcode("mov","@%s,a",rname);
8585                 } else
8586                     pic16_emitcode("mov","@%s,%s",rname,l);
8587                 break;
8588
8589             case FPOINTER:
8590                 MOVA(l);
8591                 pic16_emitcode("movx","@dptr,a");
8592                 break;
8593
8594             case GPOINTER:
8595                 MOVA(l);
8596                 DEBUGpic16_emitcode(";lcall","__gptrput");
8597                 break;  
8598         }   
8599         pic16_emitcode ("inc","%s",rname);
8600     }
8601
8602     MOVA(l);
8603
8604     /* last last was not complete */
8605     if (rLen)   {
8606         /* save the byte & read byte */
8607         switch (p_type) {
8608             case POINTER:
8609                 pic16_emitcode ("mov","b,a");
8610                 pic16_emitcode("mov","a,@%s",rname);
8611                 break;
8612
8613             case FPOINTER:
8614                 pic16_emitcode ("mov","b,a");
8615                 pic16_emitcode("movx","a,@dptr");
8616                 break;
8617
8618             case GPOINTER:
8619                 pic16_emitcode ("push","b");
8620                 pic16_emitcode ("push","acc");
8621                 pic16_emitcode ("lcall","__gptrget");
8622                 pic16_emitcode ("pop","b");
8623                 break;
8624         }
8625
8626         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8627         pic16_emitcode ("orl","a,b");
8628     }
8629
8630     if (p_type == GPOINTER)
8631         pic16_emitcode("pop","b");
8632
8633     switch (p_type) {
8634
8635     case POINTER:
8636         pic16_emitcode("mov","@%s,a",rname);
8637         break;
8638         
8639     case FPOINTER:
8640         pic16_emitcode("movx","@dptr,a");
8641         break;
8642         
8643     case GPOINTER:
8644         DEBUGpic16_emitcode(";lcall","__gptrput");
8645         break;                  
8646     }
8647 }
8648 /*-----------------------------------------------------------------*/
8649 /* genDataPointerSet - remat pointer to data space                 */
8650 /*-----------------------------------------------------------------*/
8651 static void genDataPointerSet(operand *right,
8652                               operand *result,
8653                               iCode *ic)
8654 {
8655     int size, offset = 0 ;
8656     char *l, buffer[256];
8657
8658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8659     pic16_aopOp(right,ic,FALSE);
8660     
8661     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8662     size = AOP_SIZE(right);
8663 /*
8664     if ( AOP_TYPE(result) == AOP_PCODE) {
8665       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8666               AOP(result)->aopu.pcop->name,
8667               PCOI(AOP(result)->aopu.pcop)->offset);
8668     }
8669 */
8670
8671     // tsd, was l+1 - the underline `_' prefix was being stripped
8672     while (size--) {
8673       if (offset) {
8674         sprintf(buffer,"(%s + %d)",l,offset);
8675         fprintf(stderr,"oops  %s\n",buffer);
8676       } else
8677         sprintf(buffer,"%s",l);
8678
8679         if (AOP_TYPE(right) == AOP_LIT) {
8680           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8681           lit = lit >> (8*offset);
8682           if(lit&0xff) {
8683             pic16_emitcode("movlw","%d",lit);
8684             pic16_emitcode("movwf","%s",buffer);
8685
8686             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8687             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8688             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8689
8690           } else {
8691             pic16_emitcode("clrf","%s",buffer);
8692             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
8693             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8694           }
8695         }else {
8696           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8697           pic16_emitcode("movwf","%s",buffer);
8698
8699           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8700           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8701           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8702
8703         }
8704
8705         offset++;
8706     }
8707
8708     pic16_freeAsmop(right,NULL,ic,TRUE);
8709     pic16_freeAsmop(result,NULL,ic,TRUE);
8710 }
8711
8712 /*-----------------------------------------------------------------*/
8713 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8714 /*-----------------------------------------------------------------*/
8715 static void genNearPointerSet (operand *right,
8716                                operand *result, 
8717                                iCode *ic)
8718 {
8719   asmop *aop = NULL;
8720   char *l;
8721   sym_link *retype;
8722   sym_link *ptype = operandType(result);
8723
8724     
8725   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8726   retype= getSpec(operandType(right));
8727
8728   pic16_aopOp(result,ic,FALSE);
8729
8730     
8731   /* if the result is rematerializable &
8732      in data space & not a bit variable */
8733   //if (AOP_TYPE(result) == AOP_IMMD &&
8734   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8735       DCL_TYPE(ptype) == POINTER   &&
8736       !IS_BITVAR(retype)) {
8737     genDataPointerSet (right,result,ic);
8738     pic16_freeAsmop(result,NULL,ic,TRUE);
8739     return;
8740   }
8741
8742   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8743   pic16_aopOp(right,ic,FALSE);
8744   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8745
8746   /* if the value is already in a pointer register
8747      then don't need anything more */
8748   if (!AOP_INPREG(AOP(result))) {
8749     /* otherwise get a free pointer register */
8750     //aop = newAsmop(0);
8751     //preg = getFreePtr(ic,&aop,FALSE);
8752     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8753     //pic16_emitcode("mov","%s,%s",
8754     //         preg->name,
8755     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8756     //rname = preg->name ;
8757     //pic16_emitcode("movwf","fsr0");
8758     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8759     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8760     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8761     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8762     goto release;
8763
8764   }// else
8765   //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8766
8767
8768   /* if bitfield then unpack the bits */
8769   if (IS_BITVAR(retype)) {
8770     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8771            "The programmer is obviously confused");
8772     //genPackBits (retype,right,rname,POINTER);
8773     exit(1);
8774   }
8775   else {
8776     /* we have can just get the values */
8777     int size = AOP_SIZE(right);
8778     int offset = 0 ;    
8779
8780     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8781     while (size--) {
8782       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8783       if (*l == '@' ) {
8784         //MOVA(l);
8785         //pic16_emitcode("mov","@%s,a",rname);
8786         pic16_emitcode("movf","indf0,w ;1");
8787       } else {
8788
8789         if (AOP_TYPE(right) == AOP_LIT) {
8790           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8791           if(lit) {
8792             pic16_emitcode("movlw","%s",l);
8793             pic16_emitcode("movwf","indf0 ;2");
8794           } else 
8795             pic16_emitcode("clrf","indf0");
8796         }else {
8797           pic16_emitcode("movf","%s,w",l);
8798           pic16_emitcode("movwf","indf0 ;2");
8799         }
8800         //pic16_emitcode("mov","@%s,%s",rname,l);
8801       }
8802       if (size)
8803         pic16_emitcode("incf","fsr0,f ;3");
8804       //pic16_emitcode("inc","%s",rname);
8805       offset++;
8806     }
8807   }
8808
8809   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8810   /* now some housekeeping stuff */
8811   if (aop) {
8812     /* we had to allocate for this iCode */
8813     pic16_freeAsmop(NULL,aop,ic,TRUE);
8814   } else { 
8815     /* we did not allocate which means left
8816        already in a pointer register, then
8817        if size > 0 && this could be used again
8818        we have to point it back to where it 
8819        belongs */
8820     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8821     if (AOP_SIZE(right) > 1 &&
8822         !OP_SYMBOL(result)->remat &&
8823         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8824           ic->depth )) {
8825       int size = AOP_SIZE(right) - 1;
8826       while (size--)
8827         pic16_emitcode("decf","fsr0,f");
8828       //pic16_emitcode("dec","%s",rname);
8829     }
8830   }
8831
8832   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8833   /* done */
8834  release:
8835   pic16_freeAsmop(right,NULL,ic,TRUE);
8836   pic16_freeAsmop(result,NULL,ic,TRUE);
8837 }
8838
8839 /*-----------------------------------------------------------------*/
8840 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
8841 /*-----------------------------------------------------------------*/
8842 static void genPagedPointerSet (operand *right,
8843                                operand *result, 
8844                                iCode *ic)
8845 {
8846     asmop *aop = NULL;
8847     regs *preg = NULL ;
8848     char *rname , *l;
8849     sym_link *retype;
8850        
8851     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8852
8853     retype= getSpec(operandType(right));
8854     
8855     pic16_aopOp(result,ic,FALSE);
8856     
8857     /* if the value is already in a pointer register
8858        then don't need anything more */
8859     if (!AOP_INPREG(AOP(result))) {
8860         /* otherwise get a free pointer register */
8861         aop = newAsmop(0);
8862         preg = getFreePtr(ic,&aop,FALSE);
8863         pic16_emitcode("mov","%s,%s",
8864                 preg->name,
8865                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
8866         rname = preg->name ;
8867     } else
8868         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8869     
8870     pic16_freeAsmop(result,NULL,ic,TRUE);
8871     pic16_aopOp (right,ic,FALSE);
8872
8873     /* if bitfield then unpack the bits */
8874     if (IS_BITVAR(retype)) 
8875         genPackBits (retype,right,rname,PPOINTER);
8876     else {
8877         /* we have can just get the values */
8878         int size = AOP_SIZE(right);
8879         int offset = 0 ;        
8880         
8881         while (size--) {
8882             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8883             
8884             MOVA(l);
8885             pic16_emitcode("movx","@%s,a",rname);
8886
8887             if (size)
8888                 pic16_emitcode("inc","%s",rname);
8889
8890             offset++;
8891         }
8892     }
8893     
8894     /* now some housekeeping stuff */
8895     if (aop) {
8896         /* we had to allocate for this iCode */
8897         pic16_freeAsmop(NULL,aop,ic,TRUE);
8898     } else { 
8899         /* we did not allocate which means left
8900            already in a pointer register, then
8901            if size > 0 && this could be used again
8902            we have to point it back to where it 
8903            belongs */
8904         if (AOP_SIZE(right) > 1 &&
8905             !OP_SYMBOL(result)->remat &&
8906             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8907               ic->depth )) {
8908             int size = AOP_SIZE(right) - 1;
8909             while (size--)
8910                 pic16_emitcode("dec","%s",rname);
8911         }
8912     }
8913
8914     /* done */
8915     pic16_freeAsmop(right,NULL,ic,TRUE);
8916     
8917         
8918 }
8919
8920 /*-----------------------------------------------------------------*/
8921 /* genFarPointerSet - set value from far space                     */
8922 /*-----------------------------------------------------------------*/
8923 static void genFarPointerSet (operand *right,
8924                               operand *result, iCode *ic)
8925 {
8926     int size, offset ;
8927     sym_link *retype = getSpec(operandType(right));
8928
8929     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8930     pic16_aopOp(result,ic,FALSE);
8931
8932     /* if the operand is already in dptr 
8933     then we do nothing else we move the value to dptr */
8934     if (AOP_TYPE(result) != AOP_STR) {
8935         /* if this is remateriazable */
8936         if (AOP_TYPE(result) == AOP_IMMD)
8937             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8938         else { /* we need to get it byte by byte */
8939             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
8940             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
8941             if (options.model == MODEL_FLAT24)
8942             {
8943                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
8944             }
8945         }
8946     }
8947     /* so dptr know contains the address */
8948     pic16_freeAsmop(result,NULL,ic,TRUE);
8949     pic16_aopOp(right,ic,FALSE);
8950
8951     /* if bit then unpack */
8952     if (IS_BITVAR(retype)) 
8953         genPackBits(retype,right,"dptr",FPOINTER);
8954     else {
8955         size = AOP_SIZE(right);
8956         offset = 0 ;
8957
8958         while (size--) {
8959             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8960             MOVA(l);
8961             pic16_emitcode("movx","@dptr,a");
8962             if (size)
8963                 pic16_emitcode("inc","dptr");
8964         }
8965     }
8966
8967     pic16_freeAsmop(right,NULL,ic,TRUE);
8968 }
8969
8970 /*-----------------------------------------------------------------*/
8971 /* genGenPointerSet - set value from generic pointer space         */
8972 /*-----------------------------------------------------------------*/
8973 static void genGenPointerSet (operand *right,
8974                               operand *result, iCode *ic)
8975 {
8976   int size, offset ;
8977   sym_link *retype = getSpec(operandType(right));
8978
8979   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8980
8981   pic16_aopOp(result,ic,FALSE);
8982   pic16_aopOp(right,ic,FALSE);
8983   size = AOP_SIZE(right);
8984
8985   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8986
8987   /* if the operand is already in dptr 
8988      then we do nothing else we move the value to dptr */
8989   if (AOP_TYPE(result) != AOP_STR) {
8990     /* if this is remateriazable */
8991     if (AOP_TYPE(result) == AOP_IMMD) {
8992       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8993       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
8994     }
8995     else { /* we need to get it byte by byte */
8996       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8997       size = AOP_SIZE(right);
8998       offset = 0 ;
8999
9000       /* hack hack! see if this the FSR. If so don't load W */
9001       if(AOP_TYPE(right) != AOP_ACC) {
9002
9003
9004         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9005         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9006
9007         if(AOP_SIZE(result) > 1) {
9008           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9009           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9010           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9011
9012         }
9013
9014         //if(size==2)
9015         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9016         //if(size==4) {
9017         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9018         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9019         //}
9020
9021         while(size--) {
9022           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9023           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9024           
9025           if(size)
9026             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9027         }
9028
9029
9030         goto release;
9031       } 
9032
9033       if(aopIdx(AOP(result),0) != 4) {
9034
9035         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9036         goto release;
9037       }
9038
9039       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9040       goto release;
9041
9042     }
9043   }
9044   /* so dptr know contains the address */
9045
9046
9047   /* if bit then unpack */
9048   if (IS_BITVAR(retype)) 
9049     genPackBits(retype,right,"dptr",GPOINTER);
9050   else {
9051     size = AOP_SIZE(right);
9052     offset = 0 ;
9053
9054   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9055
9056     while (size--) {
9057
9058       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9059       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9060
9061       if (AOP_TYPE(right) == AOP_LIT) 
9062         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9063       else
9064         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9065
9066       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9067
9068       offset++;
9069     }
9070   }
9071
9072  release:
9073   pic16_freeAsmop(right,NULL,ic,TRUE);
9074   pic16_freeAsmop(result,NULL,ic,TRUE);
9075 }
9076
9077 /*-----------------------------------------------------------------*/
9078 /* genPointerSet - stores the value into a pointer location        */
9079 /*-----------------------------------------------------------------*/
9080 static void genPointerSet (iCode *ic)
9081 {    
9082     operand *right, *result ;
9083     sym_link *type, *etype;
9084     int p_type;
9085
9086     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9087
9088     right = IC_RIGHT(ic);
9089     result = IC_RESULT(ic) ;
9090
9091     /* depending on the type of pointer we need to
9092     move it to the correct pointer register */
9093     type = operandType(result);
9094     etype = getSpec(type);
9095     /* if left is of type of pointer then it is simple */
9096     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9097         p_type = DCL_TYPE(type);
9098     }
9099     else {
9100         /* we have to go by the storage class */
9101         p_type = PTR_TYPE(SPEC_OCLS(etype));
9102
9103 /*      if (SPEC_OCLS(etype)->codesp ) { */
9104 /*          p_type = CPOINTER ;  */
9105 /*      } */
9106 /*      else */
9107 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9108 /*              p_type = FPOINTER ; */
9109 /*          else */
9110 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9111 /*                  p_type = PPOINTER ; */
9112 /*              else */
9113 /*                  if (SPEC_OCLS(etype) == idata ) */
9114 /*                      p_type = IPOINTER ; */
9115 /*                  else */
9116 /*                      p_type = POINTER ; */
9117     }
9118
9119     /* now that we have the pointer type we assign
9120     the pointer values */
9121     switch (p_type) {
9122
9123     case POINTER:
9124     case IPOINTER:
9125         genNearPointerSet (right,result,ic);
9126         break;
9127
9128     case PPOINTER:
9129         genPagedPointerSet (right,result,ic);
9130         break;
9131
9132     case FPOINTER:
9133         genFarPointerSet (right,result,ic);
9134         break;
9135
9136     case GPOINTER:
9137         genGenPointerSet (right,result,ic);
9138         break;
9139
9140     default:
9141       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9142               "genPointerSet: illegal pointer type");
9143     }
9144 }
9145
9146 /*-----------------------------------------------------------------*/
9147 /* genIfx - generate code for Ifx statement                        */
9148 /*-----------------------------------------------------------------*/
9149 static void genIfx (iCode *ic, iCode *popIc)
9150 {
9151   operand *cond = IC_COND(ic);
9152   int isbit =0;
9153
9154   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9155
9156   pic16_aopOp(cond,ic,FALSE);
9157
9158   /* get the value into acc */
9159   if (AOP_TYPE(cond) != AOP_CRY)
9160     pic16_toBoolean(cond);
9161   else
9162     isbit = 1;
9163   /* the result is now in the accumulator */
9164   pic16_freeAsmop(cond,NULL,ic,TRUE);
9165
9166   /* if there was something to be popped then do it */
9167   if (popIc)
9168     genIpop(popIc);
9169
9170   /* if the condition is  a bit variable */
9171   if (isbit && IS_ITEMP(cond) && 
9172       SPIL_LOC(cond)) {
9173     genIfxJump(ic,SPIL_LOC(cond)->rname);
9174     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9175   }
9176   else {
9177     if (isbit && !IS_ITEMP(cond))
9178       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9179     else
9180       genIfxJump(ic,"a");
9181   }
9182   ic->generated = 1;
9183
9184 }
9185
9186 /*-----------------------------------------------------------------*/
9187 /* genAddrOf - generates code for address of                       */
9188 /*-----------------------------------------------------------------*/
9189 static void genAddrOf (iCode *ic)
9190 {
9191   operand *right, *result, *left;
9192   int size, offset ;
9193
9194   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9195
9196
9197   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9198
9199   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9200   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9201   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9202
9203   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9204
9205   size = AOP_SIZE(IC_RESULT(ic));
9206   offset = 0;
9207
9208
9209   while (size--) {
9210     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9211     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9212     offset++;
9213   }
9214
9215
9216   pic16_freeAsmop(left,NULL,ic,FALSE);
9217   pic16_freeAsmop(result,NULL,ic,TRUE);
9218
9219 }
9220
9221 #if 0
9222 /*-----------------------------------------------------------------*/
9223 /* genFarFarAssign - assignment when both are in far space         */
9224 /*-----------------------------------------------------------------*/
9225 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9226 {
9227     int size = AOP_SIZE(right);
9228     int offset = 0;
9229     char *l ;
9230     /* first push the right side on to the stack */
9231     while (size--) {
9232         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9233         MOVA(l);
9234         pic16_emitcode ("push","acc");
9235     }
9236     
9237     pic16_freeAsmop(right,NULL,ic,FALSE);
9238     /* now assign DPTR to result */
9239     pic16_aopOp(result,ic,FALSE);
9240     size = AOP_SIZE(result);
9241     while (size--) {
9242         pic16_emitcode ("pop","acc");
9243         pic16_aopPut(AOP(result),"a",--offset);
9244     }
9245     pic16_freeAsmop(result,NULL,ic,FALSE);
9246         
9247 }
9248 #endif
9249
9250 /*-----------------------------------------------------------------*/
9251 /* genAssign - generate code for assignment                        */
9252 /*-----------------------------------------------------------------*/
9253 static void genAssign (iCode *ic)
9254 {
9255   operand *result, *right;
9256   int size, offset,know_W;
9257   unsigned long lit = 0L;
9258
9259   result = IC_RESULT(ic);
9260   right  = IC_RIGHT(ic) ;
9261
9262   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9263   
9264   /* if they are the same */
9265   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9266     return ;
9267
9268   pic16_aopOp(right,ic,FALSE);
9269   pic16_aopOp(result,ic,TRUE);
9270
9271   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9272
9273   /* if they are the same registers */
9274   if (pic16_sameRegs(AOP(right),AOP(result)))
9275     goto release;
9276
9277   /* if the result is a bit */
9278   if (AOP_TYPE(result) == AOP_CRY) {
9279     /* if the right size is a literal then
9280        we know what the value is */
9281     if (AOP_TYPE(right) == AOP_LIT) {
9282           
9283       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9284                   pic16_popGet(AOP(result),0));
9285
9286       if (((int) operandLitValue(right))) 
9287         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9288                        AOP(result)->aopu.aop_dir,
9289                        AOP(result)->aopu.aop_dir);
9290       else
9291         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9292                        AOP(result)->aopu.aop_dir,
9293                        AOP(result)->aopu.aop_dir);
9294       goto release;
9295     }
9296
9297     /* the right is also a bit variable */
9298     if (AOP_TYPE(right) == AOP_CRY) {
9299       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9300       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9301       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9302
9303       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9304                      AOP(result)->aopu.aop_dir,
9305                      AOP(result)->aopu.aop_dir);
9306       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9307                      AOP(right)->aopu.aop_dir,
9308                      AOP(right)->aopu.aop_dir);
9309       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9310                      AOP(result)->aopu.aop_dir,
9311                      AOP(result)->aopu.aop_dir);
9312       goto release ;
9313     }
9314
9315     /* we need to or */
9316     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9317     pic16_toBoolean(right);
9318     emitSKPZ;
9319     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9320     //pic16_aopPut(AOP(result),"a",0);
9321     goto release ;
9322   }
9323
9324   /* bit variables done */
9325   /* general case */
9326   size = AOP_SIZE(result);
9327   offset = 0 ;
9328   if(AOP_TYPE(right) == AOP_LIT)
9329     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9330
9331 /* VR - What is this?! */
9332   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9333   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9334     if(aopIdx(AOP(result),0) == 4) {
9335   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9336       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9337       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9338       goto release;
9339     } else
9340       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9341   }
9342
9343   know_W=-1;
9344   while (size--) {
9345   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9346     if(AOP_TYPE(right) == AOP_LIT) {
9347       if(lit&0xff) {
9348         if(know_W != (lit&0xff))
9349           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9350         know_W = lit&0xff;
9351         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9352       } else
9353         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9354
9355       lit >>= 8;
9356
9357     } else if (AOP_TYPE(right) == AOP_CRY) {
9358       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9359       if(offset == 0) {
9360         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9361         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9362       }
9363     } else {
9364   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9365
9366 #if 1
9367         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9368            normally should work, but mind that thw W register live range
9369            is not checked, so if the code generator assumes that the W
9370            is already loaded after such a pair, wrong code will be generated.
9371            
9372            Checking the live range is the next step.
9373            This is experimental code yet and has not been fully tested yet.
9374            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9375            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9376            
9377         
9378         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9379 #else   
9380         /* This is the old code, which is assumed(?!) that works fine(!?) */
9381
9382         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9383         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9384 #endif
9385     }
9386             
9387     offset++;
9388   }
9389
9390     
9391  release:
9392   pic16_freeAsmop (right,NULL,ic,FALSE);
9393   pic16_freeAsmop (result,NULL,ic,TRUE);
9394 }   
9395
9396 /*-----------------------------------------------------------------*/
9397 /* genJumpTab - generates code for jump table                       */
9398 /*-----------------------------------------------------------------*/
9399 static void genJumpTab (iCode *ic)
9400 {
9401     symbol *jtab;
9402     char *l;
9403
9404     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9405
9406     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9407     /* get the condition into accumulator */
9408     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9409     MOVA(l);
9410     /* multiply by three */
9411     pic16_emitcode("add","a,acc");
9412     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9413
9414     jtab = newiTempLabel(NULL);
9415     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9416     pic16_emitcode("jmp","@a+dptr");
9417     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9418
9419     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9420     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9421     emitSKPNC;
9422     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9423     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9424     pic16_emitpLabel(jtab->key);
9425
9426     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9427
9428     /* now generate the jump labels */
9429     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9430          jtab = setNextItem(IC_JTLABELS(ic))) {
9431         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9432         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9433         
9434     }
9435
9436 }
9437
9438 /*-----------------------------------------------------------------*/
9439 /* genMixedOperation - gen code for operators between mixed types  */
9440 /*-----------------------------------------------------------------*/
9441 /*
9442   TSD - Written for the PIC port - but this unfortunately is buggy.
9443   This routine is good in that it is able to efficiently promote 
9444   types to different (larger) sizes. Unfortunately, the temporary
9445   variables that are optimized out by this routine are sometimes
9446   used in other places. So until I know how to really parse the 
9447   iCode tree, I'm going to not be using this routine :(.
9448 */
9449 static int genMixedOperation (iCode *ic)
9450 {
9451 #if 0
9452   operand *result = IC_RESULT(ic);
9453   sym_link *ctype = operandType(IC_LEFT(ic));
9454   operand *right = IC_RIGHT(ic);
9455   int ret = 0;
9456   int big,small;
9457   int offset;
9458
9459   iCode *nextic;
9460   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9461
9462   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9463
9464   nextic = ic->next;
9465   if(!nextic)
9466     return 0;
9467
9468   nextright = IC_RIGHT(nextic);
9469   nextleft  = IC_LEFT(nextic);
9470   nextresult = IC_RESULT(nextic);
9471
9472   pic16_aopOp(right,ic,FALSE);
9473   pic16_aopOp(result,ic,FALSE);
9474   pic16_aopOp(nextright,  nextic, FALSE);
9475   pic16_aopOp(nextleft,   nextic, FALSE);
9476   pic16_aopOp(nextresult, nextic, FALSE);
9477
9478   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9479
9480     operand *t = right;
9481     right = nextright;
9482     nextright = t; 
9483
9484     pic16_emitcode(";remove right +","");
9485
9486   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9487 /*
9488     operand *t = right;
9489     right = nextleft;
9490     nextleft = t; 
9491 */
9492     pic16_emitcode(";remove left +","");
9493   } else
9494     return 0;
9495
9496   big = AOP_SIZE(nextleft);
9497   small = AOP_SIZE(nextright);
9498
9499   switch(nextic->op) {
9500
9501   case '+':
9502     pic16_emitcode(";optimize a +","");
9503     /* if unsigned or not an integral type */
9504     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9505       pic16_emitcode(";add a bit to something","");
9506     } else {
9507
9508       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9509
9510       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9511         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9512         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9513       } else
9514         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9515
9516       offset = 0;
9517       while(--big) {
9518
9519         offset++;
9520
9521         if(--small) {
9522           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9523             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9524             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9525           }
9526
9527           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9528           emitSKPNC;
9529           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9530                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9531                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9532           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9533           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9534
9535         } else {
9536           pic16_emitcode("rlf","known_zero,w");
9537
9538           /*
9539             if right is signed
9540               btfsc  right,7
9541                addlw ff
9542           */
9543           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9544             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9545             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9546           } else {
9547             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9548           }
9549         }
9550       }
9551       ret = 1;
9552     }
9553   }
9554   ret = 1;
9555
9556 release:
9557   pic16_freeAsmop(right,NULL,ic,TRUE);
9558   pic16_freeAsmop(result,NULL,ic,TRUE);
9559   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9560   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9561   if(ret)
9562     nextic->generated = 1;
9563
9564   return ret;
9565 #else
9566   return 0;
9567 #endif
9568 }
9569 /*-----------------------------------------------------------------*/
9570 /* genCast - gen code for casting                                  */
9571 /*-----------------------------------------------------------------*/
9572 static void genCast (iCode *ic)
9573 {
9574     operand *result = IC_RESULT(ic);
9575     sym_link *ctype = operandType(IC_LEFT(ic));
9576     sym_link *rtype = operandType(IC_RIGHT(ic));
9577     operand *right = IC_RIGHT(ic);
9578     int size, offset ;
9579
9580     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9581     /* if they are equivalent then do nothing */
9582     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9583         return ;
9584
9585     pic16_aopOp(right,ic,FALSE) ;
9586     pic16_aopOp(result,ic,FALSE);
9587
9588     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9589
9590     /* if the result is a bit */
9591     if (AOP_TYPE(result) == AOP_CRY) {
9592         /* if the right size is a literal then
9593         we know what the value is */
9594       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9595         if (AOP_TYPE(right) == AOP_LIT) {
9596
9597           pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9598                       pic16_popGet(AOP(result),0));
9599
9600             if (((int) operandLitValue(right))) 
9601               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9602                        AOP(result)->aopu.aop_dir,
9603                        AOP(result)->aopu.aop_dir);
9604             else
9605               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9606                        AOP(result)->aopu.aop_dir,
9607                        AOP(result)->aopu.aop_dir);
9608
9609             goto release;
9610         }
9611
9612         /* the right is also a bit variable */
9613         if (AOP_TYPE(right) == AOP_CRY) {
9614
9615           emitCLRC;
9616           pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9617
9618           pic16_emitcode("clrc","");
9619           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9620                    AOP(right)->aopu.aop_dir,
9621                    AOP(right)->aopu.aop_dir);
9622             pic16_aopPut(AOP(result),"c",0);
9623             goto release ;
9624         }
9625
9626         /* we need to or */
9627         if (AOP_TYPE(right) == AOP_REG) {
9628           pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9629           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9630           pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9631         }
9632         pic16_toBoolean(right);
9633         pic16_aopPut(AOP(result),"a",0);
9634         goto release ;
9635     }
9636
9637     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9638       int offset = 1;
9639       size = AOP_SIZE(result);
9640
9641       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9642
9643       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9644       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9645       pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9646
9647       while (size--)
9648         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9649
9650       goto release;
9651     }
9652
9653     /* if they are the same size : or less */
9654     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9655
9656         /* if they are in the same place */
9657       if (pic16_sameRegs(AOP(right),AOP(result)))
9658         goto release;
9659
9660       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9661 #if 0
9662       if (IS_PTR_CONST(rtype))
9663 #else
9664       if (IS_CODEPTR(rtype))
9665 #endif
9666         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9667 #if 0
9668       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9669 #else
9670       if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9671 #endif
9672         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9673
9674       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9675         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9676         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9677         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9678         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9679         if(AOP_SIZE(result) <2)
9680           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9681
9682       } else {
9683
9684         /* if they in different places then copy */
9685         size = AOP_SIZE(result);
9686         offset = 0 ;
9687         while (size--) {
9688           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9689           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9690
9691           //pic16_aopPut(AOP(result),
9692           // pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9693           // offset);
9694
9695           offset++;
9696         }
9697       }
9698       goto release;
9699     }
9700
9701
9702     /* if the result is of type pointer */
9703     if (IS_PTR(ctype)) {
9704
9705         int p_type;
9706         sym_link *type = operandType(right);
9707         sym_link *etype = getSpec(type);
9708       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9709
9710         /* pointer to generic pointer */
9711         if (IS_GENPTR(ctype)) {
9712             char *l = zero;
9713             
9714             if (IS_PTR(type)) 
9715                 p_type = DCL_TYPE(type);
9716             else {
9717                 /* we have to go by the storage class */
9718                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9719
9720 /*              if (SPEC_OCLS(etype)->codesp )  */
9721 /*                  p_type = CPOINTER ;  */
9722 /*              else */
9723 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9724 /*                      p_type = FPOINTER ; */
9725 /*                  else */
9726 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9727 /*                          p_type = PPOINTER; */
9728 /*                      else */
9729 /*                          if (SPEC_OCLS(etype) == idata ) */
9730 /*                              p_type = IPOINTER ; */
9731 /*                          else */
9732 /*                              p_type = POINTER ; */
9733             }
9734                 
9735             /* the first two bytes are known */
9736       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9737             size = GPTRSIZE - 1; 
9738             offset = 0 ;
9739             while (size--) {
9740               if(offset < AOP_SIZE(right)) {
9741       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9742                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9743                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9744                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9745                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9746                 } else { 
9747                   pic16_aopPut(AOP(result),
9748                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9749                          offset);
9750                 }
9751               } else 
9752                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9753               offset++;
9754             }
9755             /* the last byte depending on type */
9756             switch (p_type) {
9757             case IPOINTER:
9758             case POINTER:
9759                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
9760                 break;
9761             case FPOINTER:
9762               pic16_emitcode(";BUG!? ","%d",__LINE__);
9763                 l = one;
9764                 break;
9765             case CPOINTER:
9766               pic16_emitcode(";BUG!? ","%d",__LINE__);
9767                 l = "#0x02";
9768                 break;                          
9769             case PPOINTER:
9770               pic16_emitcode(";BUG!? ","%d",__LINE__);
9771                 l = "#0x03";
9772                 break;
9773                 
9774             default:
9775                 /* this should never happen */
9776                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9777                        "got unknown pointer type");
9778                 exit(1);
9779             }
9780             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
9781             goto release ;
9782         }
9783         
9784         /* just copy the pointers */
9785         size = AOP_SIZE(result);
9786         offset = 0 ;
9787         while (size--) {
9788             pic16_aopPut(AOP(result),
9789                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9790                    offset);
9791             offset++;
9792         }
9793         goto release ;
9794     }
9795     
9796
9797
9798     /* so we now know that the size of destination is greater
9799     than the size of the source.
9800     Now, if the next iCode is an operator then we might be
9801     able to optimize the operation without performing a cast.
9802     */
9803     if(genMixedOperation(ic))
9804       goto release;
9805
9806     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9807     
9808     /* we move to result for the size of source */
9809     size = AOP_SIZE(right);
9810     offset = 0 ;
9811     while (size--) {
9812       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
9813       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
9814       offset++;
9815     }
9816
9817     /* now depending on the sign of the destination */
9818     size = AOP_SIZE(result) - AOP_SIZE(right);
9819     /* if unsigned or not an integral type */
9820     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9821       while (size--)
9822         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9823     } else {
9824       /* we need to extend the sign :{ */
9825
9826       if(size == 1) {
9827         /* Save one instruction of casting char to int */
9828         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9829         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9830         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
9831       } else {
9832         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9833
9834         if(offset)
9835           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9836         else
9837           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9838         
9839         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9840
9841         while (size--)
9842           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9843       }
9844     }
9845
9846 release:
9847     pic16_freeAsmop(right,NULL,ic,TRUE);
9848     pic16_freeAsmop(result,NULL,ic,TRUE);
9849
9850 }
9851
9852 /*-----------------------------------------------------------------*/
9853 /* genDjnz - generate decrement & jump if not zero instrucion      */
9854 /*-----------------------------------------------------------------*/
9855 static int genDjnz (iCode *ic, iCode *ifx)
9856 {
9857     symbol *lbl, *lbl1;
9858     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9859
9860     if (!ifx)
9861         return 0;
9862     
9863     /* if the if condition has a false label
9864        then we cannot save */
9865     if (IC_FALSE(ifx))
9866         return 0;
9867
9868     /* if the minus is not of the form 
9869        a = a - 1 */
9870     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9871         !IS_OP_LITERAL(IC_RIGHT(ic)))
9872         return 0;
9873
9874     if (operandLitValue(IC_RIGHT(ic)) != 1)
9875         return 0;
9876
9877     /* if the size of this greater than one then no
9878        saving */
9879     if (getSize(operandType(IC_RESULT(ic))) > 1)
9880         return 0;
9881
9882     /* otherwise we can save BIG */
9883     lbl = newiTempLabel(NULL);
9884     lbl1= newiTempLabel(NULL);
9885
9886     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9887     
9888     if (IS_AOP_PREG(IC_RESULT(ic))) {
9889         pic16_emitcode("dec","%s",
9890                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9891         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9892         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
9893     } else {    
9894
9895
9896       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9897       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9898
9899       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9900       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9901
9902     }
9903 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9904 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
9905 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9906 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
9907
9908     
9909     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9910     ifx->generated = 1;
9911     return 1;
9912 }
9913
9914 /*-----------------------------------------------------------------*/
9915 /* genReceive - generate code for a receive iCode                  */
9916 /*-----------------------------------------------------------------*/
9917 static void genReceive (iCode *ic)
9918 {    
9919   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9920
9921   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9922       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9923         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9924
9925     int size = getSize(operandType(IC_RESULT(ic)));
9926     int offset =  pic16_fReturnSizePic - size;
9927     while (size--) {
9928       pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9929                                     fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9930       offset++;
9931     }
9932     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9933     size = AOP_SIZE(IC_RESULT(ic));
9934     offset = 0;
9935     while (size--) {
9936       pic16_emitcode ("pop","acc");
9937       pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9938     }
9939         
9940   } else {
9941     _G.accInUse++;
9942     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
9943     _G.accInUse--;
9944     assignResultValue(IC_RESULT(ic));   
9945   }
9946
9947   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9948 }
9949
9950 /*-----------------------------------------------------------------*/
9951 /* genDummyRead - generate code for dummy read of volatiles        */
9952 /*-----------------------------------------------------------------*/
9953 static void
9954 genDummyRead (iCode * ic)
9955 {
9956   pic16_emitcode ("; genDummyRead","");
9957   pic16_emitcode ("; not implemented","");
9958
9959   ic = ic;
9960 }
9961
9962 /*-----------------------------------------------------------------*/
9963 /* genpic16Code - generate code for pic16 based controllers        */
9964 /*-----------------------------------------------------------------*/
9965 /*
9966  * At this point, ralloc.c has gone through the iCode and attempted
9967  * to optimize in a way suitable for a PIC. Now we've got to generate
9968  * PIC instructions that correspond to the iCode.
9969  *
9970  * Once the instructions are generated, we'll pass through both the
9971  * peep hole optimizer and the pCode optimizer.
9972  *-----------------------------------------------------------------*/
9973
9974 void genpic16Code (iCode *lic)
9975 {
9976     iCode *ic;
9977     int cln = 0;
9978
9979     lineHead = lineCurr = NULL;
9980
9981     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
9982     pic16_addpBlock(pb);
9983
9984 #if 0
9985     /* if debug information required */
9986     if (options.debug && currFunc) {
9987       if (currFunc) {
9988         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9989         _G.debugLine = 1;
9990         if (IS_STATIC(currFunc->etype)) {
9991           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9992           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
9993         } else {
9994           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9995           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
9996         }
9997         _G.debugLine = 0;
9998       }
9999     }
10000 #endif
10001
10002 //    dumpiCode(lic);
10003
10004     for (ic = lic ; ic ; ic = ic->next ) {
10005
10006 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10007 //      DEBUGpic16_emitcode("; VR", "");
10008       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10009         if ( cln != ic->lineno ) {
10010             if ( options.debug ) {
10011                 _G.debugLine = 1;
10012                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10013                          FileBaseName(ic->filename),ic->lineno,
10014                          ic->level,ic->block);
10015                 _G.debugLine = 0;
10016             }
10017             /*
10018               pic16_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
10019               pic16_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
10020               printCLine(ic->filename, ic->lineno));
10021             */
10022             pic16_addpCode2pBlock(pb,
10023                             pic16_newpCodeCSource(ic->lineno, 
10024                                             ic->filename, 
10025                                             printCLine(ic->filename, ic->lineno)));
10026
10027             cln = ic->lineno ;
10028         }
10029         /* if the result is marked as
10030            spilt and rematerializable or code for
10031            this has already been generated then
10032            do nothing */
10033         if (resultRemat(ic) || ic->generated ) 
10034             continue ;
10035         
10036         /* depending on the operation */
10037         switch (ic->op) {
10038         case '!' :
10039             genNot(ic);
10040             break;
10041             
10042         case '~' :
10043             genCpl(ic);
10044             break;
10045             
10046         case UNARYMINUS:
10047             genUminus (ic);
10048             break;
10049             
10050         case IPUSH:
10051             genIpush (ic);
10052             break;
10053             
10054         case IPOP:
10055             /* IPOP happens only when trying to restore a 
10056                spilt live range, if there is an ifx statement
10057                following this pop then the if statement might
10058                be using some of the registers being popped which
10059                would destroy the contents of the register so
10060                we need to check for this condition and handle it */
10061             if (ic->next            && 
10062                 ic->next->op == IFX &&
10063                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10064                 genIfx (ic->next,ic);
10065             else
10066                 genIpop (ic);
10067             break; 
10068             
10069         case CALL:
10070             genCall (ic);
10071             break;
10072             
10073         case PCALL:
10074             genPcall (ic);
10075             break;
10076             
10077         case FUNCTION:
10078             genFunction (ic);
10079             break;
10080             
10081         case ENDFUNCTION:
10082             genEndFunction (ic);
10083             break;
10084             
10085         case RETURN:
10086             genRet (ic);
10087             break;
10088             
10089         case LABEL:
10090             genLabel (ic);
10091             break;
10092             
10093         case GOTO:
10094             genGoto (ic);
10095             break;
10096             
10097         case '+' :
10098             pic16_genPlus (ic) ;
10099             break;
10100             
10101         case '-' :
10102             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10103                 pic16_genMinus (ic);
10104             break;
10105             
10106         case '*' :
10107             genMult (ic);
10108             break;
10109             
10110         case '/' :
10111             genDiv (ic) ;
10112             break;
10113             
10114         case '%' :
10115             genMod (ic);
10116             break;
10117             
10118         case '>' :
10119             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10120             break;
10121             
10122         case '<' :
10123             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10124             break;
10125             
10126         case LE_OP:
10127         case GE_OP:
10128         case NE_OP:
10129             
10130             /* note these two are xlated by algebraic equivalence
10131                during parsing SDCC.y */
10132             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10133                    "got '>=' or '<=' shouldn't have come here");
10134             break;      
10135             
10136         case EQ_OP:
10137             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10138             break;          
10139             
10140         case AND_OP:
10141             genAndOp (ic);
10142             break;
10143             
10144         case OR_OP:
10145             genOrOp (ic);
10146             break;
10147             
10148         case '^' :
10149             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10150             break;
10151             
10152         case '|' :
10153                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10154             break;
10155             
10156         case BITWISEAND:
10157             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10158             break;
10159             
10160         case INLINEASM:
10161             genInline (ic);
10162             break;
10163             
10164         case RRC:
10165             genRRC (ic);
10166             break;
10167             
10168         case RLC:
10169             genRLC (ic);
10170             break;
10171             
10172         case GETHBIT:
10173             genGetHbit (ic);
10174             break;
10175             
10176         case LEFT_OP:
10177             genLeftShift (ic);
10178             break;
10179             
10180         case RIGHT_OP:
10181             genRightShift (ic);
10182             break;
10183             
10184         case GET_VALUE_AT_ADDRESS:
10185             genPointerGet(ic);
10186             break;
10187             
10188         case '=' :
10189             if (POINTER_SET(ic))
10190                 genPointerSet(ic);
10191             else
10192                 genAssign(ic);
10193             break;
10194             
10195         case IFX:
10196             genIfx (ic,NULL);
10197             break;
10198             
10199         case ADDRESS_OF:
10200             genAddrOf (ic);
10201             break;
10202             
10203         case JUMPTABLE:
10204             genJumpTab (ic);
10205             break;
10206             
10207         case CAST:
10208             genCast (ic);
10209             break;
10210             
10211         case RECEIVE:
10212             genReceive(ic);
10213             break;
10214             
10215         case SEND:
10216             addSet(&_G.sendSet,ic);
10217             break;
10218
10219         case DUMMY_READ_VOLATILE:
10220           genDummyRead (ic);
10221           break;
10222
10223         default :
10224             ic = ic;
10225         }
10226     }
10227
10228
10229     /* now we are ready to call the
10230        peep hole optimizer */
10231     if (!options.nopeep) {
10232       peepHole (&lineHead);
10233     }
10234     /* now do the actual printing */
10235     printLine (lineHead,codeOutFile);
10236
10237 #ifdef PCODE_DEBUG
10238     DFPRINTF((stderr,"printing pBlock\n\n"));
10239     pic16_printpBlock(stdout,pb);
10240 #endif
10241
10242     return;
10243 }
10244