9bd719d2b2c2936d1001b91d7b3b3aaf8c447442
[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 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
81
82 /* this is the down and dirty file with all kinds of 
83    kludgy & hacky stuff. This is what it is all about
84    CODE GENERATION for a specific MCU . some of the
85    routines may be reusable, will have to see */
86
87 static char *zero = "#0x00";
88 static char *one  = "#0x01";
89 static char *spname = "sp";
90
91 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
92 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
93 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
94 static char **fReturn = fReturnpic16;
95
96 static char *accUse[] = {"a","b"};
97
98 //static short rbank = -1;
99
100 static struct {
101     short r0Pushed;
102     short r1Pushed;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108 } _G;
109
110 /* Resolved ifx structure. This structure stores information
111    about an iCode ifx that makes it easier to generate code.
112 */
113 typedef struct resolvedIfx {
114   symbol *lbl;     /* pointer to a label */
115   int condition;   /* true or false ifx */
116   int generated;   /* set true when the code associated with the ifx
117                     * is generated */
118 } resolvedIfx;
119
120 extern int pic16_ptrRegReq ;
121 extern int pic16_nRegs;
122 extern FILE *codeOutFile;
123 static void saverbank (int, iCode *,bool);
124
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
127
128 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
129 0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
131 0x07, 0x03, 0x01, 0x00};
132
133 static  pBlock *pb;
134
135 /*-----------------------------------------------------------------*/
136 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
137 /*                 exponent of 2 is returned, otherwise -1 is      */
138 /*                 returned.                                       */
139 /* note that this is similar to the function `powof2' in SDCCsymt  */
140 /* if(n == 2^y)                                                    */
141 /*   return y;                                                     */
142 /* return -1;                                                      */
143 /*-----------------------------------------------------------------*/
144 static int my_powof2 (unsigned long num)
145 {
146   if(num) {
147     if( (num & (num-1)) == 0) {
148       int nshifts = -1;
149       while(num) {
150         num>>=1;
151         nshifts++;
152       }
153       return nshifts;
154     }
155   }
156
157   return -1;
158 }
159
160 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
161 {
162
163   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
164                        line_no,
165                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
166                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
167                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
168                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
170                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                        ((result) ? AOP_SIZE(result) : 0));
172
173 }
174
175 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177
178   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                        line_no,
180                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
181                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
183                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
184                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
185                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186
187 }
188
189 void pic16_emitcomment (char *fmt, ...)
190 {
191     va_list ap;
192     char lb[INITIAL_INLINEASM];  
193     char *lbp = lb;
194
195     if(!pic16_debug_verbose)
196       return;
197
198     va_start(ap,fmt);   
199
200     lb[0] = ';';
201     vsprintf(lb+1,fmt,ap);
202
203     while (isspace(*lbp)) lbp++;
204
205     if (lbp && *lbp) 
206         lineCurr = (lineCurr ?
207                     connectLine(lineCurr,newLineNode(lb)) :
208                     (lineHead = newLineNode(lb)));
209     lineCurr->isInline = _G.inLine;
210     lineCurr->isDebug  = _G.debugLine;
211
212     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
213     va_end(ap);
214
215 //      fprintf(stderr, "%s\n", lb);
216 }
217
218 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
219 {
220     va_list ap;
221     char lb[INITIAL_INLINEASM];  
222     char *lbp = lb;
223
224     if(!pic16_debug_verbose)
225       return;
226
227     va_start(ap,fmt);   
228
229     if (inst && *inst) {
230         if (fmt && *fmt)
231             sprintf(lb,"%s\t",inst);
232         else
233             sprintf(lb,"%s",inst);
234         vsprintf(lb+(strlen(lb)),fmt,ap);
235     }  else
236         vsprintf(lb,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
248     va_end(ap);
249
250 //      fprintf(stderr, "%s\n", lb);
251 }
252
253 void pic16_emitpLabel(int key)
254 {
255   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
256 }
257
258 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
259 {
260
261   if(pcop)
262     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
263   else
264     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
265     
266 //    fprintf(stderr, "%s\n", pcop->name);
267 }
268
269 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
270 {
271
272   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
273
274 }
275
276 /*-----------------------------------------------------------------*/
277 /* pic16_emitcode - writes the code into a file : for now it is simple    */
278 /*-----------------------------------------------------------------*/
279 void pic16_emitcode (char *inst,char *fmt, ...)
280 {
281     va_list ap;
282     char lb[INITIAL_INLINEASM];  
283     char *lbp = lb;
284
285     va_start(ap,fmt);   
286
287     if (inst && *inst) {
288         if (fmt && *fmt)
289             sprintf(lb,"%s\t",inst);
290         else
291             sprintf(lb,"%s",inst);
292         vsprintf(lb+(strlen(lb)),fmt,ap);
293     }  else
294         vsprintf(lb,fmt,ap);
295
296     while (isspace(*lbp)) lbp++;
297
298     if (lbp && *lbp) 
299         lineCurr = (lineCurr ?
300                     connectLine(lineCurr,newLineNode(lb)) :
301                     (lineHead = newLineNode(lb)));
302     lineCurr->isInline = _G.inLine;
303     lineCurr->isDebug  = _G.debugLine;
304
305 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
306
307 //    if(pic16_debug_verbose)
308 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
309
310     va_end(ap);
311 }
312
313
314 /*-----------------------------------------------------------------*/
315 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
316 /*-----------------------------------------------------------------*/
317 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
318 {
319     bool r0iu = FALSE , r1iu = FALSE;
320     bool r0ou = FALSE , r1ou = FALSE;
321
322         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
323
324     /* the logic: if r0 & r1 used in the instruction
325     then we are in trouble otherwise */
326
327     /* first check if r0 & r1 are used by this
328     instruction, in which case we are in trouble */
329     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
330         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
331     {
332         goto endOfWorld;      
333     }
334
335     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
336     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
337
338     /* if no usage of r0 then return it */
339     if (!r0iu && !r0ou) {
340         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
341         (*aopp)->type = AOP_R0;
342         
343         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
344     }
345
346     /* if no usage of r1 then return it */
347     if (!r1iu && !r1ou) {
348         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
349         (*aopp)->type = AOP_R1;
350
351         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
352     }    
353
354     /* now we know they both have usage */
355     /* if r0 not used in this instruction */
356     if (!r0iu) {
357         /* push it if not already pushed */
358         if (!_G.r0Pushed) {
359           //pic16_emitcode ("push","%s",
360           //          pic16_regWithIdx(R0_IDX)->dname);
361             _G.r0Pushed++ ;
362         }
363         
364         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
365         (*aopp)->type = AOP_R0;
366
367         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
368     }
369
370     /* if r1 not used then */
371
372     if (!r1iu) {
373         /* push it if not already pushed */
374         if (!_G.r1Pushed) {
375           //pic16_emitcode ("push","%s",
376           //          pic16_regWithIdx(R1_IDX)->dname);
377             _G.r1Pushed++ ;
378         }
379         
380         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
381         (*aopp)->type = AOP_R1;
382         return pic16_regWithIdx(R1_IDX);
383     }
384
385 endOfWorld :
386     /* I said end of world but not quite end of world yet */
387     /* if this is a result then we can push it on the stack*/
388     if (result) {
389         (*aopp)->type = AOP_STK;    
390         return NULL;
391     }
392
393     /* other wise this is true end of the world */
394     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
395            "getFreePtr should never reach here");
396     exit(0);
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* newAsmop - creates a new asmOp                                  */
401 /*-----------------------------------------------------------------*/
402 static asmop *newAsmop (short type)
403 {
404     asmop *aop;
405
406     aop = Safe_calloc(1,sizeof(asmop));
407     aop->type = type;
408     return aop;
409 }
410
411 static void genSetDPTR(int n)
412 {
413     if (!n)
414     {
415         pic16_emitcode(";", "Select standard DPTR");
416         pic16_emitcode("mov", "dps, #0x00");
417     }
418     else
419     {
420         pic16_emitcode(";", "Select alternate DPTR");
421         pic16_emitcode("mov", "dps, #0x01");
422     }
423 }
424
425 /*-----------------------------------------------------------------*/
426 /* resolveIfx - converts an iCode ifx into a form more useful for  */
427 /*              generating code                                    */
428 /*-----------------------------------------------------------------*/
429 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
430 {
431   if(!resIfx) 
432     return;
433
434   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
435
436   resIfx->condition = 1;    /* assume that the ifx is true */
437   resIfx->generated = 0;    /* indicate that the ifx has not been used */
438
439   if(!ifx) {
440     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
441 /*
442     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
443                         __FUNCTION__,__LINE__,resIfx->lbl->key);
444 */
445   } else {
446     if(IC_TRUE(ifx)) {
447       resIfx->lbl = IC_TRUE(ifx);
448     } else {
449       resIfx->lbl = IC_FALSE(ifx);
450       resIfx->condition = 0;
451     }
452 /*
453     if(IC_TRUE(ifx)) 
454       DEBUGpic16_emitcode("; ***","ifx true is non-null");
455     if(IC_FALSE(ifx)) 
456       DEBUGpic16_emitcode("; ***","ifx false is non-null");
457 */
458   }
459
460   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
461
462 }
463 /*-----------------------------------------------------------------*/
464 /* pointerCode - returns the code for a pointer type               */
465 /*-----------------------------------------------------------------*/
466 static int pointerCode (sym_link *etype)
467 {
468
469     return PTR_TYPE(SPEC_OCLS(etype));
470
471 }
472
473 /*-----------------------------------------------------------------*/
474 /* aopForSym - for a true symbol                                   */
475 /*-----------------------------------------------------------------*/
476 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
477 {
478     asmop *aop;
479     memmap *space= SPEC_OCLS(sym->etype);
480
481     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
482     /* if already has one */
483     if (sym->aop) {
484             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
485         return sym->aop;
486     }
487
488     /* assign depending on the storage class */
489     /* if it is on the stack or indirectly addressable */
490     /* space we need to assign either r0 or r1 to it   */    
491     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
492         sym->aop = aop = newAsmop(0);
493         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
494         aop->size = getSize(sym->type);
495
496         /* now assign the address of the variable to 
497         the pointer register */
498         if (aop->type != AOP_STK) {
499
500             if (sym->onStack) {
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                     pic16_emitcode("mov","%s,a",
510                              aop->aopu.aop_ptr->name);
511
512                     if ( _G.accInUse )
513                         pic16_emitcode("pop","acc");
514             } else
515                 pic16_emitcode("mov","%s,#%s",
516                          aop->aopu.aop_ptr->name,
517                          sym->rname);
518             aop->paged = space->paged;
519         } else
520             aop->aopu.aop_stk = sym->stack;
521         return aop;
522     }
523     
524     if (sym->onStack && options.stack10bit)
525     {
526         /* It's on the 10 bit stack, which is located in
527          * far data space.
528          */
529          
530       //DEBUGpic16_emitcode(";","%d",__LINE__);
531
532         if ( _G.accInUse )
533                 pic16_emitcode("push","acc");
534
535         pic16_emitcode("mov","a,_bp");
536         pic16_emitcode("add","a,#0x%02x",
537                  ((sym->stack < 0) ?
538                    ((char)(sym->stack - _G.nRegsSaved )) :
539                    ((char)sym->stack)) & 0xff);
540         
541         genSetDPTR(1);
542         pic16_emitcode ("mov","dpx1,#0x40");
543         pic16_emitcode ("mov","dph1,#0x00");
544         pic16_emitcode ("mov","dpl1, a");
545         genSetDPTR(0);
546         
547         if ( _G.accInUse )
548             pic16_emitcode("pop","acc");
549             
550         sym->aop = aop = newAsmop(AOP_DPTR2);
551         aop->size = getSize(sym->type); 
552         return aop;
553     }
554
555     //DEBUGpic16_emitcode(";","%d",__LINE__);
556     /* if in bit space */
557     if (IN_BITSPACE(space)) {
558         sym->aop = aop = newAsmop (AOP_CRY);
559         aop->aopu.aop_dir = sym->rname ;
560         aop->size = getSize(sym->type);
561         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
562         return aop;
563     }
564     /* if it is in direct space */
565     if (IN_DIRSPACE(space)) {
566         sym->aop = aop = newAsmop (AOP_DIR);
567         aop->aopu.aop_dir = sym->rname ;
568         aop->size = getSize(sym->type);
569         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
570         return aop;
571     }
572
573     /* special case for a function */
574     if (IS_FUNC(sym->type)) {   
575         sym->aop = aop = newAsmop(AOP_IMMD);    
576         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
577         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
578         strcpy(aop->aopu.aop_immd,sym->rname);
579         aop->size = FPTRSIZE; 
580         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
581         return aop;
582     }
583
584
585     /* only remaining is far space */
586     /* in which case DPTR gets the address */
587     sym->aop = aop = newAsmop(AOP_PCODE);
588
589     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
590     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
591     PCOI(aop->aopu.pcop)->index = 0;
592
593     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
594                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
595
596     pic16_allocDirReg (IC_LEFT(ic));
597
598     aop->size = FPTRSIZE; 
599 /*
600     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
601     sym->aop = aop = newAsmop(AOP_DPTR);
602     pic16_emitcode ("mov","dptr,#%s", sym->rname);
603     aop->size = getSize(sym->type);
604
605     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
606 */
607
608     /* if it is in code space */
609     if (IN_CODESPACE(space))
610         aop->code = 1;
611
612     return aop;     
613 }
614
615 /*-----------------------------------------------------------------*/
616 /* aopForRemat - rematerialzes an object                           */
617 /*-----------------------------------------------------------------*/
618 static asmop *aopForRemat (operand *op) // x symbol *sym)
619 {
620   symbol *sym = OP_SYMBOL(op);
621   iCode *ic = NULL;
622   asmop *aop = newAsmop(AOP_PCODE);
623   int val = 0;
624   int offset = 0;
625
626   ic = sym->rematiCode;
627
628   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
629   if(IS_OP_POINTER(op)) {
630     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
631   }
632   for (;;) {
633     if (ic->op == '+') {
634       val += (int) operandLitValue(IC_RIGHT(ic));
635     } else if (ic->op == '-') {
636       val -= (int) operandLitValue(IC_RIGHT(ic));
637     } else
638       break;
639         
640     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
641   }
642
643   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
644   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
645 #if 0
646   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
647 #else
648   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
649 #endif
650   PCOI(aop->aopu.pcop)->index = val;
651
652   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
653                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
654 #if 0
655                       val, IS_PTR_CONST(operandType(op)));
656 #else
657                       val, IS_CODEPTR(operandType(op)));
658 #endif
659
660   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
661
662   pic16_allocDirReg (IC_LEFT(ic));
663
664   return aop;        
665 }
666
667 static int aopIdx (asmop *aop, int offset)
668 {
669   if(!aop)
670     return -1;
671
672   if(aop->type !=  AOP_REG)
673     return -2;
674         
675   return aop->aopu.aop_reg[offset]->rIdx;
676
677 }
678 /*-----------------------------------------------------------------*/
679 /* regsInCommon - two operands have some registers in common       */
680 /*-----------------------------------------------------------------*/
681 static bool regsInCommon (operand *op1, operand *op2)
682 {
683     symbol *sym1, *sym2;
684     int i;
685
686     /* if they have registers in common */
687     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
688         return FALSE ;
689
690     sym1 = OP_SYMBOL(op1);
691     sym2 = OP_SYMBOL(op2);
692
693     if (sym1->nRegs == 0 || sym2->nRegs == 0)
694         return FALSE ;
695
696     for (i = 0 ; i < sym1->nRegs ; i++) {
697         int j;
698         if (!sym1->regs[i])
699             continue ;
700
701         for (j = 0 ; j < sym2->nRegs ;j++ ) {
702             if (!sym2->regs[j])
703                 continue ;
704
705             if (sym2->regs[j] == sym1->regs[i])
706                 return TRUE ;
707         }
708     }
709
710     return FALSE ;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* operandsEqu - equivalent                                        */
715 /*-----------------------------------------------------------------*/
716 static bool operandsEqu ( operand *op1, operand *op2)
717 {
718     symbol *sym1, *sym2;
719
720     /* if they not symbols */
721     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
722         return FALSE;
723
724     sym1 = OP_SYMBOL(op1);
725     sym2 = OP_SYMBOL(op2);
726
727     /* if both are itemps & one is spilt
728        and the other is not then false */
729     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
730         sym1->isspilt != sym2->isspilt )
731         return FALSE ;
732
733     /* if they are the same */
734     if (sym1 == sym2)
735         return TRUE ;
736
737     if (strcmp(sym1->rname,sym2->rname) == 0)
738         return TRUE;
739
740
741     /* if left is a tmp & right is not */
742     if (IS_ITEMP(op1)  && 
743         !IS_ITEMP(op2) &&
744         sym1->isspilt  &&
745         (sym1->usl.spillLoc == sym2))
746         return TRUE;
747
748     if (IS_ITEMP(op2)  && 
749         !IS_ITEMP(op1) &&
750         sym2->isspilt  &&
751         sym1->level > 0 &&
752         (sym2->usl.spillLoc == sym1))
753         return TRUE ;
754
755     return FALSE ;
756 }
757
758 /*-----------------------------------------------------------------*/
759 /* pic16_sameRegs - two asmops have the same registers                   */
760 /*-----------------------------------------------------------------*/
761 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
762 {
763     int i;
764
765     if (aop1 == aop2)
766         return TRUE ;
767
768     if (aop1->type != AOP_REG ||
769         aop2->type != AOP_REG )
770         return FALSE ;
771
772     if (aop1->size != aop2->size )
773         return FALSE ;
774
775     for (i = 0 ; i < aop1->size ; i++ )
776         if (aop1->aopu.aop_reg[i] !=
777             aop2->aopu.aop_reg[i] )
778             return FALSE ;
779
780     return TRUE ;
781 }
782
783 /*-----------------------------------------------------------------*/
784 /* pic16_aopOp - allocates an asmop for an operand  :                    */
785 /*-----------------------------------------------------------------*/
786 void pic16_aopOp (operand *op, iCode *ic, bool result)
787 {
788     asmop *aop;
789     symbol *sym;
790     int i;
791
792     if (!op)
793         return ;
794
795 //      DEBUGpic16_emitcode(";","%d",__LINE__);
796
797     /* if this a literal */
798     if (IS_OP_LITERAL(op)) {
799         op->aop = aop = newAsmop(AOP_LIT);
800         aop->aopu.aop_lit = op->operand.valOperand;
801         aop->size = getSize(operandType(op));
802         return;
803     }
804
805     {
806       sym_link *type = operandType(op);
807 #if 0
808       if(IS_PTR_CONST(type))
809 #else
810       if(IS_CODEPTR(type))
811 #endif
812         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
813     }
814
815     /* if already has a asmop then continue */
816     if (op->aop)
817         return ;
818
819     /* if the underlying symbol has a aop */
820     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
821       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
822         op->aop = OP_SYMBOL(op)->aop;
823         return;
824     }
825
826     /* if this is a true symbol */
827     if (IS_TRUE_SYMOP(op)) {    
828         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
829       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
830       return ;
831     }
832
833     /* this is a temporary : this has
834     only four choices :
835     a) register
836     b) spillocation
837     c) rematerialize 
838     d) conditional   
839     e) can be a return use only */
840
841     sym = OP_SYMBOL(op);
842
843         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
844     /* if the type is a conditional */
845     if (sym->regType == REG_CND) {
846         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
847         aop->size = 0;
848         return;
849     }
850
851     /* if it is spilt then two situations
852     a) is rematerialize 
853     b) has a spill location */
854     if (sym->isspilt || sym->nRegs == 0) {
855
856       DEBUGpic16_emitcode(";","%d",__LINE__);
857         /* rematerialize it NOW */
858         if (sym->remat) {
859
860             sym->aop = op->aop = aop =
861                                       aopForRemat (op);
862             aop->size = getSize(sym->type);
863             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
864             return;
865         }
866
867         if (sym->accuse) {
868             int i;
869             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
870             aop->size = getSize(sym->type);
871             for ( i = 0 ; i < 2 ; i++ )
872                 aop->aopu.aop_str[i] = accUse[i];
873             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
874             return;  
875         }
876
877         if (sym->ruonly ) {
878           /*
879           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
880           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
881           //pic16_allocDirReg (IC_LEFT(ic));
882           aop->size = getSize(sym->type);
883           */
884
885           unsigned i;
886
887           aop = op->aop = sym->aop = newAsmop(AOP_STR);
888           aop->size = getSize(sym->type);
889           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
890             aop->aopu.aop_str[i] = fReturn[i];
891
892           DEBUGpic16_emitcode(";","%d",__LINE__);
893           return;
894         }
895
896         /* else spill location  */
897         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
898             /* force a new aop if sizes differ */
899             sym->usl.spillLoc->aop = NULL;
900         }
901         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
902                             __FUNCTION__,__LINE__,
903                             sym->usl.spillLoc->rname,
904                             sym->rname, sym->usl.spillLoc->offset);
905
906         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
907         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
908         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
909                                           getSize(sym->type), 
910                                           sym->usl.spillLoc->offset);
911         aop->size = getSize(sym->type);
912
913         return;
914     }
915
916     {
917       sym_link *type = operandType(op);
918 #if 0
919       if(IS_PTR_CONST(type)) 
920 #else
921       if(IS_CODEPTR(type)) 
922 #endif
923         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
924     }
925
926     /* must be in a register */
927     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
928     sym->aop = op->aop = aop = newAsmop(AOP_REG);
929     aop->size = sym->nRegs;
930     for ( i = 0 ; i < sym->nRegs ;i++)
931         aop->aopu.aop_reg[i] = sym->regs[i];
932 }
933
934 /*-----------------------------------------------------------------*/
935 /* pic16_freeAsmop - free up the asmop given to an operand               */
936 /*----------------------------------------------------------------*/
937 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
938 {   
939     asmop *aop ;
940
941     if (!op)
942         aop = aaop;
943     else 
944         aop = op->aop;
945
946     if (!aop)
947         return ;
948
949     if (aop->freed)
950         goto dealloc; 
951
952     aop->freed = 1;
953
954     /* depending on the asmop type only three cases need work AOP_RO
955        , AOP_R1 && AOP_STK */
956 #if 0
957     switch (aop->type) {
958         case AOP_R0 :
959             if (_G.r0Pushed ) {
960                 if (pop) {
961                     pic16_emitcode ("pop","ar0");     
962                     _G.r0Pushed--;
963                 }
964             }
965             bitVectUnSetBit(ic->rUsed,R0_IDX);
966             break;
967
968         case AOP_R1 :
969             if (_G.r1Pushed ) {
970                 if (pop) {
971                     pic16_emitcode ("pop","ar1");
972                     _G.r1Pushed--;
973                 }
974             }
975             bitVectUnSetBit(ic->rUsed,R1_IDX);          
976             break;
977
978         case AOP_STK :
979         {
980             int sz = aop->size;    
981             int stk = aop->aopu.aop_stk + aop->size;
982             bitVectUnSetBit(ic->rUsed,R0_IDX);
983             bitVectUnSetBit(ic->rUsed,R1_IDX);          
984
985             getFreePtr(ic,&aop,FALSE);
986             
987             if (options.stack10bit)
988             {
989                 /* I'm not sure what to do here yet... */
990                 /* #STUB */
991                 fprintf(stderr, 
992                         "*** Warning: probably generating bad code for "
993                         "10 bit stack mode.\n");
994             }
995             
996             if (stk) {
997                 pic16_emitcode ("mov","a,_bp");
998                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
999                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1000             } else {
1001                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1002             }
1003
1004             while (sz--) {
1005                 pic16_emitcode("pop","acc");
1006                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1007                 if (!sz) break;
1008                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1009             }
1010             op->aop = aop;
1011             pic16_freeAsmop(op,NULL,ic,TRUE);
1012             if (_G.r0Pushed) {
1013                 pic16_emitcode("pop","ar0");
1014                 _G.r0Pushed--;
1015             }
1016
1017             if (_G.r1Pushed) {
1018                 pic16_emitcode("pop","ar1");
1019                 _G.r1Pushed--;
1020             }       
1021         }
1022     }
1023 #endif
1024
1025 dealloc:
1026     /* all other cases just dealloc */
1027     if (op ) {
1028         op->aop = NULL;
1029         if (IS_SYMOP(op)) {
1030             OP_SYMBOL(op)->aop = NULL;    
1031             /* if the symbol has a spill */
1032             if (SPIL_LOC(op))
1033                 SPIL_LOC(op)->aop = NULL;
1034         }
1035     }
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* pic16_aopGet - for fetching value of the aop                          */
1040 /*-----------------------------------------------------------------*/
1041 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1042 {
1043     char *s = buffer ;
1044     char *rs;
1045
1046     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1047     /* offset is greater than
1048     size then zero */
1049     if (offset > (aop->size - 1) &&
1050         aop->type != AOP_LIT)
1051         return zero;
1052
1053     /* depending on type */
1054     switch (aop->type) {
1055         
1056     case AOP_R0:
1057     case AOP_R1:
1058         DEBUGpic16_emitcode(";","%d",__LINE__);
1059         /* if we need to increment it */       
1060         while (offset > aop->coff) {        
1061             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1062             aop->coff++;
1063         }
1064         
1065         while (offset < aop->coff) {
1066             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1067             aop->coff--;
1068         }
1069         
1070         aop->coff = offset ;
1071         if (aop->paged) {
1072             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1073             return (dname ? "acc" : "a");
1074         }       
1075         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1076         rs = Safe_calloc(1,strlen(s)+1);
1077         strcpy(rs,s);   
1078         return rs;
1079         
1080     case AOP_DPTR:
1081     case AOP_DPTR2:
1082         DEBUGpic16_emitcode(";","%d",__LINE__);
1083     if (aop->type == AOP_DPTR2)
1084     {
1085         genSetDPTR(1);
1086     }
1087     
1088         while (offset > aop->coff) {
1089             pic16_emitcode ("inc","dptr");
1090             aop->coff++;
1091         }
1092         
1093         while (offset < aop->coff) {        
1094             pic16_emitcode("lcall","__decdptr");
1095             aop->coff--;
1096         }
1097         
1098         aop->coff = offset;
1099         if (aop->code) {
1100             pic16_emitcode("clr","a");
1101             pic16_emitcode("movc","a,@a+dptr");
1102         }
1103     else {
1104             pic16_emitcode("movx","a,@dptr");
1105     }
1106             
1107     if (aop->type == AOP_DPTR2)
1108     {
1109         genSetDPTR(0);
1110     }
1111             
1112     return (dname ? "acc" : "a");
1113         
1114         
1115     case AOP_IMMD:
1116         if (bit16) 
1117             sprintf (s,"%s",aop->aopu.aop_immd);
1118         else
1119             if (offset) 
1120                 sprintf(s,"(%s >> %d)",
1121                         aop->aopu.aop_immd,
1122                         offset*8);
1123             else
1124                 sprintf(s,"%s",
1125                         aop->aopu.aop_immd);
1126         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1127         rs = Safe_calloc(1,strlen(s)+1);
1128         strcpy(rs,s);   
1129         return rs;
1130         
1131     case AOP_DIR:
1132       if (offset) {
1133         sprintf(s,"(%s + %d)",
1134                 aop->aopu.aop_dir,
1135                 offset);
1136         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1137       } else
1138             sprintf(s,"%s",aop->aopu.aop_dir);
1139         rs = Safe_calloc(1,strlen(s)+1);
1140         strcpy(rs,s);   
1141         return rs;
1142         
1143     case AOP_REG:
1144       //if (dname) 
1145       //    return aop->aopu.aop_reg[offset]->dname;
1146       //else
1147             return aop->aopu.aop_reg[offset]->name;
1148         
1149     case AOP_CRY:
1150       //pic16_emitcode(";","%d",__LINE__);
1151       return aop->aopu.aop_dir;
1152         
1153     case AOP_ACC:
1154         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1155         return "AOP_accumulator_bug";
1156
1157     case AOP_LIT:
1158         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1159         rs = Safe_calloc(1,strlen(s)+1);
1160         strcpy(rs,s);   
1161         return rs;
1162         
1163     case AOP_STR:
1164         aop->coff = offset ;
1165         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1166             dname)
1167             return "acc";
1168         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1169         
1170         return aop->aopu.aop_str[offset];
1171         
1172     case AOP_PCODE:
1173       {
1174         pCodeOp *pcop = aop->aopu.pcop;
1175         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1176         if(pcop->name) {
1177           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1178           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1179           sprintf(s,"%s", pcop->name);
1180         } else
1181           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1182
1183       }
1184       rs = Safe_calloc(1,strlen(s)+1);
1185       strcpy(rs,s);   
1186       return rs;
1187
1188     }
1189
1190     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1191            "aopget got unsupported aop->type");
1192     exit(0);
1193 }
1194
1195
1196 /*-----------------------------------------------------------------*/
1197 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1198 /*-----------------------------------------------------------------*/
1199 pCodeOp *pic16_popGetTempReg(void)
1200 {
1201
1202   pCodeOp *pcop;
1203
1204   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1205   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1206     PCOR(pcop)->r->wasUsed=1;
1207     PCOR(pcop)->r->isFree=0;
1208   }
1209
1210   return pcop;
1211 }
1212
1213 /*-----------------------------------------------------------------*/
1214 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1215 /*-----------------------------------------------------------------*/
1216 void pic16_popReleaseTempReg(pCodeOp *pcop)
1217 {
1218
1219   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1220     PCOR(pcop)->r->isFree = 1;
1221
1222 }
1223 /*-----------------------------------------------------------------*/
1224 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1225 /*-----------------------------------------------------------------*/
1226 pCodeOp *pic16_popGetLabel(unsigned int key)
1227 {
1228
1229   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1230
1231   if(key>max_key)
1232     max_key = key;
1233
1234   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1235 }
1236
1237 /*-----------------------------------------------------------------*/
1238 /* pic16_popCopyReg - copy a pcode operator                              */
1239 /*-----------------------------------------------------------------*/
1240 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1241 {
1242   pCodeOpReg *pcor;
1243
1244   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1245   pcor->pcop.type = pc->pcop.type;
1246   if(pc->pcop.name) {
1247     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1248       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1249   } else
1250     pcor->pcop.name = NULL;
1251
1252   pcor->r = pc->r;
1253   pcor->rIdx = pc->rIdx;
1254   pcor->r->wasUsed=1;
1255
1256   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1257
1258   return PCOP(pcor);
1259 }
1260
1261 /*-----------------------------------------------------------------*/
1262 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *pic16_popGetLit(unsigned int lit)
1265 {
1266   return pic16_newpCodeOpLit(lit);
1267 }
1268
1269 /*-----------------------------------------------------------------*/
1270 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1271 /*-----------------------------------------------------------------*/
1272 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1273 {
1274   return pic16_newpCodeOpLit2(lit, arg2);
1275 }
1276
1277
1278 /*-----------------------------------------------------------------*/
1279 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1280 /*-----------------------------------------------------------------*/
1281 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1282 {
1283
1284   return pic16_newpCodeOpImmd(name, offset,index, 0);
1285 }
1286
1287
1288 /*-----------------------------------------------------------------*/
1289 /* pic16_popGet - asm operator to pcode operator conversion              */
1290 /*-----------------------------------------------------------------*/
1291 pCodeOp *pic16_popGetWithString(char *str)
1292 {
1293   pCodeOp *pcop;
1294
1295
1296   if(!str) {
1297     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1298     exit (1);
1299   }
1300
1301   pcop = pic16_newpCodeOp(str,PO_STR);
1302
1303   return pcop;
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* pic16_popRegFromString -                                        */
1308 /*-----------------------------------------------------------------*/
1309 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1310 {
1311
1312   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1313   pcop->type = PO_DIR;
1314
1315   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1316 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1317
1318   if(!str)
1319     str = "BAD_STRING";
1320
1321   pcop->name = Safe_calloc(1,strlen(str)+1);
1322   strcpy(pcop->name,str);
1323
1324   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1325
1326   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1327   if(PCOR(pcop)->r == NULL) {
1328 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1329 //              __FUNCTION__, __LINE__, str, size, offset);
1330     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1331
1332         //fprintf(stderr, "allocating new register -> %s\n", str);
1333
1334     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1335   } else {
1336     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1337   }
1338   PCOR(pcop)->instance = offset;
1339
1340   return pcop;
1341 }
1342
1343 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1344 {
1345   pCodeOp *pcop;
1346
1347 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1348
1349         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1350         PCOR(pcop)->rIdx = rIdx;
1351         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1352         PCOR(pcop)->r->isFree = 0;
1353         PCOR(pcop)->r->wasUsed = 1;
1354
1355         pcop->type = PCOR(pcop)->r->pc_type;
1356
1357   return pcop;
1358 }
1359
1360 /*---------------------------------------------------------------------------------*/
1361 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1362 /*                 VR 030601                                                       */
1363 /*---------------------------------------------------------------------------------*/
1364 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1365 {
1366   pCodeOpReg2 *pcop2;
1367   pCodeOp *temp;
1368   
1369         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1370
1371         /* comment the following check, so errors to throw up */
1372 //      if(!pcop2)return NULL;
1373
1374         temp = pic16_popGet(aop_dst, offset);
1375         pcop2->pcop2 = temp;
1376         
1377   return PCOP(pcop2);
1378 }
1379
1380 /*---------------------------------------------------------------------------------*/
1381 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1382 /*                     movff instruction                                           */
1383 /*---------------------------------------------------------------------------------*/
1384 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1385 {
1386   pCodeOpReg2 *pcop2;
1387
1388         if(!noalloc) {
1389                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1390                 pcop2->pcop2 = pic16_popCopyReg(dst);
1391         } else {
1392                 /* the pCodeOp may be already allocated */
1393                 pcop2 = (pCodeOpReg2 *)(src);
1394                 pcop2->pcop2 = (pCodeOp *)(dst);
1395         }
1396
1397   return PCOP(pcop2);
1398 }
1399
1400
1401 /*-----------------------------------------------------------------*/
1402 /* pic16_popGet - asm operator to pcode operator conversion              */
1403 /*-----------------------------------------------------------------*/
1404 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1405 {
1406   //char *s = buffer ;
1407     //char *rs;
1408
1409     pCodeOp *pcop;
1410
1411     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1412     /* offset is greater than
1413     size then zero */
1414
1415     if (offset > (aop->size - 1) &&
1416         aop->type != AOP_LIT)
1417       return NULL;  //zero;
1418
1419     /* depending on type */
1420     switch (aop->type) {
1421         
1422     case AOP_R0:
1423     case AOP_R1:
1424     case AOP_DPTR:
1425     case AOP_DPTR2:
1426     case AOP_ACC:
1427         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1428         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1429         return NULL;
1430         
1431     case AOP_IMMD:
1432       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1433       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1434
1435     case AOP_DIR:
1436       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1437       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1438         
1439     case AOP_REG:
1440       {
1441         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1442
1443         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1444         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1445         PCOR(pcop)->rIdx = rIdx;
1446         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1447         PCOR(pcop)->r->wasUsed=1;
1448         PCOR(pcop)->r->isFree=0;
1449
1450         PCOR(pcop)->instance = offset;
1451         pcop->type = PCOR(pcop)->r->pc_type;
1452         //rs = aop->aopu.aop_reg[offset]->name;
1453         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1454         return pcop;
1455       }
1456
1457     case AOP_CRY:
1458         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1459
1460       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1461       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1462       //if(PCOR(pcop)->r == NULL)
1463       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1464       return pcop;
1465         
1466     case AOP_LIT:
1467         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1468       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1469
1470     case AOP_STR:
1471       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1472       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1473
1474       /*
1475       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1476       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1477       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1478       pcop->type = PCOR(pcop)->r->pc_type;
1479       pcop->name = PCOR(pcop)->r->name;
1480
1481       return pcop;
1482       */
1483
1484     case AOP_PCODE:
1485       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1486                           __LINE__, 
1487                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1488       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1489       PCOI(pcop)->offset = offset;
1490       return pcop;
1491     }
1492
1493     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1494            "pic16_popGet got unsupported aop->type");
1495     exit(0);
1496 }
1497 /*-----------------------------------------------------------------*/
1498 /* pic16_aopPut - puts a string for a aop                                */
1499 /*-----------------------------------------------------------------*/
1500 void pic16_aopPut (asmop *aop, char *s, int offset)
1501 {
1502     char *d = buffer ;
1503     symbol *lbl ;
1504
1505     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1506
1507     if (aop->size && offset > ( aop->size - 1)) {
1508         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1509                "pic16_aopPut got offset > aop->size");
1510         exit(0);
1511     }
1512
1513     /* will assign value to value */
1514     /* depending on where it is ofcourse */
1515     switch (aop->type) {
1516     case AOP_DIR:
1517       if (offset) {
1518         sprintf(d,"(%s + %d)",
1519                 aop->aopu.aop_dir,offset);
1520         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1521
1522       } else
1523             sprintf(d,"%s",aop->aopu.aop_dir);
1524         
1525         if (strcmp(d,s)) {
1526           DEBUGpic16_emitcode(";","%d",__LINE__);
1527           if(strcmp(s,"W"))
1528             pic16_emitcode("movf","%s,w",s);
1529           pic16_emitcode("movwf","%s",d);
1530
1531           if(strcmp(s,"W")) {
1532             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1533             if(offset >= aop->size) {
1534               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1535               break;
1536             } else
1537               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1538           }
1539
1540           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1541
1542
1543         }
1544         break;
1545         
1546     case AOP_REG:
1547       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1548         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1549           /*
1550             if (*s == '@'           ||
1551                 strcmp(s,"r0") == 0 ||
1552                 strcmp(s,"r1") == 0 ||
1553                 strcmp(s,"r2") == 0 ||
1554                 strcmp(s,"r3") == 0 ||
1555                 strcmp(s,"r4") == 0 ||
1556                 strcmp(s,"r5") == 0 ||
1557                 strcmp(s,"r6") == 0 || 
1558                 strcmp(s,"r7") == 0 )
1559                 pic16_emitcode("mov","%s,%s  ; %d",
1560                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1561             else
1562           */
1563
1564           if(strcmp(s,"W")==0 )
1565             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1566
1567           pic16_emitcode("movwf","%s",
1568                    aop->aopu.aop_reg[offset]->name);
1569
1570           if(strcmp(s,zero)==0) {
1571             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1572
1573           } else if(strcmp(s,"W")==0) {
1574             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1575             pcop->type = PO_GPR_REGISTER;
1576
1577             PCOR(pcop)->rIdx = -1;
1578             PCOR(pcop)->r = NULL;
1579
1580             DEBUGpic16_emitcode(";","%d",__LINE__);
1581             pcop->name = Safe_strdup(s);
1582             pic16_emitpcode(POC_MOVFW,pcop);
1583             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1584           } else if(strcmp(s,one)==0) {
1585             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1586             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1587           } else {
1588             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1589           }
1590         }
1591         break;
1592         
1593     case AOP_DPTR:
1594     case AOP_DPTR2:
1595     
1596     if (aop->type == AOP_DPTR2)
1597     {
1598         genSetDPTR(1);
1599     }
1600     
1601         if (aop->code) {
1602             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1603                    "pic16_aopPut writting to code space");
1604             exit(0);
1605         }
1606         
1607         while (offset > aop->coff) {
1608             aop->coff++;
1609             pic16_emitcode ("inc","dptr");
1610         }
1611         
1612         while (offset < aop->coff) {
1613             aop->coff-- ;
1614             pic16_emitcode("lcall","__decdptr");
1615         }
1616         
1617         aop->coff = offset;
1618         
1619         /* if not in accumulater */
1620         MOVA(s);        
1621         
1622         pic16_emitcode ("movx","@dptr,a");
1623         
1624     if (aop->type == AOP_DPTR2)
1625     {
1626         genSetDPTR(0);
1627     }
1628         break;
1629         
1630     case AOP_R0:
1631     case AOP_R1:
1632         while (offset > aop->coff) {
1633             aop->coff++;
1634             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1635         }
1636         while (offset < aop->coff) {
1637             aop->coff-- ;
1638             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1639         }
1640         aop->coff = offset;
1641         
1642         if (aop->paged) {
1643             MOVA(s);           
1644             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1645             
1646         } else
1647             if (*s == '@') {
1648                 MOVA(s);
1649                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1650             } else
1651                 if (strcmp(s,"r0") == 0 ||
1652                     strcmp(s,"r1") == 0 ||
1653                     strcmp(s,"r2") == 0 ||
1654                     strcmp(s,"r3") == 0 ||
1655                     strcmp(s,"r4") == 0 ||
1656                     strcmp(s,"r5") == 0 ||
1657                     strcmp(s,"r6") == 0 || 
1658                     strcmp(s,"r7") == 0 ) {
1659                     char buffer[10];
1660                     sprintf(buffer,"a%s",s);
1661                     pic16_emitcode("mov","@%s,%s",
1662                              aop->aopu.aop_ptr->name,buffer);
1663                 } else
1664                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1665         
1666         break;
1667         
1668     case AOP_STK:
1669         if (strcmp(s,"a") == 0)
1670             pic16_emitcode("push","acc");
1671         else
1672             pic16_emitcode("push","%s",s);
1673         
1674         break;
1675         
1676     case AOP_CRY:
1677         /* if bit variable */
1678         if (!aop->aopu.aop_dir) {
1679             pic16_emitcode("clr","a");
1680             pic16_emitcode("rlc","a");
1681         } else {
1682             if (s == zero) 
1683                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1684             else
1685                 if (s == one)
1686                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1687                 else
1688                     if (!strcmp(s,"c"))
1689                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1690                     else {
1691                         lbl = newiTempLabel(NULL);
1692                         
1693                         if (strcmp(s,"a")) {
1694                             MOVA(s);
1695                         }
1696                         pic16_emitcode("clr","c");
1697                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1698                         pic16_emitcode("cpl","c");
1699                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1700                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1701                     }
1702         }
1703         break;
1704         
1705     case AOP_STR:
1706         aop->coff = offset;
1707         if (strcmp(aop->aopu.aop_str[offset],s))
1708             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1709         break;
1710         
1711     case AOP_ACC:
1712         aop->coff = offset;
1713         if (!offset && (strcmp(s,"acc") == 0))
1714             break;
1715         
1716         if (strcmp(aop->aopu.aop_str[offset],s))
1717             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1718         break;
1719
1720     default :
1721         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1722                "pic16_aopPut got unsupported aop->type");
1723         exit(0);    
1724     }    
1725
1726 }
1727
1728 /*-----------------------------------------------------------------*/
1729 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1730 /*-----------------------------------------------------------------*/
1731 static void mov2w (asmop *aop, int offset)
1732 {
1733
1734   if(!aop)
1735     return;
1736
1737   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1738
1739   if ( aop->type == AOP_PCODE ||
1740        aop->type == AOP_LIT )
1741     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1742   else
1743     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1744
1745 }
1746
1747
1748 void pic16_pushpCodeOpReg(pCodeOpReg *pcop)
1749 {
1750         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pcop, &pic16_pc_postdec1, 0));
1751 }
1752
1753 void pic16_poppCodeOpReg(pCodeOpReg *pcop)
1754 {
1755         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, pcop, 0));
1756 }
1757
1758
1759 /*-----------------------------------------------------------------*/
1760 /* pushw - pushes wreg to stack                                    */
1761 /*-----------------------------------------------------------------*/
1762 void pushw(void)
1763 {
1764         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1765         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1766 }
1767
1768                 
1769 /*-----------------------------------------------------------------*/
1770 /* pushaop - pushes aop to stack                                   */
1771 /*-----------------------------------------------------------------*/
1772 void pushaop(asmop *aop, int offset)
1773 {
1774         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1775         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1776 }
1777
1778 /*-----------------------------------------------------------------*/
1779 /* popaop - pops aop from stack                                    */
1780 /*-----------------------------------------------------------------*/
1781 void popaop(asmop *aop, int offset)
1782 {
1783         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1784         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1785 }
1786
1787 void popaopidx(asmop *aop, int offset, int index)
1788 {
1789   int ofs=1;
1790
1791         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1792
1793         if(STACK_MODEL_LARGE)ofs++;
1794
1795         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1796         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1797 }
1798
1799 /*-----------------------------------------------------------------*/
1800 /* reAdjustPreg - points a register back to where it should        */
1801 /*-----------------------------------------------------------------*/
1802 static void reAdjustPreg (asmop *aop)
1803 {
1804     int size ;
1805
1806     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1807     aop->coff = 0;
1808     if ((size = aop->size) <= 1)
1809         return ;
1810     size-- ;
1811     switch (aop->type) {
1812         case AOP_R0 :
1813         case AOP_R1 :
1814             while (size--)
1815                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1816             break;          
1817         case AOP_DPTR :
1818         case AOP_DPTR2:
1819             if (aop->type == AOP_DPTR2)
1820             {
1821                 genSetDPTR(1);
1822             } 
1823             while (size--)
1824             {
1825                 pic16_emitcode("lcall","__decdptr");
1826             }
1827                 
1828             if (aop->type == AOP_DPTR2)
1829             {
1830                 genSetDPTR(0);
1831             }                
1832             break;  
1833
1834     }   
1835
1836 }
1837
1838
1839 #if 0
1840 /*-----------------------------------------------------------------*/
1841 /* opIsGptr: returns non-zero if the passed operand is             */   
1842 /* a generic pointer type.                                         */
1843 /*-----------------------------------------------------------------*/ 
1844 static int opIsGptr(operand *op)
1845 {
1846     sym_link *type = operandType(op);
1847     
1848     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1849     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1850     {
1851         return 1;
1852     }
1853     return 0;        
1854 }
1855 #endif
1856
1857 /*-----------------------------------------------------------------*/
1858 /* pic16_getDataSize - get the operand data size                         */
1859 /*-----------------------------------------------------------------*/
1860 int pic16_getDataSize(operand *op)
1861 {
1862     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1863
1864
1865     return AOP_SIZE(op);
1866
1867     // tsd- in the pic port, the genptr size is 1, so this code here
1868     // fails. ( in the 8051 port, the size was 4).
1869 #if 0
1870     int size;
1871     size = AOP_SIZE(op);
1872     if (size == GPTRSIZE)
1873     {
1874         sym_link *type = operandType(op);
1875         if (IS_GENPTR(type))
1876         {
1877             /* generic pointer; arithmetic operations
1878              * should ignore the high byte (pointer type).
1879              */
1880             size--;
1881     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1882         }
1883     }
1884     return size;
1885 #endif
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* pic16_outAcc - output Acc                                             */
1890 /*-----------------------------------------------------------------*/
1891 void pic16_outAcc(operand *result)
1892 {
1893   int size,offset;
1894   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1895   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1896
1897
1898   size = pic16_getDataSize(result);
1899   if(size){
1900     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1901     size--;
1902     offset = 1;
1903     /* unsigned or positive */
1904     while(size--)
1905       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1906   }
1907
1908 }
1909
1910 /*-----------------------------------------------------------------*/
1911 /* pic16_outBitC - output a bit C                                        */
1912 /*-----------------------------------------------------------------*/
1913 void pic16_outBitC(operand *result)
1914 {
1915
1916     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1917     /* if the result is bit */
1918     if (AOP_TYPE(result) == AOP_CRY) 
1919         pic16_aopPut(AOP(result),"c",0);
1920     else {
1921         pic16_emitcode("clr","a  ; %d", __LINE__);
1922         pic16_emitcode("rlc","a");
1923         pic16_outAcc(result);
1924     }
1925 }
1926
1927 /*-----------------------------------------------------------------*/
1928 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1929 /*-----------------------------------------------------------------*/
1930 void pic16_toBoolean(operand *oper)
1931 {
1932     int size = AOP_SIZE(oper) - 1;
1933     int offset = 1;
1934
1935     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1936
1937     if ( AOP_TYPE(oper) != AOP_ACC) {
1938       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1939     }
1940     while (size--) {
1941       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1942     }
1943 }
1944
1945
1946 #if !defined(GEN_Not)
1947 /*-----------------------------------------------------------------*/
1948 /* genNot - generate code for ! operation                          */
1949 /*-----------------------------------------------------------------*/
1950 static void pic16_genNot (iCode *ic)
1951 {
1952   symbol *tlbl;
1953   int size;
1954
1955   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1956   /* assign asmOps to operand & result */
1957   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1958   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1959
1960   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1961   /* if in bit space then a special case */
1962   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1963     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1964       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1965       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1966     } else {
1967       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1968       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1969       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1970     }
1971     goto release;
1972   }
1973
1974   size = AOP_SIZE(IC_LEFT(ic));
1975   if(size == 1) {
1976     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1977     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1978     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1979     goto release;
1980   }
1981   pic16_toBoolean(IC_LEFT(ic));
1982
1983   tlbl = newiTempLabel(NULL);
1984   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1985   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1986   pic16_outBitC(IC_RESULT(ic));
1987
1988  release:    
1989   /* release the aops */
1990   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1991   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1992 }
1993 #endif
1994
1995
1996 #if !defined(GEN_Cpl)
1997 /*-----------------------------------------------------------------*/
1998 /* genCpl - generate code for complement                           */
1999 /*-----------------------------------------------------------------*/
2000 static void pic16_genCpl (iCode *ic)
2001 {
2002     int offset = 0;
2003     int size ;
2004
2005
2006     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2007     /* assign asmOps to operand & result */
2008     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2009     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2010
2011     /* if both are in bit space then 
2012     a special case */
2013     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2014         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2015
2016         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2017         pic16_emitcode("cpl","c"); 
2018         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2019         goto release; 
2020     } 
2021
2022     size = AOP_SIZE(IC_RESULT(ic));
2023     while (size--) {
2024 /*
2025         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2026         MOVA(l);       
2027         pic16_emitcode("cpl","a");
2028         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2029 */
2030         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2031               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2032         } else {
2033                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2034                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2035         }
2036         offset++;
2037
2038     }
2039
2040
2041 release:
2042     /* release the aops */
2043     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2044     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2045 }
2046 #endif
2047
2048 /*-----------------------------------------------------------------*/
2049 /* genUminusFloat - unary minus for floating points                */
2050 /*-----------------------------------------------------------------*/
2051 static void genUminusFloat(operand *op,operand *result)
2052 {
2053     int size ,offset =0 ;
2054     char *l;
2055
2056     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2057     /* for this we just need to flip the 
2058     first it then copy the rest in place */
2059     size = AOP_SIZE(op) - 1;
2060     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2061
2062     MOVA(l);    
2063
2064     pic16_emitcode("cpl","acc.7");
2065     pic16_aopPut(AOP(result),"a",3);    
2066
2067     while(size--) {
2068         pic16_aopPut(AOP(result),
2069                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2070                offset);
2071         offset++;
2072     }          
2073 }
2074
2075 /*-----------------------------------------------------------------*/
2076 /* genUminus - unary minus code generation                         */
2077 /*-----------------------------------------------------------------*/
2078 static void genUminus (iCode *ic)
2079 {
2080   int size, i;
2081   sym_link *optype, *rtype;
2082
2083
2084   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2085   /* assign asmops */
2086   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2087   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2088
2089   /* if both in bit space then special
2090      case */
2091   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2092       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2093
2094     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2095     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2096     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2097
2098     goto release; 
2099   } 
2100
2101   optype = operandType(IC_LEFT(ic));
2102   rtype = operandType(IC_RESULT(ic));
2103
2104   /* if float then do float stuff */
2105   if (IS_FLOAT(optype)) {
2106     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2107     goto release;
2108   }
2109
2110   /* otherwise subtract from zero by taking the 2's complement */
2111   size = AOP_SIZE(IC_LEFT(ic));
2112
2113   for(i=0; i<size; i++) {
2114     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2115       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2116     else {
2117       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2118       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2119     }
2120   }
2121
2122   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2123   for(i=1; i<size; i++) {
2124     emitSKPNZ;
2125     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2126   }
2127
2128  release:
2129   /* release the aops */
2130   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2131   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2132 }
2133
2134 /*-----------------------------------------------------------------*/
2135 /* saveRegisters - will look for a call and save the registers     */
2136 /*-----------------------------------------------------------------*/
2137 static void saveRegisters(iCode *lic) 
2138 {
2139     int i;
2140     iCode *ic;
2141     bitVect *rsave;
2142     sym_link *dtype;
2143
2144     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2145     /* look for call */
2146     for (ic = lic ; ic ; ic = ic->next) 
2147         if (ic->op == CALL || ic->op == PCALL)
2148             break;
2149
2150     if (!ic) {
2151         fprintf(stderr,"found parameter push with no function call\n");
2152         return ;
2153     }
2154
2155     /* if the registers have been saved already then
2156     do nothing */
2157     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2158         return ;
2159
2160     /* find the registers in use at this time 
2161     and push them away to safety */
2162     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2163                           ic->rUsed);
2164
2165     ic->regsSaved = 1;
2166     if (options.useXstack) {
2167         if (bitVectBitValue(rsave,R0_IDX))
2168             pic16_emitcode("mov","b,r0");
2169         pic16_emitcode("mov","r0,%s",spname);
2170         for (i = 0 ; i < pic16_nRegs ; i++) {
2171             if (bitVectBitValue(rsave,i)) {
2172                 if (i == R0_IDX)
2173                     pic16_emitcode("mov","a,b");
2174                 else
2175                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2176                 pic16_emitcode("movx","@r0,a");
2177                 pic16_emitcode("inc","r0");
2178             }
2179         }
2180         pic16_emitcode("mov","%s,r0",spname);
2181         if (bitVectBitValue(rsave,R0_IDX))
2182             pic16_emitcode("mov","r0,b");           
2183     }// else
2184     //for (i = 0 ; i < pic16_nRegs ; i++) {
2185     //    if (bitVectBitValue(rsave,i))
2186     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2187     //}
2188
2189     dtype = operandType(IC_LEFT(ic));
2190     if (currFunc && dtype && 
2191         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2192         IFFUNC_ISISR(currFunc->type) &&
2193         !ic->bankSaved) 
2194
2195         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2196
2197 }
2198 /*-----------------------------------------------------------------*/
2199 /* unsaveRegisters - pop the pushed registers                      */
2200 /*-----------------------------------------------------------------*/
2201 static void unsaveRegisters (iCode *ic)
2202 {
2203     int i;
2204     bitVect *rsave;
2205
2206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2207     /* find the registers in use at this time 
2208     and push them away to safety */
2209     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2210                           ic->rUsed);
2211     
2212     if (options.useXstack) {
2213         pic16_emitcode("mov","r0,%s",spname);   
2214         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2215             if (bitVectBitValue(rsave,i)) {
2216                 pic16_emitcode("dec","r0");
2217                 pic16_emitcode("movx","a,@r0");
2218                 if (i == R0_IDX)
2219                     pic16_emitcode("mov","b,a");
2220                 else
2221                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2222             }       
2223
2224         }
2225         pic16_emitcode("mov","%s,r0",spname);
2226         if (bitVectBitValue(rsave,R0_IDX))
2227             pic16_emitcode("mov","r0,b");
2228     } //else
2229     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2230     //    if (bitVectBitValue(rsave,i))
2231     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2232     //}
2233
2234 }  
2235
2236
2237 /*-----------------------------------------------------------------*/
2238 /* pushSide -                                                      */
2239 /*-----------------------------------------------------------------*/
2240 static void pushSide(operand * oper, int size)
2241 {
2242 #if 0
2243         int offset = 0;
2244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2245         while (size--) {
2246                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2247                 if (AOP_TYPE(oper) != AOP_REG &&
2248                     AOP_TYPE(oper) != AOP_DIR &&
2249                     strcmp(l,"a") ) {
2250                         pic16_emitcode("mov","a,%s",l);
2251                         pic16_emitcode("push","acc");
2252                 } else
2253                         pic16_emitcode("push","%s",l);
2254         }
2255 #endif
2256 }
2257
2258 /*-----------------------------------------------------------------*/
2259 /* assignResultValue -                                             */
2260 /*-----------------------------------------------------------------*/
2261 static void assignResultValue(operand * oper)
2262 {
2263   int size = AOP_SIZE(oper);
2264
2265         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2266         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2267
2268         if(!GpsuedoStkPtr) {
2269 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2270                 /* The last byte in the assignment is in W */
2271                 size--;
2272                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2273                 GpsuedoStkPtr++;
2274         }
2275
2276         while (size--) {
2277 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2278 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2279                 
2280 #if STACK_SUPPORT
2281                 if(USE_STACK) {
2282                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2283                 } else {
2284                         pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2285                 }
2286 #else
2287                 pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2288 #endif  /* STACK_SUPPORT */
2289                 GpsuedoStkPtr++;
2290
2291 #if STACK_SUPPORT
2292                 if(!USE_STACK)
2293                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2294 #else
2295                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2296 #endif
2297
2298         }
2299                 
2300 }
2301
2302
2303 /*-----------------------------------------------------------------*/
2304 /* genIpush - genrate code for pushing this gets a little complex  */
2305 /*-----------------------------------------------------------------*/
2306 static void genIpush (iCode *ic)
2307 {
2308
2309   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2310 #if 0
2311     int size, offset = 0 ;
2312     char *l;
2313
2314
2315     /* if this is not a parm push : ie. it is spill push 
2316     and spill push is always done on the local stack */
2317     if (!ic->parmPush) {
2318
2319         /* and the item is spilt then do nothing */
2320         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2321             return ;
2322
2323         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2324         size = AOP_SIZE(IC_LEFT(ic));
2325         /* push it on the stack */
2326         while(size--) {
2327             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2328             if (*l == '#') {
2329                 MOVA(l);
2330                 l = "acc";
2331             }
2332             pic16_emitcode("push","%s",l);
2333         }
2334         return ;        
2335     }
2336
2337     /* this is a paramter push: in this case we call
2338     the routine to find the call and save those
2339     registers that need to be saved */   
2340     saveRegisters(ic);
2341
2342     /* then do the push */
2343     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2344
2345
2346         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2347     size = AOP_SIZE(IC_LEFT(ic));
2348
2349     while (size--) {
2350         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2351         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2352             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2353             strcmp(l,"a") ) {
2354             pic16_emitcode("mov","a,%s",l);
2355             pic16_emitcode("push","acc");
2356         } else
2357             pic16_emitcode("push","%s",l);
2358     }       
2359
2360     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2361 #endif
2362 }
2363
2364 /*-----------------------------------------------------------------*/
2365 /* genIpop - recover the registers: can happen only for spilling   */
2366 /*-----------------------------------------------------------------*/
2367 static void genIpop (iCode *ic)
2368 {
2369   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2370 #if 0
2371     int size,offset ;
2372
2373
2374     /* if the temp was not pushed then */
2375     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2376         return ;
2377
2378     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2379     size = AOP_SIZE(IC_LEFT(ic));
2380     offset = (size-1);
2381     while (size--) 
2382         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2383                                    FALSE,TRUE));
2384
2385     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2386 #endif
2387 }
2388
2389 /*-----------------------------------------------------------------*/
2390 /* unsaverbank - restores the resgister bank from stack            */
2391 /*-----------------------------------------------------------------*/
2392 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2393 {
2394   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2395 #if 0
2396     int i;
2397     asmop *aop ;
2398     regs *r = NULL;
2399
2400     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2401     if (popPsw) {
2402         if (options.useXstack) {
2403             aop = newAsmop(0);
2404             r = getFreePtr(ic,&aop,FALSE);
2405             
2406             
2407             pic16_emitcode("mov","%s,_spx",r->name);
2408             pic16_emitcode("movx","a,@%s",r->name);
2409             pic16_emitcode("mov","psw,a");
2410             pic16_emitcode("dec","%s",r->name);
2411             
2412         }else
2413             pic16_emitcode ("pop","psw");
2414     }
2415
2416     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2417         if (options.useXstack) {       
2418             pic16_emitcode("movx","a,@%s",r->name);
2419             //pic16_emitcode("mov","(%s+%d),a",
2420             //       regspic16[i].base,8*bank+regspic16[i].offset);
2421             pic16_emitcode("dec","%s",r->name);
2422
2423         } else 
2424           pic16_emitcode("pop",""); //"(%s+%d)",
2425         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2426     }
2427
2428     if (options.useXstack) {
2429
2430         pic16_emitcode("mov","_spx,%s",r->name);
2431         pic16_freeAsmop(NULL,aop,ic,TRUE);
2432
2433     }
2434 #endif 
2435 }
2436
2437 /*-----------------------------------------------------------------*/
2438 /* saverbank - saves an entire register bank on the stack          */
2439 /*-----------------------------------------------------------------*/
2440 static void saverbank (int bank, iCode *ic, bool pushPsw)
2441 {
2442   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2443 #if 0
2444     int i;
2445     asmop *aop ;
2446     regs *r = NULL;
2447
2448     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2449     if (options.useXstack) {
2450
2451         aop = newAsmop(0);
2452         r = getFreePtr(ic,&aop,FALSE);  
2453         pic16_emitcode("mov","%s,_spx",r->name);
2454
2455     }
2456
2457     for (i = 0 ; i < pic16_nRegs ;i++) {
2458         if (options.useXstack) {
2459             pic16_emitcode("inc","%s",r->name);
2460             //pic16_emitcode("mov","a,(%s+%d)",
2461             //         regspic16[i].base,8*bank+regspic16[i].offset);
2462             pic16_emitcode("movx","@%s,a",r->name);           
2463         } else 
2464           pic16_emitcode("push","");// "(%s+%d)",
2465                      //regspic16[i].base,8*bank+regspic16[i].offset);
2466     }
2467     
2468     if (pushPsw) {
2469         if (options.useXstack) {
2470             pic16_emitcode("mov","a,psw");
2471             pic16_emitcode("movx","@%s,a",r->name);     
2472             pic16_emitcode("inc","%s",r->name);
2473             pic16_emitcode("mov","_spx,%s",r->name);       
2474             pic16_freeAsmop (NULL,aop,ic,TRUE);
2475             
2476         } else
2477             pic16_emitcode("push","psw");
2478         
2479         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2480     }
2481     ic->bankSaved = 1;
2482 #endif
2483 }
2484
2485
2486
2487 /*-----------------------------------------------------------------*/
2488 /* genCall - generates a call statement                            */
2489 /*-----------------------------------------------------------------*/
2490 static void genCall (iCode *ic)
2491 {
2492   sym_link *dtype;   
2493   int stackParms=0;
2494   
2495         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2496
2497         /* if caller saves & we have not saved then */
2498         if (!ic->regsSaved)
2499                 saveRegisters(ic);
2500
2501         /* if we are calling a function that is not using
2502          * the same register bank then we need to save the
2503          * destination registers on the stack */
2504         dtype = operandType(IC_LEFT(ic));
2505         if (currFunc && dtype && 
2506                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2507                 IFFUNC_ISISR(currFunc->type) &&
2508                 !ic->bankSaved) 
2509
2510                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2511
2512         /* if send set is not empty the assign */
2513         if (_G.sendSet) {
2514           iCode *sic;
2515
2516                 /* For the Pic port, there is no data stack.
2517                  * So parameters passed to functions are stored
2518                  * in registers. (The pCode optimizer will get
2519                  * rid of most of these :). */
2520
2521           int psuedoStkPtr=-1; 
2522           int firstTimeThruLoop = 1;
2523
2524                 _G.sendSet = reverseSet(_G.sendSet);
2525
2526                 /* First figure how many parameters are getting passed */
2527                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2528                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2529                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2530                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2531                 }
2532
2533                 stackParms = psuedoStkPtr;
2534
2535                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2536                   int size, offset = 0;
2537
2538                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2539                         size = AOP_SIZE(IC_LEFT(sic));
2540
2541                         while (size--) {
2542                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2543                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2544                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2545
2546                                 if(!firstTimeThruLoop) {
2547                                         /* If this is not the first time we've been through the loop
2548                                          * then we need to save the parameter in a temporary
2549                                          * register. The last byte of the last parameter is
2550                                          * passed in W. */
2551
2552 #if STACK_SUPPORT
2553                                         if(USE_STACK) {
2554                                                 pushw();
2555                                                 --psuedoStkPtr;         // sanity check
2556                                         } else {
2557                                                 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2558                                         }
2559 #else
2560                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2561 #endif  /* STACK_SUPPORT */
2562                                 }
2563                         
2564                                 firstTimeThruLoop=0;
2565
2566                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2567                                 offset++;
2568                         }
2569                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2570                 }
2571                 _G.sendSet = NULL;
2572         }
2573
2574         /* make the call */
2575         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2576                         OP_SYMBOL(IC_LEFT(ic))->rname :
2577                         OP_SYMBOL(IC_LEFT(ic))->name));
2578
2579         GpsuedoStkPtr=0;
2580         /* if we need assign a result value */
2581         if ((IS_ITEMP(IC_RESULT(ic)) && 
2582                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2583                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2584                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2585
2586                 _G.accInUse++;
2587                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2588                 _G.accInUse--;
2589
2590                 assignResultValue(IC_RESULT(ic));
2591
2592                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2593                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2594                 
2595                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2596         }
2597
2598 #if STACK_SUPPORT
2599         if(USE_STACK && stackParms>0) {
2600                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2601                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2602                 if(STACK_MODEL_LARGE) {
2603                         emitSKPNC;
2604                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2605                 }
2606         }
2607 #endif
2608
2609         /* adjust the stack for parameters if required */
2610 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2611
2612         if (ic->parmBytes) {
2613           int i;
2614
2615                 if (ic->parmBytes > 3) {
2616                         pic16_emitcode("mov","a,%s",spname);
2617                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2618                         pic16_emitcode("mov","%s,a",spname);
2619                 } else 
2620                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2621                                 pic16_emitcode("dec","%s",spname);
2622         }
2623
2624         /* if register bank was saved then pop them */
2625         if (ic->bankSaved)
2626                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2627
2628         /* if we hade saved some registers then unsave them */
2629         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2630                 unsaveRegisters (ic);
2631 }
2632
2633 /*-----------------------------------------------------------------*/
2634 /* genPcall - generates a call by pointer statement                */
2635 /*-----------------------------------------------------------------*/
2636 static void genPcall (iCode *ic)
2637 {
2638     sym_link *dtype;
2639     symbol *rlbl = newiTempLabel(NULL);
2640
2641
2642     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2643     /* if caller saves & we have not saved then */
2644     if (!ic->regsSaved)
2645         saveRegisters(ic);
2646
2647     /* if we are calling a function that is not using
2648     the same register bank then we need to save the
2649     destination registers on the stack */
2650     dtype = operandType(IC_LEFT(ic));
2651     if (currFunc && dtype && 
2652         IFFUNC_ISISR(currFunc->type) &&
2653         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2654         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2655
2656
2657     /* push the return address on to the stack */
2658     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2659     pic16_emitcode("push","acc");    
2660     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2661     pic16_emitcode("push","acc");
2662     
2663     if (options.model == MODEL_FLAT24)
2664     {
2665         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2666         pic16_emitcode("push","acc");    
2667     }
2668
2669     /* now push the calling address */
2670     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2671
2672     pushSide(IC_LEFT(ic), FPTRSIZE);
2673
2674     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2675
2676     /* if send set is not empty the assign */
2677     if (_G.sendSet) {
2678         iCode *sic ;
2679
2680         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2681              sic = setNextItem(_G.sendSet)) {
2682             int size, offset = 0;
2683             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2684             size = AOP_SIZE(IC_LEFT(sic));
2685             while (size--) {
2686                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2687                                 FALSE,FALSE);
2688                 if (strcmp(l,fReturn[offset]))
2689                     pic16_emitcode("mov","%s,%s",
2690                              fReturn[offset],
2691                              l);
2692                 offset++;
2693             }
2694             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2695         }
2696         _G.sendSet = NULL;
2697     }
2698
2699     pic16_emitcode("ret","");
2700     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2701
2702
2703     /* if we need assign a result value */
2704     if ((IS_ITEMP(IC_RESULT(ic)) &&
2705          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2706           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2707         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2708
2709         _G.accInUse++;
2710         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2711         _G.accInUse--;
2712         
2713         assignResultValue(IC_RESULT(ic));
2714
2715         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2716     }
2717
2718     /* adjust the stack for parameters if 
2719     required */
2720     if (ic->parmBytes) {
2721         int i;
2722         if (ic->parmBytes > 3) {
2723             pic16_emitcode("mov","a,%s",spname);
2724             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2725             pic16_emitcode("mov","%s,a",spname);
2726         } else 
2727             for ( i = 0 ; i <  ic->parmBytes ;i++)
2728                 pic16_emitcode("dec","%s",spname);
2729
2730     }
2731
2732     /* if register bank was saved then unsave them */
2733     if (currFunc && dtype && 
2734         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2735         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2736
2737     /* if we hade saved some registers then
2738     unsave them */
2739     if (ic->regsSaved)
2740         unsaveRegisters (ic);
2741
2742 }
2743
2744 /*-----------------------------------------------------------------*/
2745 /* resultRemat - result  is rematerializable                       */
2746 /*-----------------------------------------------------------------*/
2747 static int resultRemat (iCode *ic)
2748 {
2749   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2750   if (SKIP_IC(ic) || ic->op == IFX)
2751     return 0;
2752
2753   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2754     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2755     if (sym->remat && !POINTER_SET(ic)) 
2756       return 1;
2757   }
2758
2759   return 0;
2760 }
2761
2762 #if defined(__BORLANDC__) || defined(_MSC_VER)
2763 #define STRCASECMP stricmp
2764 #else
2765 #define STRCASECMP strcasecmp
2766 #endif
2767
2768 #if 0
2769 /*-----------------------------------------------------------------*/
2770 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2771 /*-----------------------------------------------------------------*/
2772 static bool inExcludeList(char *s)
2773 {
2774   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2775     int i =0;
2776     
2777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2778     if (options.excludeRegs[i] &&
2779     STRCASECMP(options.excludeRegs[i],"none") == 0)
2780         return FALSE ;
2781
2782     for ( i = 0 ; options.excludeRegs[i]; i++) {
2783         if (options.excludeRegs[i] &&
2784         STRCASECMP(s,options.excludeRegs[i]) == 0)
2785             return TRUE;
2786     }
2787     return FALSE ;
2788 }
2789 #endif
2790
2791 /*-----------------------------------------------------------------*/
2792 /* genFunction - generated code for function entry                 */
2793 /*-----------------------------------------------------------------*/
2794 static void genFunction (iCode *ic)
2795 {
2796   symbol *sym;
2797   sym_link *ftype;
2798
2799         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2800
2801         labelOffset += (max_key+4);
2802         max_key=0;
2803         GpsuedoStkPtr=0;
2804         _G.nRegsSaved = 0;
2805         /* create the function header */
2806         pic16_emitcode(";","-----------------------------------------");
2807         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2808         pic16_emitcode(";","-----------------------------------------");
2809
2810         pic16_emitcode("","%s:",sym->rname);
2811         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2812
2813         {
2814           absSym *ab;
2815
2816                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
2817                         if(strcmp(ab->name, sym->name)) {
2818                                 pic16_pBlockConvert2Absolute(pb);
2819                                 break;
2820                         }
2821                 
2822         }
2823
2824         ftype = operandType(IC_LEFT(ic));
2825
2826         if(IFFUNC_ISNAKED(ftype)) {
2827                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2828                 return;
2829         }
2830         
2831
2832         /* if critical function then turn interrupts off */
2833         if (IFFUNC_ISCRITICAL(ftype))
2834                 pic16_emitcode("clr","ea");
2835
2836         /* here we need to generate the equates for the
2837          * register bank if required */
2838 #if 0
2839         if (FUNC_REGBANK(ftype) != rbank) {
2840           int i ;
2841
2842                 rbank = FUNC_REGBANK(ftype);
2843                 for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2844                         if (strcmp(regspic16[i].base,"0") == 0)
2845                                 pic16_emitcode("","%s = 0x%02x",
2846                                         regspic16[i].dname,
2847                                         8*rbank+regspic16[i].offset);
2848                         else
2849                                 pic16_emitcode ("","%s = %s + 0x%02x",
2850                                         regspic16[i].dname,
2851                                         regspic16[i].base,
2852                                         *rbank+regspic16[i].offset);
2853                 }
2854         }
2855 #endif
2856
2857         /* if this is an interrupt service routine then
2858          * save acc, b, dpl, dph  */
2859         if (IFFUNC_ISISR(sym->type)) {
2860                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2861                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2862                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2863                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2864
2865                 pic16_pBlockConvert2ISR(pb);
2866 #if 0  
2867                 if (!inExcludeList("acc"))          
2868                         pic16_emitcode ("push","acc");  
2869                 if (!inExcludeList("b"))
2870                         pic16_emitcode ("push","b");
2871                 if (!inExcludeList("dpl"))
2872                         pic16_emitcode ("push","dpl");
2873                 if (!inExcludeList("dph"))
2874                         pic16_emitcode ("push","dph");
2875                 
2876                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx")) {
2877                         pic16_emitcode ("push", "dpx");
2878
2879                         /* Make sure we're using standard DPTR */
2880                         pic16_emitcode ("push", "dps");
2881                         pic16_emitcode ("mov", "dps, #0x00");
2882                         if (options.stack10bit) {       
2883                                 /* This ISR could conceivably use DPTR2. Better save it. */
2884                                 pic16_emitcode ("push", "dpl1");
2885                                 pic16_emitcode ("push", "dph1");
2886                                 pic16_emitcode ("push", "dpx1");
2887                         }
2888                 }
2889
2890                 /* if this isr has no bank i.e. is going to
2891                  * run with bank 0 , then we need to save more
2892                  * registers :-) */
2893                 if (!FUNC_REGBANK(sym->type)) {
2894
2895                         /* if this function does not call any other
2896                          * function then we can be economical and
2897                          * save only those registers that are used */
2898                         if (! IFFUNC_HASFCALL(sym->type)) {
2899                           int i;
2900
2901                                 /* if any registers used */
2902                                 if (sym->regsUsed) {
2903                                         /* save the registers used */
2904                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2905                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2906                                                         (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2907                                                 pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                           
2908                                         }
2909                                 }
2910
2911                         } else {
2912                                 /* this function has  a function call cannot
2913                                  * determines register usage so we will have the
2914                                  * entire bank */
2915                                 saverbank(0,ic,FALSE);
2916                         }           
2917                 }
2918 #endif
2919         } else {
2920 #if STACK_SUPPORT
2921                 /* emit code to setup stack frame if user enabled,
2922                  * and function is not main() */
2923          
2924 //              fprintf(stderr, "function name: %s\n", sym->name);
2925                 if(USE_STACK && strcmp(sym->name, "main")) {
2926                         if(!options.ommitFramePtr || sym->regsUsed) {
2927                         /* setup the stack frame */
2928                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
2929                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
2930                                 if(STACK_MODEL_LARGE)
2931                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
2932                         }
2933                 }
2934 #endif
2935
2936                 /* if callee-save to be used for this function
2937                 * then save the registers being used in this function */
2938                 if (IFFUNC_CALLEESAVES(sym->type)) {
2939                   int i;
2940             
2941 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
2942                         
2943                         /* if any registers used */
2944                         if (sym->regsUsed
2945 #if STACK_SUPPORT
2946                                 && USE_STACK
2947 #endif
2948                                 ) {
2949                                 /* save the registers used */
2950                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
2951                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2952                                         if (bitVectBitValue(sym->regsUsed,i)) {
2953 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
2954 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
2955 //                                                              pic16_regWithIdx(i)->name);
2956
2957                                                 pic16_pushpCodeOpReg( PCOR(pic16_popRegFromIdx(i) ));
2958 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
2959 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
2960 //                                                      &pic16_pc_postdec1, 0));
2961                                                 _G.nRegsSaved++;
2962                                         }
2963                                 }
2964                         }
2965                 }
2966         }
2967
2968
2969         
2970 #if 0
2971         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2972
2973                 if (options.useXstack) {
2974                         pic16_emitcode("mov","r0,%s",spname);
2975                         pic16_emitcode("mov","a,_bp");
2976                         pic16_emitcode("movx","@r0,a");
2977                         pic16_emitcode("inc","%s",spname);
2978                 } else {
2979                         /* set up the stack */
2980                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
2981                 }
2982                 pic16_emitcode ("mov","_bp,%s",spname);
2983         }
2984 #endif
2985         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
2986
2987         /* adjust the stack for the function */
2988         if (sym->stack) {
2989           int i = sym->stack;
2990
2991                 if (i > 127 ) 
2992                         werror(W_STACK_OVERFLOW,sym->name);
2993
2994                 if (i > 3 && sym->recvSize < 4) {              
2995                         pic16_emitcode ("mov","a,sp");
2996                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2997                         pic16_emitcode ("mov","sp,a");
2998                 } else
2999                         while(i--)
3000                                 pic16_emitcode("inc","sp");
3001         }
3002
3003         if (sym->xstack) {
3004                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3005
3006                 pic16_emitcode ("mov","a,_spx");
3007                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3008                 pic16_emitcode ("mov","_spx,a");
3009         }
3010     
3011 }
3012
3013 /*-----------------------------------------------------------------*/
3014 /* genEndFunction - generates epilogue for functions               */
3015 /*-----------------------------------------------------------------*/
3016 static void genEndFunction (iCode *ic)
3017 {
3018     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3019
3020     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3021
3022     if(IFFUNC_ISNAKED(sym->type)) {
3023         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3024         return;
3025     }
3026
3027 #if 0
3028     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3029     {
3030         pic16_emitcode ("mov","%s,_bp",spname);
3031     }
3032 #endif
3033
3034     /* if use external stack but some variables were
3035     added to the local stack then decrement the
3036     local stack */
3037     if (options.useXstack && sym->stack) {      
3038         pic16_emitcode("mov","a,sp");
3039         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3040         pic16_emitcode("mov","sp,a");
3041     }
3042
3043
3044 #if 0
3045     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3046         if (options.useXstack) {
3047             pic16_emitcode("mov","r0,%s",spname);
3048             pic16_emitcode("movx","a,@r0");
3049             pic16_emitcode("mov","_bp,a");
3050             pic16_emitcode("dec","%s",spname);
3051         }
3052         else
3053         {
3054             pic16_emitcode ("pop","_bp");
3055         }
3056     }
3057 #endif
3058
3059     /* restore the register bank  */    
3060     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3061         pic16_emitcode ("pop","psw");
3062
3063     if (IFFUNC_ISISR(sym->type)) {
3064
3065         /* now we need to restore the registers */
3066         /* if this isr has no bank i.e. is going to
3067            run with bank 0 , then we need to save more
3068            registers :-) */
3069         if (!FUNC_REGBANK(sym->type)) {
3070             
3071             /* if this function does not call any other
3072                function then we can be economical and
3073                save only those registers that are used */
3074             if (! IFFUNC_HASFCALL(sym->type)) {
3075                 int i;
3076                 
3077                 /* if any registers used */
3078                 if (sym->regsUsed) {
3079                     /* save the registers used */
3080                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3081                         if (bitVectBitValue(sym->regsUsed,i) ||
3082                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3083                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3084                     }
3085                 }
3086                 
3087             } else {
3088                 /* this function has  a function call cannot
3089                    determines register usage so we will have the
3090                    entire bank */
3091                 unsaverbank(0,ic,FALSE);
3092             }       
3093         }
3094 #if 0
3095         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3096         {
3097             if (options.stack10bit)
3098             {
3099                 pic16_emitcode ("pop", "dpx1");
3100                 pic16_emitcode ("pop", "dph1");
3101                 pic16_emitcode ("pop", "dpl1");
3102             }   
3103             pic16_emitcode ("pop", "dps");
3104             pic16_emitcode ("pop", "dpx");
3105         }
3106         if (!inExcludeList("dph"))
3107             pic16_emitcode ("pop","dph");
3108         if (!inExcludeList("dpl"))
3109             pic16_emitcode ("pop","dpl");
3110         if (!inExcludeList("b"))
3111             pic16_emitcode ("pop","b");
3112         if (!inExcludeList("acc"))
3113             pic16_emitcode ("pop","acc");
3114
3115         if (IFFUNC_ISCRITICAL(sym->type))
3116             pic16_emitcode("setb","ea");
3117 #endif
3118
3119         /* if debug then send end of function */
3120 /*      if (options.debug && currFunc) { */
3121         if (currFunc) {
3122             _G.debugLine = 1;
3123             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3124                      FileBaseName(ic->filename),currFunc->lastLine,
3125                      ic->level,ic->block); 
3126             if (IS_STATIC(currFunc->etype))         
3127                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3128             else
3129                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3130             _G.debugLine = 0;
3131         }
3132         
3133 //      pic16_emitcode ("reti","");
3134
3135         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3136         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3137         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3138         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3139         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3140
3141 #if 0
3142         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3143 #endif
3144
3145         pic16_emitpcodeNULLop(POC_RETFIE);
3146
3147     }
3148     else {
3149         if (IFFUNC_ISCRITICAL(sym->type))
3150             pic16_emitcode("setb","ea");
3151         
3152         /* if any registers used */
3153         if (sym->regsUsed
3154 #if STACK_SUPPORT
3155                 && USE_STACK
3156 #endif
3157         ) {
3158           int i;
3159                 /* save the registers used */
3160                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3161                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3162                         if (bitVectBitValue(sym->regsUsed,i)) {
3163 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3164 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3165 //                                              pic16_regWithIdx(i)->name);
3166         
3167                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3168                                         &pic16_pc_preinc1,
3169                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3170                         }
3171                 }
3172         }
3173         
3174
3175         /* if debug then send end of function */
3176         if (currFunc) {
3177             _G.debugLine = 1;
3178             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3179                      FileBaseName(ic->filename),currFunc->lastLine,
3180                      ic->level,ic->block); 
3181             if (IS_STATIC(currFunc->etype))         
3182                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3183             else
3184                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3185             _G.debugLine = 0;
3186         }
3187
3188 #if STACK_SUPPORT
3189         /* insert code to restore stack frame, if user enabled it
3190          * and function is not main() */
3191          
3192         if(USE_STACK && strcmp(sym->name, "main")) {
3193                 if(!options.ommitFramePtr || sym->regsUsed) {
3194                         /* restore stack frame */
3195                         if(STACK_MODEL_LARGE)
3196                                 pic16_emitpcode(POC_MOVFF,
3197                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h, 0));
3198                         pic16_emitpcode(POC_MOVFF,
3199                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l, 0));
3200                 }
3201         }
3202 #endif
3203
3204         pic16_emitcode ("return","");
3205         pic16_emitpcodeNULLop(POC_RETURN);
3206
3207         /* Mark the end of a function */
3208         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3209     }
3210
3211 }
3212
3213 /*-----------------------------------------------------------------*/
3214 /* genRet - generate code for return statement                     */
3215 /*-----------------------------------------------------------------*/
3216 static void genRet (iCode *ic)
3217 {
3218   int size,offset = 0 , pushed = 0;
3219     
3220   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3221   /* if we have no return value then
3222      just generate the "ret" */
3223   if (!IC_LEFT(ic)) 
3224     goto jumpret;       
3225     
3226   /* we have something to return then
3227      move the return value into place */
3228   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3229   size = AOP_SIZE(IC_LEFT(ic));
3230     
3231   while (size--) {
3232     char *l ;
3233     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3234       /* #NOCHANGE */
3235       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3236                  FALSE,TRUE);
3237       pic16_emitcode("push","%s",l);
3238       pushed++;
3239     } else {
3240         DEBUGpic16_emitcode(";", "%d", __LINE__);
3241       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3242                  FALSE,FALSE);
3243         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3244       if (strcmp(fReturn[offset],l)) {
3245         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3246             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3247           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3248         }else {
3249           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3250         }
3251         if(size) {
3252           pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3253         }
3254         offset++;
3255       }
3256     }
3257   }    
3258
3259   if (pushed) {
3260     while(pushed) {
3261       pushed--;
3262       if (strcmp(fReturn[pushed],"a"))
3263         pic16_emitcode("pop",fReturn[pushed]);
3264       else
3265         pic16_emitcode("pop","acc");
3266     }
3267   }
3268   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3269     
3270  jumpret:
3271   /* generate a jump to the return label
3272      if the next is not the return statement */
3273   if (!(ic->next && ic->next->op == LABEL &&
3274         IC_LABEL(ic->next) == returnLabel)) {
3275         
3276     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3277     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3278   }
3279     
3280 }
3281
3282 /*-----------------------------------------------------------------*/
3283 /* genLabel - generates a label                                    */
3284 /*-----------------------------------------------------------------*/
3285 static void genLabel (iCode *ic)
3286 {
3287     /* special case never generate */
3288     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3289     if (IC_LABEL(ic) == entryLabel)
3290         return ;
3291
3292     pic16_emitpLabel(IC_LABEL(ic)->key);
3293     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3294 }
3295
3296 /*-----------------------------------------------------------------*/
3297 /* genGoto - generates a goto                                      */
3298 /*-----------------------------------------------------------------*/
3299 //tsd
3300 static void genGoto (iCode *ic)
3301 {
3302   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3303   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3304 }
3305
3306
3307 /*-----------------------------------------------------------------*/
3308 /* genMultbits :- multiplication of bits                           */
3309 /*-----------------------------------------------------------------*/
3310 static void genMultbits (operand *left, 
3311                          operand *right, 
3312                          operand *result)
3313 {
3314   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3315
3316   if(!pic16_sameRegs(AOP(result),AOP(right)))
3317     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3318
3319   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3320   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3321   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3322
3323 }
3324
3325
3326 /*-----------------------------------------------------------------*/
3327 /* genMultOneByte : 8 bit multiplication & division                */
3328 /*-----------------------------------------------------------------*/
3329 static void genMultOneByte (operand *left,
3330                             operand *right,
3331                             operand *result)
3332 {
3333   sym_link *opetype = operandType(result);
3334
3335   // symbol *lbl ;
3336   int size,offset;
3337
3338   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3339   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3340   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3341
3342   /* (if two literals, the value is computed before) */
3343   /* if one literal, literal on the right */
3344   if (AOP_TYPE(left) == AOP_LIT){
3345     operand *t = right;
3346     right = left;
3347     left = t;
3348   }
3349
3350   size = AOP_SIZE(result);
3351   if(size == 1) {
3352
3353     if (AOP_TYPE(right) == AOP_LIT){
3354       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3355                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3356                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3357                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3358       pic16_emitcode("call","genMultLit");
3359     } else {
3360       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3361                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3362                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3363                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3364       pic16_emitcode("call","pic16_genMult8X8_8");
3365
3366     }
3367     pic16_genMult8X8_8 (left, right,result);
3368
3369
3370     /* signed or unsigned */
3371     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3372     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3373     //MOVA(l);       
3374     //pic16_emitcode("mul","ab");
3375     /* if result size = 1, mul signed = mul unsigned */
3376     //pic16_aopPut(AOP(result),"a",0);
3377
3378   } else {  // (size > 1)
3379
3380     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3381                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3382                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3383                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3384
3385     if (SPEC_USIGN(opetype)){
3386       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3387       pic16_genUMult8X8_16 (left, right, result, NULL);
3388
3389       if (size > 2) {
3390         /* for filling the MSBs */
3391         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3392         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3393       }
3394     }
3395     else{
3396       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3397
3398       pic16_emitcode("mov","a,b");
3399
3400       /* adjust the MSB if left or right neg */
3401
3402       /* if one literal */
3403       if (AOP_TYPE(right) == AOP_LIT){
3404         pic16_emitcode("multiply ","right is a lit");
3405         /* AND literal negative */
3406         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3407           /* adjust MSB (c==0 after mul) */
3408           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3409         }
3410       }
3411       else{
3412         pic16_genSMult8X8_16 (left, right, result, NULL);
3413       }
3414
3415       if(size > 2){
3416         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3417         /* get the sign */
3418         pic16_emitcode("rlc","a");
3419         pic16_emitcode("subb","a,acc");
3420       }
3421     }
3422
3423     size -= 2;   
3424     offset = 2;
3425     if (size > 0)
3426       while (size--)
3427         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3428     //pic16_aopPut(AOP(result),"a",offset++);
3429   }
3430 }
3431
3432 /*-----------------------------------------------------------------*/
3433 /* genMult - generates code for multiplication                     */
3434 /*-----------------------------------------------------------------*/
3435 static void genMult (iCode *ic)
3436 {
3437     operand *left = IC_LEFT(ic);
3438     operand *right = IC_RIGHT(ic);
3439     operand *result= IC_RESULT(ic);   
3440
3441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3442     /* assign the amsops */
3443     pic16_aopOp (left,ic,FALSE);
3444     pic16_aopOp (right,ic,FALSE);
3445     pic16_aopOp (result,ic,TRUE);
3446
3447   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3448
3449     /* special cases first */
3450     /* both are bits */
3451     if (AOP_TYPE(left) == AOP_CRY &&
3452         AOP_TYPE(right)== AOP_CRY) {
3453         genMultbits(left,right,result);
3454         goto release ;
3455     }
3456
3457     /* if both are of size == 1 */
3458     if (AOP_SIZE(left) == 1 &&
3459         AOP_SIZE(right) == 1 ) {
3460         genMultOneByte(left,right,result);
3461         goto release ;
3462     }
3463
3464     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3465
3466     /* should have been converted to function call */
3467     //assert(0) ;
3468
3469 release :
3470     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3471     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3472     pic16_freeAsmop(result,NULL,ic,TRUE); 
3473 }
3474
3475 /*-----------------------------------------------------------------*/
3476 /* genDivbits :- division of bits                                  */
3477 /*-----------------------------------------------------------------*/
3478 static void genDivbits (operand *left, 
3479                         operand *right, 
3480                         operand *result)
3481 {
3482
3483     char *l;
3484
3485     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3486     /* the result must be bit */    
3487     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3488     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3489
3490     MOVA(l);    
3491
3492     pic16_emitcode("div","ab");
3493     pic16_emitcode("rrc","a");
3494     pic16_aopPut(AOP(result),"c",0);
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* genDivOneByte : 8 bit division                                  */
3499 /*-----------------------------------------------------------------*/
3500 static void genDivOneByte (operand *left,
3501                            operand *right,
3502                            operand *result)
3503 {
3504     sym_link *opetype = operandType(result);
3505     char *l ;
3506     symbol *lbl ;
3507     int size,offset;
3508
3509     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3510     size = AOP_SIZE(result) - 1;
3511     offset = 1;
3512     /* signed or unsigned */
3513     if (SPEC_USIGN(opetype)) {
3514         /* unsigned is easy */
3515         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3516         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3517         MOVA(l);        
3518         pic16_emitcode("div","ab");
3519         pic16_aopPut(AOP(result),"a",0);
3520         while (size--)
3521             pic16_aopPut(AOP(result),zero,offset++);
3522         return ;
3523     }
3524
3525     /* signed is a little bit more difficult */
3526
3527     /* save the signs of the operands */
3528     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3529     MOVA(l);    
3530     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3531     pic16_emitcode("push","acc"); /* save it on the stack */
3532
3533     /* now sign adjust for both left & right */
3534     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3535     MOVA(l);       
3536     lbl = newiTempLabel(NULL);
3537     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3538     pic16_emitcode("cpl","a");   
3539     pic16_emitcode("inc","a");
3540     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3541     pic16_emitcode("mov","b,a");
3542
3543     /* sign adjust left side */
3544     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3545     MOVA(l);
3546
3547     lbl = newiTempLabel(NULL);
3548     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3549     pic16_emitcode("cpl","a");
3550     pic16_emitcode("inc","a");
3551     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3552
3553     /* now the division */
3554     pic16_emitcode("div","ab");
3555     /* we are interested in the lower order
3556     only */
3557     pic16_emitcode("mov","b,a");
3558     lbl = newiTempLabel(NULL);
3559     pic16_emitcode("pop","acc");   
3560     /* if there was an over flow we don't 
3561     adjust the sign of the result */
3562     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3563     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3564     CLRC;
3565     pic16_emitcode("clr","a");
3566     pic16_emitcode("subb","a,b");
3567     pic16_emitcode("mov","b,a");
3568     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3569
3570     /* now we are done */
3571     pic16_aopPut(AOP(result),"b",0);
3572     if(size > 0){
3573         pic16_emitcode("mov","c,b.7");
3574         pic16_emitcode("subb","a,acc");   
3575     }
3576     while (size--)
3577         pic16_aopPut(AOP(result),"a",offset++);
3578
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* genDiv - generates code for division                            */
3583 /*-----------------------------------------------------------------*/
3584 static void genDiv (iCode *ic)
3585 {
3586     operand *left = IC_LEFT(ic);
3587     operand *right = IC_RIGHT(ic);
3588     operand *result= IC_RESULT(ic);   
3589
3590     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3591     /* assign the amsops */
3592     pic16_aopOp (left,ic,FALSE);
3593     pic16_aopOp (right,ic,FALSE);
3594     pic16_aopOp (result,ic,TRUE);
3595
3596     /* special cases first */
3597     /* both are bits */
3598     if (AOP_TYPE(left) == AOP_CRY &&
3599         AOP_TYPE(right)== AOP_CRY) {
3600         genDivbits(left,right,result);
3601         goto release ;
3602     }
3603
3604     /* if both are of size == 1 */
3605     if (AOP_SIZE(left) == 1 &&
3606         AOP_SIZE(right) == 1 ) {
3607         genDivOneByte(left,right,result);
3608         goto release ;
3609     }
3610
3611     /* should have been converted to function call */
3612     assert(0);
3613 release :
3614     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3615     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3616     pic16_freeAsmop(result,NULL,ic,TRUE); 
3617 }
3618
3619 /*-----------------------------------------------------------------*/
3620 /* genModbits :- modulus of bits                                   */
3621 /*-----------------------------------------------------------------*/
3622 static void genModbits (operand *left, 
3623                         operand *right, 
3624                         operand *result)
3625 {
3626
3627     char *l;
3628
3629     /* the result must be bit */    
3630     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3631     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3632
3633     MOVA(l);       
3634
3635     pic16_emitcode("div","ab");
3636     pic16_emitcode("mov","a,b");
3637     pic16_emitcode("rrc","a");
3638     pic16_aopPut(AOP(result),"c",0);
3639 }
3640
3641 /*-----------------------------------------------------------------*/
3642 /* genModOneByte : 8 bit modulus                                   */
3643 /*-----------------------------------------------------------------*/
3644 static void genModOneByte (operand *left,
3645                            operand *right,
3646                            operand *result)
3647 {
3648     sym_link *opetype = operandType(result);
3649     char *l ;
3650     symbol *lbl ;
3651
3652     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3653     /* signed or unsigned */
3654     if (SPEC_USIGN(opetype)) {
3655         /* unsigned is easy */
3656         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3657         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3658         MOVA(l);    
3659         pic16_emitcode("div","ab");
3660         pic16_aopPut(AOP(result),"b",0);
3661         return ;
3662     }
3663
3664     /* signed is a little bit more difficult */
3665
3666     /* save the signs of the operands */
3667     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3668     MOVA(l);
3669
3670     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3671     pic16_emitcode("push","acc"); /* save it on the stack */
3672
3673     /* now sign adjust for both left & right */
3674     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3675     MOVA(l);
3676
3677     lbl = newiTempLabel(NULL);
3678     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3679     pic16_emitcode("cpl","a");   
3680     pic16_emitcode("inc","a");
3681     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3682     pic16_emitcode("mov","b,a"); 
3683
3684     /* sign adjust left side */
3685     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3686     MOVA(l);
3687
3688     lbl = newiTempLabel(NULL);
3689     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3690     pic16_emitcode("cpl","a");   
3691     pic16_emitcode("inc","a");
3692     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3693
3694     /* now the multiplication */
3695     pic16_emitcode("div","ab");
3696     /* we are interested in the lower order
3697     only */
3698     lbl = newiTempLabel(NULL);
3699     pic16_emitcode("pop","acc");   
3700     /* if there was an over flow we don't 
3701     adjust the sign of the result */
3702     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3703     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3704     CLRC ;
3705     pic16_emitcode("clr","a");
3706     pic16_emitcode("subb","a,b");
3707     pic16_emitcode("mov","b,a");
3708     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3709
3710     /* now we are done */
3711     pic16_aopPut(AOP(result),"b",0);
3712
3713 }
3714
3715 /*-----------------------------------------------------------------*/
3716 /* genMod - generates code for division                            */
3717 /*-----------------------------------------------------------------*/
3718 static void genMod (iCode *ic)
3719 {
3720     operand *left = IC_LEFT(ic);
3721     operand *right = IC_RIGHT(ic);
3722     operand *result= IC_RESULT(ic);  
3723
3724     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3725     /* assign the amsops */
3726     pic16_aopOp (left,ic,FALSE);
3727     pic16_aopOp (right,ic,FALSE);
3728     pic16_aopOp (result,ic,TRUE);
3729
3730     /* special cases first */
3731     /* both are bits */
3732     if (AOP_TYPE(left) == AOP_CRY &&
3733         AOP_TYPE(right)== AOP_CRY) {
3734         genModbits(left,right,result);
3735         goto release ;
3736     }
3737
3738     /* if both are of size == 1 */
3739     if (AOP_SIZE(left) == 1 &&
3740         AOP_SIZE(right) == 1 ) {
3741         genModOneByte(left,right,result);
3742         goto release ;
3743     }
3744
3745     /* should have been converted to function call */
3746     assert(0);
3747
3748 release :
3749     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3750     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3751     pic16_freeAsmop(result,NULL,ic,TRUE); 
3752 }
3753
3754 /*-----------------------------------------------------------------*/
3755 /* genIfxJump :- will create a jump depending on the ifx           */
3756 /*-----------------------------------------------------------------*/
3757 /*
3758   note: May need to add parameter to indicate when a variable is in bit space.
3759 */
3760 static void genIfxJump (iCode *ic, char *jval)
3761 {
3762
3763     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3764     /* if true label then we jump if condition
3765     supplied is true */
3766     if ( IC_TRUE(ic) ) {
3767
3768         if(strcmp(jval,"a") == 0)
3769           emitSKPZ;
3770         else if (strcmp(jval,"c") == 0)
3771           emitSKPC;
3772         else {
3773           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3774           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3775         }
3776
3777         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3778         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3779
3780     }
3781     else {
3782         /* false label is present */
3783         if(strcmp(jval,"a") == 0)
3784           emitSKPNZ;
3785         else if (strcmp(jval,"c") == 0)
3786           emitSKPNC;
3787         else {
3788           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3789           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3790         }
3791
3792         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3793         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3794
3795     }
3796
3797
3798     /* mark the icode as generated */
3799     ic->generated = 1;
3800 }
3801
3802 /*-----------------------------------------------------------------*/
3803 /* genSkip                                                         */
3804 /*-----------------------------------------------------------------*/
3805 static void genSkip(iCode *ifx,int status_bit)
3806 {
3807   if(!ifx)
3808     return;
3809
3810   if ( IC_TRUE(ifx) ) {
3811     switch(status_bit) {
3812     case 'z':
3813       emitSKPNZ;
3814       break;
3815
3816     case 'c':
3817       emitSKPNC;
3818       break;
3819
3820     case 'd':
3821       emitSKPDC;
3822       break;
3823
3824     }
3825
3826     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3827     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3828
3829   } else {
3830
3831     switch(status_bit) {
3832
3833     case 'z':
3834       emitSKPZ;
3835       break;
3836
3837     case 'c':
3838       emitSKPC;
3839       break;
3840
3841     case 'd':
3842       emitSKPDC;
3843       break;
3844     }
3845     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3846     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3847
3848   }
3849
3850 }
3851
3852 /*-----------------------------------------------------------------*/
3853 /* genSkipc                                                        */
3854 /*-----------------------------------------------------------------*/
3855 static void genSkipc(resolvedIfx *rifx)
3856 {
3857   if(!rifx)
3858     return;
3859
3860   if(rifx->condition)
3861     emitSKPC;
3862   else
3863     emitSKPNC;
3864
3865   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3866   rifx->generated = 1;
3867 }
3868
3869 /*-----------------------------------------------------------------*/
3870 /* genSkipz2                                                       */
3871 /*-----------------------------------------------------------------*/
3872 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3873 {
3874   if(!rifx)
3875     return;
3876
3877   if( (rifx->condition ^ invert_condition) & 1)
3878     emitSKPZ;
3879   else
3880     emitSKPNZ;
3881
3882   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3883   rifx->generated = 1;
3884 }
3885
3886 /*-----------------------------------------------------------------*/
3887 /* genSkipz                                                        */
3888 /*-----------------------------------------------------------------*/
3889 static void genSkipz(iCode *ifx, int condition)
3890 {
3891   if(!ifx)
3892     return;
3893
3894   if(condition)
3895     emitSKPNZ;
3896   else
3897     emitSKPZ;
3898
3899   if ( IC_TRUE(ifx) )
3900     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3901   else
3902     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3903
3904   if ( IC_TRUE(ifx) )
3905     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3906   else
3907     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3908
3909 }
3910 /*-----------------------------------------------------------------*/
3911 /* genSkipCond                                                     */
3912 /*-----------------------------------------------------------------*/
3913 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3914 {
3915   if(!rifx)
3916     return;
3917
3918   if(rifx->condition)
3919     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3920   else
3921     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3922
3923
3924   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3925   rifx->generated = 1;
3926 }
3927
3928 #if 0
3929 /*-----------------------------------------------------------------*/
3930 /* genChkZeroes :- greater or less than comparison                 */
3931 /*     For each byte in a literal that is zero, inclusive or the   */
3932 /*     the corresponding byte in the operand with W                */
3933 /*     returns true if any of the bytes are zero                   */
3934 /*-----------------------------------------------------------------*/
3935 static int genChkZeroes(operand *op, int lit,  int size)
3936 {
3937
3938   int i;
3939   int flag =1;
3940
3941   while(size--) {
3942     i = (lit >> (size*8)) & 0xff;
3943
3944     if(i==0) {
3945       if(flag) 
3946         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3947       else
3948         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3949       flag = 0;
3950     }
3951   }
3952
3953   return (flag==0);
3954 }
3955 #endif
3956
3957 /*-----------------------------------------------------------------*/
3958 /* genCmp :- greater or less than comparison                       */
3959 /*-----------------------------------------------------------------*/
3960 static void genCmp (operand *left,operand *right,
3961                     operand *result, iCode *ifx, int sign)
3962 {
3963   int size; //, offset = 0 ;
3964   unsigned long lit = 0L,i = 0;
3965   resolvedIfx rFalseIfx;
3966   //  resolvedIfx rTrueIfx;
3967   symbol *truelbl;
3968   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3969 /*
3970   if(ifx) {
3971     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3972     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3973   }
3974 */
3975
3976   resolveIfx(&rFalseIfx,ifx);
3977   truelbl  = newiTempLabel(NULL);
3978   size = max(AOP_SIZE(left),AOP_SIZE(right));
3979
3980   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3981
3982 #define _swapp
3983
3984   /* if literal is on the right then swap with left */
3985   if ((AOP_TYPE(right) == AOP_LIT)) {
3986     operand *tmp = right ;
3987     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3988     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3989 #ifdef _swapp
3990
3991     lit = (lit - 1) & mask;
3992     right = left;
3993     left = tmp;
3994     rFalseIfx.condition ^= 1;
3995 #endif
3996
3997   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3998     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3999   }
4000
4001
4002   //if(IC_TRUE(ifx) == NULL)
4003   /* if left & right are bit variables */
4004   if (AOP_TYPE(left) == AOP_CRY &&
4005       AOP_TYPE(right) == AOP_CRY ) {
4006     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4007     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4008   } else {
4009     /* subtract right from left if at the
4010        end the carry flag is set then we know that
4011        left is greater than right */
4012
4013     //    {
4014
4015     symbol *lbl  = newiTempLabel(NULL);
4016
4017 #ifndef _swapp
4018     if(AOP_TYPE(right) == AOP_LIT) {
4019
4020       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4021
4022       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4023
4024       /* special cases */
4025
4026       if(lit == 0) {
4027
4028         if(sign != 0) 
4029           genSkipCond(&rFalseIfx,left,size-1,7);
4030         else 
4031           /* no need to compare to 0...*/
4032           /* NOTE: this is a de-generate compare that most certainly 
4033            *       creates some dead code. */
4034           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4035
4036         if(ifx) ifx->generated = 1;
4037         return;
4038
4039       }
4040       size--;
4041
4042       if(size == 0) {
4043         //i = (lit >> (size*8)) & 0xff;
4044         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4045         
4046         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4047
4048         i = ((0-lit) & 0xff);
4049         if(sign) {
4050           if( i == 0x81) { 
4051             /* lit is 0x7f, all signed chars are less than
4052              * this except for 0x7f itself */
4053             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4054             genSkipz2(&rFalseIfx,0);
4055           } else {
4056             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4057             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4058             genSkipc(&rFalseIfx);
4059           }
4060
4061         } else {
4062           if(lit == 1) {
4063             genSkipz2(&rFalseIfx,1);
4064           } else {
4065             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4066             genSkipc(&rFalseIfx);
4067           }
4068         }
4069
4070         if(ifx) ifx->generated = 1;
4071         return;
4072       }
4073
4074       /* chars are out of the way. now do ints and longs */
4075
4076
4077       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4078         
4079       /* special cases */
4080
4081       if(sign) {
4082
4083         if(lit == 0) {
4084           genSkipCond(&rFalseIfx,left,size,7);
4085           if(ifx) ifx->generated = 1;
4086           return;
4087         }
4088
4089         if(lit <0x100) {
4090           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4091
4092           //rFalseIfx.condition ^= 1;
4093           //genSkipCond(&rFalseIfx,left,size,7);
4094           //rFalseIfx.condition ^= 1;
4095
4096           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4097           if(rFalseIfx.condition)
4098             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4099           else
4100             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4101
4102           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4103           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4104           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4105
4106           while(size > 1)
4107             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4108
4109           if(rFalseIfx.condition) {
4110             emitSKPZ;
4111             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4112
4113           } else {
4114             emitSKPNZ;
4115           }
4116
4117           genSkipc(&rFalseIfx);
4118           pic16_emitpLabel(truelbl->key);
4119           if(ifx) ifx->generated = 1;
4120           return;
4121
4122         }
4123
4124         if(size == 1) {
4125
4126           if( (lit & 0xff) == 0) {
4127             /* lower byte is zero */
4128             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4129             i = ((lit >> 8) & 0xff) ^0x80;
4130             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4131             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4132             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4133             genSkipc(&rFalseIfx);
4134
4135
4136             if(ifx) ifx->generated = 1;
4137             return;
4138
4139           }
4140         } else {
4141           /* Special cases for signed longs */
4142           if( (lit & 0xffffff) == 0) {
4143             /* lower byte is zero */
4144             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4145             i = ((lit >> 8*3) & 0xff) ^0x80;
4146             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4147             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4148             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4149             genSkipc(&rFalseIfx);
4150
4151
4152             if(ifx) ifx->generated = 1;
4153             return;
4154
4155           }
4156
4157         }
4158
4159
4160         if(lit & (0x80 << (size*8))) {
4161           /* lit is negative */
4162           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4163
4164           //genSkipCond(&rFalseIfx,left,size,7);
4165
4166           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4167
4168           if(rFalseIfx.condition)
4169             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4170           else
4171             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4172
4173
4174         } else {
4175           /* lit is positive */
4176           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4177           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4178           if(rFalseIfx.condition)
4179             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4180           else
4181             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4182
4183         }
4184
4185         /*
4186           This works, but is only good for ints.
4187           It also requires a "known zero" register.
4188           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4189           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4190           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4191           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4192           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4193           genSkipc(&rFalseIfx);
4194
4195           pic16_emitpLabel(truelbl->key);
4196           if(ifx) ifx->generated = 1;
4197           return;
4198         **/
4199           
4200         /* There are no more special cases, so perform a general compare */
4201   
4202         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4203         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4204
4205         while(size--) {
4206
4207           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4208           emitSKPNZ;
4209           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4210         }
4211         //rFalseIfx.condition ^= 1;
4212         genSkipc(&rFalseIfx);
4213
4214         pic16_emitpLabel(truelbl->key);
4215
4216         if(ifx) ifx->generated = 1;
4217         return;
4218
4219
4220       }
4221
4222
4223       /* sign is out of the way. So now do an unsigned compare */
4224       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4225
4226
4227       /* General case - compare to an unsigned literal on the right.*/
4228
4229       i = (lit >> (size*8)) & 0xff;
4230       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4231       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4232       while(size--) {
4233         i = (lit >> (size*8)) & 0xff;
4234
4235         if(i) {
4236           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4237           emitSKPNZ;
4238           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4239         } else {
4240           /* this byte of the lit is zero, 
4241            *if it's not the last then OR in the variable */
4242           if(size)
4243             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4244         }
4245       }
4246
4247
4248       pic16_emitpLabel(lbl->key);
4249       //if(emitFinalCheck)
4250       genSkipc(&rFalseIfx);
4251       if(sign)
4252         pic16_emitpLabel(truelbl->key);
4253
4254       if(ifx) ifx->generated = 1;
4255       return;
4256
4257
4258     }
4259 #endif  // _swapp
4260
4261     if(AOP_TYPE(left) == AOP_LIT) {
4262       //symbol *lbl = newiTempLabel(NULL);
4263
4264       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4265
4266
4267       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4268
4269       /* Special cases */
4270       if((lit == 0) && (sign == 0)){
4271
4272         size--;
4273         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4274         while(size) 
4275           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4276
4277         genSkipz2(&rFalseIfx,0);
4278         if(ifx) ifx->generated = 1;
4279         return;
4280       }
4281
4282       if(size==1) {
4283         /* Special cases */
4284         lit &= 0xff;
4285         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4286           /* degenerate compare can never be true */
4287           if(rFalseIfx.condition == 0)
4288             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4289
4290           if(ifx) ifx->generated = 1;
4291           return;
4292         }
4293
4294         if(sign) {
4295           /* signed comparisons to a literal byte */
4296
4297           int lp1 = (lit+1) & 0xff;
4298
4299           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4300           switch (lp1) {
4301           case 0:
4302             rFalseIfx.condition ^= 1;
4303             genSkipCond(&rFalseIfx,right,0,7);
4304             break;
4305           case 0x7f:
4306             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4307             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4308             genSkipz2(&rFalseIfx,1);
4309             break;
4310           default:
4311             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4312             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4313             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4314             rFalseIfx.condition ^= 1;
4315             genSkipc(&rFalseIfx);
4316             break;
4317           }
4318         } else {
4319           /* unsigned comparisons to a literal byte */
4320
4321           switch(lit & 0xff ) {
4322           case 0:
4323             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4324             genSkipz2(&rFalseIfx,0);
4325             break;
4326           case 0x7f:
4327             rFalseIfx.condition ^= 1;
4328             genSkipCond(&rFalseIfx,right,0,7);
4329             break;
4330
4331           default:
4332             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4333             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4334             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4335             rFalseIfx.condition ^= 1;
4336             if (AOP_TYPE(result) == AOP_CRY)
4337               genSkipc(&rFalseIfx);
4338             else {
4339               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4340               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4341             }         
4342             break;
4343           }
4344         }
4345
4346         if(ifx) ifx->generated = 1;
4347         //goto check_carry;
4348         return;
4349
4350       } else {
4351
4352         /* Size is greater than 1 */
4353
4354         if(sign) {
4355           int lp1 = lit+1;
4356
4357           size--;
4358
4359           if(lp1 == 0) {
4360             /* this means lit = 0xffffffff, or -1 */
4361
4362
4363             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4364             rFalseIfx.condition ^= 1;
4365             genSkipCond(&rFalseIfx,right,size,7);
4366             if(ifx) ifx->generated = 1;
4367             return;
4368           }
4369
4370           if(lit == 0) {
4371             int s = size;
4372
4373             if(rFalseIfx.condition) {
4374               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4375               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4376             }
4377
4378             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4379             while(size--)
4380               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4381
4382
4383             emitSKPZ;
4384             if(rFalseIfx.condition) {
4385               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4386               pic16_emitpLabel(truelbl->key);
4387             }else {
4388               rFalseIfx.condition ^= 1;
4389               genSkipCond(&rFalseIfx,right,s,7);
4390             }
4391
4392             if(ifx) ifx->generated = 1;
4393             return;
4394           }
4395
4396           if((size == 1) &&  (0 == (lp1&0xff))) {
4397             /* lower byte of signed word is zero */
4398             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4399             i = ((lp1 >> 8) & 0xff) ^0x80;
4400             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4401             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4402             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4403             rFalseIfx.condition ^= 1;
4404             genSkipc(&rFalseIfx);
4405
4406
4407             if(ifx) ifx->generated = 1;
4408             return;
4409           }
4410
4411           if(lit & (0x80 << (size*8))) {
4412             /* Lit is less than zero */
4413             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4414             //rFalseIfx.condition ^= 1;
4415             //genSkipCond(&rFalseIfx,left,size,7);
4416             //rFalseIfx.condition ^= 1;
4417             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4418             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4419
4420             if(rFalseIfx.condition)
4421               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4422             else
4423               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4424
4425
4426           } else {
4427             /* Lit is greater than or equal to zero */
4428             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4429             //rFalseIfx.condition ^= 1;
4430             //genSkipCond(&rFalseIfx,right,size,7);
4431             //rFalseIfx.condition ^= 1;
4432
4433             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4434             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4435
4436             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4437             if(rFalseIfx.condition)
4438               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4439             else
4440               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4441
4442           }
4443
4444
4445           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4446           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4447
4448           while(size--) {
4449
4450             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4451             emitSKPNZ;
4452             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4453           }
4454           rFalseIfx.condition ^= 1;
4455           //rFalseIfx.condition = 1;
4456           genSkipc(&rFalseIfx);
4457
4458           pic16_emitpLabel(truelbl->key);
4459
4460           if(ifx) ifx->generated = 1;
4461           return;
4462           // end of if (sign)
4463         } else {
4464
4465           /* compare word or long to an unsigned literal on the right.*/
4466
4467
4468           size--;
4469           if(lit < 0xff) {
4470             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4471             switch (lit) {
4472             case 0:
4473               break; /* handled above */
4474 /*
4475             case 0xff:
4476               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4477               while(size--)
4478                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4479               genSkipz2(&rFalseIfx,0);
4480               break;
4481 */
4482             default:
4483               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4484               while(--size)
4485                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4486
4487               emitSKPZ;
4488               if(rFalseIfx.condition)
4489                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4490               else
4491                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4492
4493
4494               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4495               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4496
4497               rFalseIfx.condition ^= 1;
4498               genSkipc(&rFalseIfx);
4499             }
4500
4501             pic16_emitpLabel(truelbl->key);
4502
4503             if(ifx) ifx->generated = 1;
4504             return;
4505           }
4506
4507
4508           lit++;
4509           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4510           i = (lit >> (size*8)) & 0xff;
4511
4512           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4513           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4514
4515           while(size--) {
4516             i = (lit >> (size*8)) & 0xff;
4517
4518             if(i) {
4519               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4520               emitSKPNZ;
4521               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4522             } else {
4523               /* this byte of the lit is zero, 
4524                *if it's not the last then OR in the variable */
4525               if(size)
4526                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4527             }
4528           }
4529
4530
4531           pic16_emitpLabel(lbl->key);
4532
4533           rFalseIfx.condition ^= 1;
4534           genSkipc(&rFalseIfx);
4535         }
4536
4537         if(sign)
4538           pic16_emitpLabel(truelbl->key);
4539         if(ifx) ifx->generated = 1;
4540         return;
4541       }
4542     }
4543     /* Compare two variables */
4544
4545     DEBUGpic16_emitcode(";sign","%d",sign);
4546
4547     size--;
4548     if(sign) {
4549       /* Sigh. thus sucks... */
4550       if(size) {
4551         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4552         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4553         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4554         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4555         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4556         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4557       } else {
4558         /* Signed char comparison */
4559         /* Special thanks to Nikolai Golovchenko for this snippet */
4560         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4561         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4562         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4563         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4564         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4565         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4566
4567         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4568         genSkipc(&rFalseIfx);
4569           
4570         if(ifx) ifx->generated = 1;
4571         return;
4572       }
4573
4574     } else {
4575
4576       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4577       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4578     }
4579
4580
4581     /* The rest of the bytes of a multi-byte compare */
4582     while (size) {
4583
4584       emitSKPZ;
4585       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4586       size--;
4587
4588       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4589       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4590
4591
4592     }
4593
4594     pic16_emitpLabel(lbl->key);
4595
4596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4597     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4598         (AOP_TYPE(result) == AOP_REG)) {
4599       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4600       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4601     } else {
4602       genSkipc(&rFalseIfx);
4603     }         
4604     //genSkipc(&rFalseIfx);
4605     if(ifx) ifx->generated = 1;
4606
4607     return;
4608
4609   }
4610
4611   // check_carry:
4612   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4613     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4614     pic16_outBitC(result);
4615   } else {
4616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4617     /* if the result is used in the next
4618        ifx conditional branch then generate
4619        code a little differently */
4620     if (ifx )
4621       genIfxJump (ifx,"c");
4622     else
4623       pic16_outBitC(result);
4624     /* leave the result in acc */
4625   }
4626
4627 }
4628
4629 /*-----------------------------------------------------------------*/
4630 /* genCmpGt :- greater than comparison                             */
4631 /*-----------------------------------------------------------------*/
4632 static void genCmpGt (iCode *ic, iCode *ifx)
4633 {
4634     operand *left, *right, *result;
4635     sym_link *letype , *retype;
4636     int sign ;
4637
4638     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4639     left = IC_LEFT(ic);
4640     right= IC_RIGHT(ic);
4641     result = IC_RESULT(ic);
4642
4643     letype = getSpec(operandType(left));
4644     retype =getSpec(operandType(right));
4645     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4646     /* assign the amsops */
4647     pic16_aopOp (left,ic,FALSE);
4648     pic16_aopOp (right,ic,FALSE);
4649     pic16_aopOp (result,ic,TRUE);
4650
4651     genCmp(right, left, result, ifx, sign);
4652
4653     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4654     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4655     pic16_freeAsmop(result,NULL,ic,TRUE); 
4656 }
4657
4658 /*-----------------------------------------------------------------*/
4659 /* genCmpLt - less than comparisons                                */
4660 /*-----------------------------------------------------------------*/
4661 static void genCmpLt (iCode *ic, iCode *ifx)
4662 {
4663     operand *left, *right, *result;
4664     sym_link *letype , *retype;
4665     int sign ;
4666
4667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4668     left = IC_LEFT(ic);
4669     right= IC_RIGHT(ic);
4670     result = IC_RESULT(ic);
4671
4672     letype = getSpec(operandType(left));
4673     retype =getSpec(operandType(right));
4674     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4675
4676     /* assign the amsops */
4677     pic16_aopOp (left,ic,FALSE);
4678     pic16_aopOp (right,ic,FALSE);
4679     pic16_aopOp (result,ic,TRUE);
4680
4681     genCmp(left, right, result, ifx, sign);
4682
4683     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4684     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4685     pic16_freeAsmop(result,NULL,ic,TRUE); 
4686 }
4687
4688 /*-----------------------------------------------------------------*/
4689 /* genc16bit2lit - compare a 16 bit value to a literal             */
4690 /*-----------------------------------------------------------------*/
4691 static void genc16bit2lit(operand *op, int lit, int offset)
4692 {
4693   int i;
4694
4695   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4696   if( (lit&0xff) == 0) 
4697     i=1;
4698   else
4699     i=0;
4700
4701   switch( BYTEofLONG(lit,i)) { 
4702   case 0:
4703     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4704     break;
4705   case 1:
4706     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4707     break;
4708   case 0xff:
4709     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4710     break;
4711   default:
4712     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4713     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4714   }
4715
4716   i ^= 1;
4717
4718   switch( BYTEofLONG(lit,i)) { 
4719   case 0:
4720     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4721     break;
4722   case 1:
4723     emitSKPNZ;
4724     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4725     break;
4726   case 0xff:
4727     emitSKPNZ;
4728     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4729     break;
4730   default:
4731     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4732     emitSKPNZ;
4733     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4734
4735   }
4736
4737 }
4738
4739 /*-----------------------------------------------------------------*/
4740 /* gencjneshort - compare and jump if not equal                    */
4741 /*-----------------------------------------------------------------*/
4742 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4743 {
4744   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4745   int offset = 0;
4746   int res_offset = 0;  /* the result may be a different size then left or right */
4747   int res_size = AOP_SIZE(result);
4748   resolvedIfx rIfx;
4749   symbol *lbl;
4750
4751   unsigned long lit = 0L;
4752   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4753   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4754   if(result)
4755     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4756   resolveIfx(&rIfx,ifx);
4757   lbl =  newiTempLabel(NULL);
4758
4759
4760   /* if the left side is a literal or 
4761      if the right is in a pointer register and left 
4762      is not */
4763   if ((AOP_TYPE(left) == AOP_LIT) || 
4764       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4765     operand *t = right;
4766     right = left;
4767     left = t;
4768   }
4769   if(AOP_TYPE(right) == AOP_LIT)
4770     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4771
4772   /* if the right side is a literal then anything goes */
4773   if (AOP_TYPE(right) == AOP_LIT &&
4774       AOP_TYPE(left) != AOP_DIR ) {
4775     switch(size) {
4776     case 2:
4777       genc16bit2lit(left, lit, 0);
4778       emitSKPNZ;
4779       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4780       break;
4781     default:
4782       while (size--) {
4783         if(lit & 0xff) {
4784           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4785           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4786         } else {
4787           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4788         }
4789
4790         emitSKPNZ;
4791         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4792         offset++;
4793         if(res_offset < res_size-1)
4794           res_offset++;
4795         lit >>= 8;
4796       }
4797       break;
4798     }
4799   }
4800
4801   /* if the right side is in a register or in direct space or
4802      if the left is a pointer register & right is not */    
4803   else if (AOP_TYPE(right) == AOP_REG ||
4804            AOP_TYPE(right) == AOP_DIR || 
4805            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4806            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4807     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4808     int lbl_key = lbl->key;
4809
4810     if(result) {
4811       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4812       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4813     }else {
4814       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4815       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4816               __FUNCTION__,__LINE__);
4817       return;
4818     }
4819
4820 /*     switch(size) { */
4821 /*     case 2: */
4822 /*       genc16bit2lit(left, lit, 0); */
4823 /*       emitSKPNZ; */
4824 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4825 /*       break; */
4826 /*     default: */
4827     while (size--) {
4828       int emit_skip=1;
4829       if((AOP_TYPE(left) == AOP_DIR) && 
4830          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4831
4832         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4833         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4834
4835       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4836             
4837         switch (lit & 0xff) {
4838         case 0:
4839           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4840           break;
4841         case 1:
4842           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4843           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4844           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4845           emit_skip=0;
4846           break;
4847         case 0xff:
4848           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4849           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4850           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4851           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4852           emit_skip=0;
4853           break;
4854         default:
4855           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4856           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4857         }
4858         lit >>= 8;
4859
4860       } else {
4861         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4862       }
4863       if(emit_skip) {
4864         if(AOP_TYPE(result) == AOP_CRY) {
4865           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4866           if(rIfx.condition)
4867             emitSKPNZ;
4868           else
4869             emitSKPZ;
4870           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4871         } else {
4872           /* fix me. probably need to check result size too */
4873           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4874           if(rIfx.condition)
4875             emitSKPZ;
4876           else
4877             emitSKPNZ;
4878           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4879           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4880         }
4881         if(ifx)
4882           ifx->generated=1;
4883       }
4884       emit_skip++;
4885       offset++;
4886       if(res_offset < res_size-1)
4887         res_offset++;
4888     }
4889 /*       break; */
4890 /*     } */
4891   } else if(AOP_TYPE(right) == AOP_REG &&
4892             AOP_TYPE(left) != AOP_DIR){
4893
4894     while(size--) {
4895       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4896       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4897       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4898       if(rIfx.condition)
4899         emitSKPNZ;
4900       else
4901         emitSKPZ;
4902       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4903       offset++;
4904       if(res_offset < res_size-1)
4905         res_offset++;
4906     }
4907       
4908   }else{
4909     /* right is a pointer reg need both a & b */
4910     while(size--) {
4911       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4912       if(strcmp(l,"b"))
4913         pic16_emitcode("mov","b,%s",l);
4914       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4915       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4916       offset++;
4917     }
4918   }
4919
4920   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4921   if(!rIfx.condition)
4922     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4923
4924   pic16_emitpLabel(lbl->key);
4925
4926   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4927
4928   if(ifx)
4929     ifx->generated = 1;
4930 }
4931
4932 #if 0
4933 /*-----------------------------------------------------------------*/
4934 /* gencjne - compare and jump if not equal                         */
4935 /*-----------------------------------------------------------------*/
4936 static void gencjne(operand *left, operand *right, iCode *ifx)
4937 {
4938     symbol *tlbl  = newiTempLabel(NULL);
4939
4940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4941     gencjneshort(left, right, lbl);
4942
4943     pic16_emitcode("mov","a,%s",one);
4944     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4945     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4946     pic16_emitcode("clr","a");
4947     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4948
4949     pic16_emitpLabel(lbl->key);
4950     pic16_emitpLabel(tlbl->key);
4951
4952 }
4953 #endif
4954
4955 /*-----------------------------------------------------------------*/
4956 /* genCmpEq - generates code for equal to                          */
4957 /*-----------------------------------------------------------------*/
4958 static void genCmpEq (iCode *ic, iCode *ifx)
4959 {
4960     operand *left, *right, *result;
4961     unsigned long lit = 0L;
4962     int size,offset=0;
4963
4964     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4965
4966     if(ifx)
4967       DEBUGpic16_emitcode ("; ifx is non-null","");
4968     else
4969       DEBUGpic16_emitcode ("; ifx is null","");
4970
4971     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4972     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4973     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4974
4975     size = max(AOP_SIZE(left),AOP_SIZE(right));
4976
4977     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4978
4979     /* if literal, literal on the right or 
4980     if the right is in a pointer register and left 
4981     is not */
4982     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4983         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4984       operand *tmp = right ;
4985       right = left;
4986       left = tmp;
4987     }
4988
4989
4990     if(ifx && !AOP_SIZE(result)){
4991         symbol *tlbl;
4992         /* if they are both bit variables */
4993         if (AOP_TYPE(left) == AOP_CRY &&
4994             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4995             if(AOP_TYPE(right) == AOP_LIT){
4996                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4997                 if(lit == 0L){
4998                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4999                     pic16_emitcode("cpl","c");
5000                 } else if(lit == 1L) {
5001                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5002                 } else {
5003                     pic16_emitcode("clr","c");
5004                 }
5005                 /* AOP_TYPE(right) == AOP_CRY */
5006             } else {
5007                 symbol *lbl = newiTempLabel(NULL);
5008                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5009                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5010                 pic16_emitcode("cpl","c");
5011                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5012             }
5013             /* if true label then we jump if condition
5014             supplied is true */
5015             tlbl = newiTempLabel(NULL);
5016             if ( IC_TRUE(ifx) ) {
5017                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5018                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5019             } else {
5020                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5021                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5022             }
5023             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5024
5025             {
5026               /* left and right are both bit variables, result is carry */
5027               resolvedIfx rIfx;
5028               
5029               resolveIfx(&rIfx,ifx);
5030
5031               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5032               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5033               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5034               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5035               genSkipz2(&rIfx,0);
5036             }
5037         } else {
5038
5039           /* They're not both bit variables. Is the right a literal? */
5040           if(AOP_TYPE(right) == AOP_LIT) {
5041             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5042             
5043             switch(size) {
5044
5045             case 1:
5046               switch(lit & 0xff) {
5047               case 1:
5048                 if ( IC_TRUE(ifx) ) {
5049                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5050                   emitSKPNZ;
5051                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5052                 } else {
5053                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5054                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5055                 }
5056                 break;
5057               case 0xff:
5058                 if ( IC_TRUE(ifx) ) {
5059                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5060                   emitSKPNZ;
5061                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5062                 } else {
5063                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5064                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5065                 }
5066                 break;
5067               default:
5068                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5069                 if(lit)
5070                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5071                 genSkip(ifx,'z');
5072               }
5073
5074
5075               /* end of size == 1 */
5076               break;
5077               
5078             case 2:
5079               genc16bit2lit(left,lit,offset);
5080               genSkip(ifx,'z');
5081               break;
5082               /* end of size == 2 */
5083
5084             default:
5085               /* size is 4 */
5086               if(lit==0) {
5087                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5088                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5089                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5090                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5091
5092               } else {
5093
5094                 /* search for patterns that can be optimized */
5095
5096                 genc16bit2lit(left,lit,0);
5097                 lit >>= 16;
5098                 if(lit) {
5099                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
5100                   //genSkip(ifx,'z');
5101                   genc16bit2lit(left,lit,2);
5102                 } else {
5103                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5104                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5105
5106                 }
5107                 
5108               }
5109
5110               genSkip(ifx,'z');
5111             }
5112           
5113             ifx->generated = 1;
5114             goto release ;
5115             
5116
5117           } else if(AOP_TYPE(right) == AOP_CRY ) {
5118             /* we know the left is not a bit, but that the right is */
5119             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5120             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5121                       pic16_popGet(AOP(right),offset));
5122             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5123
5124             /* if the two are equal, then W will be 0 and the Z bit is set
5125              * we could test Z now, or go ahead and check the high order bytes if
5126              * the variable we're comparing is larger than a byte. */
5127
5128             while(--size)
5129               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5130
5131             if ( IC_TRUE(ifx) ) {
5132               emitSKPNZ;
5133               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5134               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5135             } else {
5136               emitSKPZ;
5137               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5138               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5139             }
5140
5141           } else {
5142             /* They're both variables that are larger than bits */
5143             int s = size;
5144
5145             tlbl = newiTempLabel(NULL);
5146
5147             while(size--) {
5148               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5149               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5150
5151               if ( IC_TRUE(ifx) ) {
5152                 if(size) {
5153                   emitSKPZ;
5154                 
5155                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5156
5157                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5158                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5159                 } else {
5160                   emitSKPNZ;
5161
5162                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5163
5164
5165                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5166                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5167                 }
5168               } else {
5169                 emitSKPZ;
5170
5171                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5172
5173                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5174                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5175               }
5176               offset++;
5177             }
5178             if(s>1 && IC_TRUE(ifx)) {
5179               pic16_emitpLabel(tlbl->key);
5180               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5181             }
5182           }
5183         }
5184         /* mark the icode as generated */
5185         ifx->generated = 1;
5186         goto release ;
5187     }
5188
5189     /* if they are both bit variables */
5190     if (AOP_TYPE(left) == AOP_CRY &&
5191         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5192         if(AOP_TYPE(right) == AOP_LIT){
5193             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5194             if(lit == 0L){
5195                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5196                 pic16_emitcode("cpl","c");
5197             } else if(lit == 1L) {
5198                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5199             } else {
5200                 pic16_emitcode("clr","c");
5201             }
5202             /* AOP_TYPE(right) == AOP_CRY */
5203         } else {
5204             symbol *lbl = newiTempLabel(NULL);
5205             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5206             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5207             pic16_emitcode("cpl","c");
5208             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5209         }
5210         /* c = 1 if egal */
5211         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5212             pic16_outBitC(result);
5213             goto release ;
5214         }
5215         if (ifx) {
5216             genIfxJump (ifx,"c");
5217             goto release ;
5218         }
5219         /* if the result is used in an arithmetic operation
5220         then put the result in place */
5221         pic16_outBitC(result);
5222     } else {
5223       
5224       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5225       gencjne(left,right,result,ifx);
5226 /*
5227       if(ifx) 
5228         gencjne(left,right,newiTempLabel(NULL));
5229       else {
5230         if(IC_TRUE(ifx)->key)
5231           gencjne(left,right,IC_TRUE(ifx)->key);
5232         else
5233           gencjne(left,right,IC_FALSE(ifx)->key);
5234         ifx->generated = 1;
5235         goto release ;
5236       }
5237       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5238         pic16_aopPut(AOP(result),"a",0);
5239         goto release ;
5240       }
5241
5242       if (ifx) {
5243         genIfxJump (ifx,"a");
5244         goto release ;
5245       }
5246 */
5247       /* if the result is used in an arithmetic operation
5248          then put the result in place */
5249 /*
5250       if (AOP_TYPE(result) != AOP_CRY) 
5251         pic16_outAcc(result);
5252 */
5253       /* leave the result in acc */
5254     }
5255
5256 release:
5257     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5258     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5259     pic16_freeAsmop(result,NULL,ic,TRUE);
5260 }
5261
5262 /*-----------------------------------------------------------------*/
5263 /* ifxForOp - returns the icode containing the ifx for operand     */
5264 /*-----------------------------------------------------------------*/
5265 static iCode *ifxForOp ( operand *op, iCode *ic )
5266 {
5267     /* if true symbol then needs to be assigned */
5268     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5269     if (IS_TRUE_SYMOP(op))
5270         return NULL ;
5271
5272     /* if this has register type condition and
5273     the next instruction is ifx with the same operand
5274     and live to of the operand is upto the ifx only then */
5275     if (ic->next &&
5276         ic->next->op == IFX &&
5277         IC_COND(ic->next)->key == op->key &&
5278         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5279         return ic->next;
5280
5281     if (ic->next &&
5282         ic->next->op == IFX &&
5283         IC_COND(ic->next)->key == op->key) {
5284       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5285       return ic->next;
5286     }
5287
5288     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5289     if (ic->next &&
5290         ic->next->op == IFX)
5291       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5292
5293     if (ic->next &&
5294         ic->next->op == IFX &&
5295         IC_COND(ic->next)->key == op->key) {
5296       DEBUGpic16_emitcode ("; "," key is okay");
5297       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5298                            OP_SYMBOL(op)->liveTo,
5299                            ic->next->seq);
5300     }
5301
5302
5303     return NULL;
5304 }
5305 /*-----------------------------------------------------------------*/
5306 /* genAndOp - for && operation                                     */
5307 /*-----------------------------------------------------------------*/
5308 static void genAndOp (iCode *ic)
5309 {
5310     operand *left,*right, *result;
5311 /*     symbol *tlbl; */
5312
5313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5314     /* note here that && operations that are in an
5315     if statement are taken away by backPatchLabels
5316     only those used in arthmetic operations remain */
5317     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5318     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5319     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5320
5321     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5322
5323     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5324     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5325     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5326
5327     /* if both are bit variables */
5328 /*     if (AOP_TYPE(left) == AOP_CRY && */
5329 /*         AOP_TYPE(right) == AOP_CRY ) { */
5330 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5331 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5332 /*         pic16_outBitC(result); */
5333 /*     } else { */
5334 /*         tlbl = newiTempLabel(NULL); */
5335 /*         pic16_toBoolean(left);     */
5336 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5337 /*         pic16_toBoolean(right); */
5338 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5339 /*         pic16_outBitAcc(result); */
5340 /*     } */
5341
5342     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5343     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5344     pic16_freeAsmop(result,NULL,ic,TRUE);
5345 }
5346
5347
5348 /*-----------------------------------------------------------------*/
5349 /* genOrOp - for || operation                                      */
5350 /*-----------------------------------------------------------------*/
5351 /*
5352   tsd pic port -
5353   modified this code, but it doesn't appear to ever get called
5354 */
5355
5356 static void genOrOp (iCode *ic)
5357 {
5358     operand *left,*right, *result;
5359     symbol *tlbl;
5360
5361     /* note here that || operations that are in an
5362     if statement are taken away by backPatchLabels
5363     only those used in arthmetic operations remain */
5364     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5365     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5366     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5367     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5368
5369     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5370
5371     /* if both are bit variables */
5372     if (AOP_TYPE(left) == AOP_CRY &&
5373         AOP_TYPE(right) == AOP_CRY ) {
5374       pic16_emitcode("clrc","");
5375       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5376                AOP(left)->aopu.aop_dir,
5377                AOP(left)->aopu.aop_dir);
5378       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5379                AOP(right)->aopu.aop_dir,
5380                AOP(right)->aopu.aop_dir);
5381       pic16_emitcode("setc","");
5382
5383     } else {
5384         tlbl = newiTempLabel(NULL);
5385         pic16_toBoolean(left);
5386         emitSKPZ;
5387         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5388         pic16_toBoolean(right);
5389         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5390
5391         pic16_outBitAcc(result);
5392     }
5393
5394     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5395     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5396     pic16_freeAsmop(result,NULL,ic,TRUE);            
5397 }
5398
5399 /*-----------------------------------------------------------------*/
5400 /* isLiteralBit - test if lit == 2^n                               */
5401 /*-----------------------------------------------------------------*/
5402 static int isLiteralBit(unsigned long lit)
5403 {
5404     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5405     0x100L,0x200L,0x400L,0x800L,
5406     0x1000L,0x2000L,0x4000L,0x8000L,
5407     0x10000L,0x20000L,0x40000L,0x80000L,
5408     0x100000L,0x200000L,0x400000L,0x800000L,
5409     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5410     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5411     int idx;
5412     
5413     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5414     for(idx = 0; idx < 32; idx++)
5415         if(lit == pw[idx])
5416             return idx+1;
5417     return 0;
5418 }
5419
5420 /*-----------------------------------------------------------------*/
5421 /* continueIfTrue -                                                */
5422 /*-----------------------------------------------------------------*/
5423 static void continueIfTrue (iCode *ic)
5424 {
5425     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5426     if(IC_TRUE(ic))
5427         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5428     ic->generated = 1;
5429 }
5430
5431 /*-----------------------------------------------------------------*/
5432 /* jmpIfTrue -                                                     */
5433 /*-----------------------------------------------------------------*/
5434 static void jumpIfTrue (iCode *ic)
5435 {
5436     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5437     if(!IC_TRUE(ic))
5438         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5439     ic->generated = 1;
5440 }
5441
5442 /*-----------------------------------------------------------------*/
5443 /* jmpTrueOrFalse -                                                */
5444 /*-----------------------------------------------------------------*/
5445 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5446 {
5447     // ugly but optimized by peephole
5448     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5449     if(IC_TRUE(ic)){
5450         symbol *nlbl = newiTempLabel(NULL);
5451         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5452         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5453         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5454         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5455     }
5456     else{
5457         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5458         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5459     }
5460     ic->generated = 1;
5461 }
5462
5463 /*-----------------------------------------------------------------*/
5464 /* genAnd  - code for and                                          */
5465 /*-----------------------------------------------------------------*/
5466 static void genAnd (iCode *ic, iCode *ifx)
5467 {
5468   operand *left, *right, *result;
5469   int size, offset=0;  
5470   unsigned long lit = 0L;
5471   int bytelit = 0;
5472   resolvedIfx rIfx;
5473
5474
5475   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5476   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5477   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5478   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5479
5480   resolveIfx(&rIfx,ifx);
5481
5482   /* if left is a literal & right is not then exchange them */
5483   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5484       AOP_NEEDSACC(left)) {
5485     operand *tmp = right ;
5486     right = left;
5487     left = tmp;
5488   }
5489
5490   /* if result = right then exchange them */
5491   if(pic16_sameRegs(AOP(result),AOP(right))){
5492     operand *tmp = right ;
5493     right = left;
5494     left = tmp;
5495   }
5496
5497   /* if right is bit then exchange them */
5498   if (AOP_TYPE(right) == AOP_CRY &&
5499       AOP_TYPE(left) != AOP_CRY){
5500     operand *tmp = right ;
5501     right = left;
5502     left = tmp;
5503   }
5504   if(AOP_TYPE(right) == AOP_LIT)
5505     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5506
5507   size = AOP_SIZE(result);
5508
5509   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5510
5511   // if(bit & yy)
5512   // result = bit & yy;
5513   if (AOP_TYPE(left) == AOP_CRY){
5514     // c = bit & literal;
5515     if(AOP_TYPE(right) == AOP_LIT){
5516       if(lit & 1) {
5517         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5518           // no change
5519           goto release;
5520         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5521       } else {
5522         // bit(result) = 0;
5523         if(size && (AOP_TYPE(result) == AOP_CRY)){
5524           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5525           goto release;
5526         }
5527         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5528           jumpIfTrue(ifx);
5529           goto release;
5530         }
5531         pic16_emitcode("clr","c");
5532       }
5533     } else {
5534       if (AOP_TYPE(right) == AOP_CRY){
5535         // c = bit & bit;
5536         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5537         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5538       } else {
5539         // c = bit & val;
5540         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5541         // c = lsb
5542         pic16_emitcode("rrc","a");
5543         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5544       }
5545     }
5546     // bit = c
5547     // val = c
5548     if(size)
5549       pic16_outBitC(result);
5550     // if(bit & ...)
5551     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5552       genIfxJump(ifx, "c");           
5553     goto release ;
5554   }
5555
5556   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5557   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5558   if((AOP_TYPE(right) == AOP_LIT) &&
5559      (AOP_TYPE(result) == AOP_CRY) &&
5560      (AOP_TYPE(left) != AOP_CRY)){
5561     int posbit = isLiteralBit(lit);
5562     /* left &  2^n */
5563     if(posbit){
5564       posbit--;
5565       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5566       // bit = left & 2^n
5567       if(size)
5568         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5569       // if(left &  2^n)
5570       else{
5571         if(ifx){
5572 /*
5573           if(IC_TRUE(ifx)) {
5574             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5575             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5576           } else {
5577             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5578             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5579           }
5580 */
5581           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5582                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5583           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5584           
5585           ifx->generated = 1;
5586         }
5587         goto release;
5588       }
5589     } else {
5590       symbol *tlbl = newiTempLabel(NULL);
5591       int sizel = AOP_SIZE(left);
5592       if(size)
5593         pic16_emitcode("setb","c");
5594       while(sizel--){
5595         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5596           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5597           // byte ==  2^n ?
5598           if((posbit = isLiteralBit(bytelit)) != 0)
5599             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5600           else{
5601             if(bytelit != 0x0FFL)
5602               pic16_emitcode("anl","a,%s",
5603                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5604             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5605           }
5606         }
5607         offset++;
5608       }
5609       // bit = left & literal
5610       if(size){
5611         pic16_emitcode("clr","c");
5612         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5613       }
5614       // if(left & literal)
5615       else{
5616         if(ifx)
5617           jmpTrueOrFalse(ifx, tlbl);
5618         goto release ;
5619       }
5620     }
5621     pic16_outBitC(result);
5622     goto release ;
5623   }
5624
5625   /* if left is same as result */
5626   if(pic16_sameRegs(AOP(result),AOP(left))){
5627     int know_W = -1;
5628     for(;size--; offset++,lit>>=8) {
5629       if(AOP_TYPE(right) == AOP_LIT){
5630         switch(lit & 0xff) {
5631         case 0x00:
5632           /*  and'ing with 0 has clears the result */
5633 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5634           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5635           break;
5636         case 0xff:
5637           /* and'ing with 0xff is a nop when the result and left are the same */
5638           break;
5639
5640         default:
5641           {
5642             int p = my_powof2( (~lit) & 0xff );
5643             if(p>=0) {
5644               /* only one bit is set in the literal, so use a bcf instruction */
5645 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5646               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5647
5648             } else {
5649               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5650               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5651               if(know_W != (lit&0xff))
5652                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5653               know_W = lit &0xff;
5654               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5655             }
5656           }    
5657         }
5658       } else {
5659         if (AOP_TYPE(left) == AOP_ACC) {
5660           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5661         } else {                    
5662           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5663           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5664
5665         }
5666       }
5667     }
5668
5669   } else {
5670     // left & result in different registers
5671     if(AOP_TYPE(result) == AOP_CRY){
5672       // result = bit
5673       // if(size), result in bit
5674       // if(!size && ifx), conditional oper: if(left & right)
5675       symbol *tlbl = newiTempLabel(NULL);
5676       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5677       if(size)
5678         pic16_emitcode("setb","c");
5679       while(sizer--){
5680         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5681         pic16_emitcode("anl","a,%s",
5682                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5683         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5684         offset++;
5685       }
5686       if(size){
5687         CLRC;
5688         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5689         pic16_outBitC(result);
5690       } else if(ifx)
5691         jmpTrueOrFalse(ifx, tlbl);
5692     } else {
5693       for(;(size--);offset++) {
5694         // normal case
5695         // result = left & right
5696         if(AOP_TYPE(right) == AOP_LIT){
5697           int t = (lit >> (offset*8)) & 0x0FFL;
5698           switch(t) { 
5699           case 0x00:
5700             pic16_emitcode("clrf","%s",
5701                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5702             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5703             break;
5704           case 0xff:
5705             pic16_emitcode("movf","%s,w",
5706                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5707             pic16_emitcode("movwf","%s",
5708                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5709             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5710             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5711             break;
5712           default:
5713             pic16_emitcode("movlw","0x%x",t);
5714             pic16_emitcode("andwf","%s,w",
5715                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5716             pic16_emitcode("movwf","%s",
5717                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5718               
5719             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5720             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5721             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5722           }
5723           continue;
5724         }
5725
5726         if (AOP_TYPE(left) == AOP_ACC) {
5727           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5728           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5729         } else {
5730           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5731           pic16_emitcode("andwf","%s,w",
5732                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5733           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5734           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5735         }
5736         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5737         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5738       }
5739     }
5740   }
5741
5742   release :
5743     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5744   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5745   pic16_freeAsmop(result,NULL,ic,TRUE);     
5746 }
5747
5748 /*-----------------------------------------------------------------*/
5749 /* genOr  - code for or                                            */
5750 /*-----------------------------------------------------------------*/
5751 static void genOr (iCode *ic, iCode *ifx)
5752 {
5753     operand *left, *right, *result;
5754     int size, offset=0;
5755     unsigned long lit = 0L;
5756
5757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5758
5759     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5760     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5761     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5762
5763     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5764
5765     /* if left is a literal & right is not then exchange them */
5766     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5767         AOP_NEEDSACC(left)) {
5768         operand *tmp = right ;
5769         right = left;
5770         left = tmp;
5771     }
5772
5773     /* if result = right then exchange them */
5774     if(pic16_sameRegs(AOP(result),AOP(right))){
5775         operand *tmp = right ;
5776         right = left;
5777         left = tmp;
5778     }
5779
5780     /* if right is bit then exchange them */
5781     if (AOP_TYPE(right) == AOP_CRY &&
5782         AOP_TYPE(left) != AOP_CRY){
5783         operand *tmp = right ;
5784         right = left;
5785         left = tmp;
5786     }
5787
5788     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5789
5790     if(AOP_TYPE(right) == AOP_LIT)
5791         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5792
5793     size = AOP_SIZE(result);
5794
5795     // if(bit | yy)
5796     // xx = bit | yy;
5797     if (AOP_TYPE(left) == AOP_CRY){
5798         if(AOP_TYPE(right) == AOP_LIT){
5799             // c = bit & literal;
5800             if(lit){
5801                 // lit != 0 => result = 1
5802                 if(AOP_TYPE(result) == AOP_CRY){
5803                   if(size)
5804                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5805                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5806                   //     AOP(result)->aopu.aop_dir,
5807                   //     AOP(result)->aopu.aop_dir);
5808                     else if(ifx)
5809                         continueIfTrue(ifx);
5810                     goto release;
5811                 }
5812             } else {
5813                 // lit == 0 => result = left
5814                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5815                     goto release;
5816                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5817             }
5818         } else {
5819             if (AOP_TYPE(right) == AOP_CRY){
5820               if(pic16_sameRegs(AOP(result),AOP(left))){
5821                 // c = bit | bit;
5822                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5823                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5824                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5825
5826                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5827                          AOP(result)->aopu.aop_dir,
5828                          AOP(result)->aopu.aop_dir);
5829                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5830                          AOP(right)->aopu.aop_dir,
5831                          AOP(right)->aopu.aop_dir);
5832                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5833                          AOP(result)->aopu.aop_dir,
5834                          AOP(result)->aopu.aop_dir);
5835               } else {
5836                 if( AOP_TYPE(result) == AOP_ACC) {
5837                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5838                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5839                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5840                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5841
5842                 } else {
5843
5844                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5845                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5846                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5847                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5848
5849                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5850                                  AOP(result)->aopu.aop_dir,
5851                                  AOP(result)->aopu.aop_dir);
5852                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5853                                  AOP(right)->aopu.aop_dir,
5854                                  AOP(right)->aopu.aop_dir);
5855                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5856                                  AOP(left)->aopu.aop_dir,
5857                                  AOP(left)->aopu.aop_dir);
5858                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5859                                  AOP(result)->aopu.aop_dir,
5860                                  AOP(result)->aopu.aop_dir);
5861                 }
5862               }
5863             } else {
5864                 // c = bit | val;
5865                 symbol *tlbl = newiTempLabel(NULL);
5866                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5867
5868
5869                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5870                 if( AOP_TYPE(right) == AOP_ACC) {
5871                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5872                   emitSKPNZ;
5873                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5874                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5875                 }
5876
5877
5878
5879                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5880                     pic16_emitcode(";XXX setb","c");
5881                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5882                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5883                 pic16_toBoolean(right);
5884                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5885                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5886                     jmpTrueOrFalse(ifx, tlbl);
5887                     goto release;
5888                 } else {
5889                     CLRC;
5890                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5891                 }
5892             }
5893         }
5894         // bit = c
5895         // val = c
5896         if(size)
5897             pic16_outBitC(result);
5898         // if(bit | ...)
5899         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5900             genIfxJump(ifx, "c");           
5901         goto release ;
5902     }
5903
5904     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5905     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5906     if((AOP_TYPE(right) == AOP_LIT) &&
5907        (AOP_TYPE(result) == AOP_CRY) &&
5908        (AOP_TYPE(left) != AOP_CRY)){
5909         if(lit){
5910           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5911             // result = 1
5912             if(size)
5913                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5914             else 
5915                 continueIfTrue(ifx);
5916             goto release;
5917         } else {
5918           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5919             // lit = 0, result = boolean(left)
5920             if(size)
5921                 pic16_emitcode(";XXX setb","c");
5922             pic16_toBoolean(right);
5923             if(size){
5924                 symbol *tlbl = newiTempLabel(NULL);
5925                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5926                 CLRC;
5927                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5928             } else {
5929                 genIfxJump (ifx,"a");
5930                 goto release;
5931             }
5932         }
5933         pic16_outBitC(result);
5934         goto release ;
5935     }
5936
5937     /* if left is same as result */
5938     if(pic16_sameRegs(AOP(result),AOP(left))){
5939       int know_W = -1;
5940       for(;size--; offset++,lit>>=8) {
5941         if(AOP_TYPE(right) == AOP_LIT){
5942           if((lit & 0xff) == 0)
5943             /*  or'ing with 0 has no effect */
5944             continue;
5945           else {
5946             int p = my_powof2(lit & 0xff);
5947             if(p>=0) {
5948               /* only one bit is set in the literal, so use a bsf instruction */
5949               pic16_emitpcode(POC_BSF,
5950                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5951             } else {
5952               if(know_W != (lit & 0xff))
5953                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5954               know_W = lit & 0xff;
5955               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5956             }
5957                     
5958           }
5959         } else {
5960           if (AOP_TYPE(left) == AOP_ACC) {
5961             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5962             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5963           } else {                  
5964             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5965             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5966
5967             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5968             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5969
5970           }
5971         }
5972       }
5973     } else {
5974         // left & result in different registers
5975         if(AOP_TYPE(result) == AOP_CRY){
5976             // result = bit
5977             // if(size), result in bit
5978             // if(!size && ifx), conditional oper: if(left | right)
5979             symbol *tlbl = newiTempLabel(NULL);
5980             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5981             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5982
5983
5984             if(size)
5985                 pic16_emitcode(";XXX setb","c");
5986             while(sizer--){
5987                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5988                 pic16_emitcode(";XXX orl","a,%s",
5989                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5990                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5991                 offset++;
5992             }
5993             if(size){
5994                 CLRC;
5995                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5996                 pic16_outBitC(result);
5997             } else if(ifx)
5998                 jmpTrueOrFalse(ifx, tlbl);
5999         } else for(;(size--);offset++){
6000           // normal case
6001           // result = left & right
6002           if(AOP_TYPE(right) == AOP_LIT){
6003             int t = (lit >> (offset*8)) & 0x0FFL;
6004             switch(t) { 
6005             case 0x00:
6006               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6007               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6008
6009               pic16_emitcode("movf","%s,w",
6010                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6011               pic16_emitcode("movwf","%s",
6012                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6013               break;
6014             default:
6015               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6016               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6017               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6018
6019               pic16_emitcode("movlw","0x%x",t);
6020               pic16_emitcode("iorwf","%s,w",
6021                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6022               pic16_emitcode("movwf","%s",
6023                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6024               
6025             }
6026             continue;
6027           }
6028
6029           // faster than result <- left, anl result,right
6030           // and better if result is SFR
6031           if (AOP_TYPE(left) == AOP_ACC) {
6032             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6033             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6034           } else {
6035             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6036             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6037
6038             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6039             pic16_emitcode("iorwf","%s,w",
6040                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6041           }
6042           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6043           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6044         }
6045     }
6046
6047 release :
6048     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6049     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6050     pic16_freeAsmop(result,NULL,ic,TRUE);     
6051 }
6052
6053 /*-----------------------------------------------------------------*/
6054 /* genXor - code for xclusive or                                   */
6055 /*-----------------------------------------------------------------*/
6056 static void genXor (iCode *ic, iCode *ifx)
6057 {
6058   operand *left, *right, *result;
6059   int size, offset=0;
6060   unsigned long lit = 0L;
6061
6062   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6063
6064   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6065   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6066   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6067
6068   /* if left is a literal & right is not ||
6069      if left needs acc & right does not */
6070   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6071       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6072     operand *tmp = right ;
6073     right = left;
6074     left = tmp;
6075   }
6076
6077   /* if result = right then exchange them */
6078   if(pic16_sameRegs(AOP(result),AOP(right))){
6079     operand *tmp = right ;
6080     right = left;
6081     left = tmp;
6082   }
6083
6084   /* if right is bit then exchange them */
6085   if (AOP_TYPE(right) == AOP_CRY &&
6086       AOP_TYPE(left) != AOP_CRY){
6087     operand *tmp = right ;
6088     right = left;
6089     left = tmp;
6090   }
6091   if(AOP_TYPE(right) == AOP_LIT)
6092     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6093
6094   size = AOP_SIZE(result);
6095
6096   // if(bit ^ yy)
6097   // xx = bit ^ yy;
6098   if (AOP_TYPE(left) == AOP_CRY){
6099     if(AOP_TYPE(right) == AOP_LIT){
6100       // c = bit & literal;
6101       if(lit>>1){
6102         // lit>>1  != 0 => result = 1
6103         if(AOP_TYPE(result) == AOP_CRY){
6104           if(size)
6105             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6106             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6107           else if(ifx)
6108             continueIfTrue(ifx);
6109           goto release;
6110         }
6111         pic16_emitcode("setb","c");
6112       } else{
6113         // lit == (0 or 1)
6114         if(lit == 0){
6115           // lit == 0, result = left
6116           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6117             goto release;
6118           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6119         } else{
6120           // lit == 1, result = not(left)
6121           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6122             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6123             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6124             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6125             goto release;
6126           } else {
6127             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6128             pic16_emitcode("cpl","c");
6129           }
6130         }
6131       }
6132
6133     } else {
6134       // right != literal
6135       symbol *tlbl = newiTempLabel(NULL);
6136       if (AOP_TYPE(right) == AOP_CRY){
6137         // c = bit ^ bit;
6138         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6139       }
6140       else{
6141         int sizer = AOP_SIZE(right);
6142         // c = bit ^ val
6143         // if val>>1 != 0, result = 1
6144         pic16_emitcode("setb","c");
6145         while(sizer){
6146           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6147           if(sizer == 1)
6148             // test the msb of the lsb
6149             pic16_emitcode("anl","a,#0xfe");
6150           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6151           sizer--;
6152         }
6153         // val = (0,1)
6154         pic16_emitcode("rrc","a");
6155       }
6156       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6157       pic16_emitcode("cpl","c");
6158       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6159     }
6160     // bit = c
6161     // val = c
6162     if(size)
6163       pic16_outBitC(result);
6164     // if(bit | ...)
6165     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6166       genIfxJump(ifx, "c");           
6167     goto release ;
6168   }
6169
6170   if(pic16_sameRegs(AOP(result),AOP(left))){
6171     /* if left is same as result */
6172     for(;size--; offset++) {
6173       if(AOP_TYPE(right) == AOP_LIT){
6174         int t  = (lit >> (offset*8)) & 0x0FFL;
6175         if(t == 0x00L)
6176           continue;
6177         else
6178           if (IS_AOP_PREG(left)) {
6179             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6180             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6181             pic16_aopPut(AOP(result),"a",offset);
6182           } else {
6183             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6184             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6185             pic16_emitcode("xrl","%s,%s",
6186                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6187                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6188           }
6189       } else {
6190         if (AOP_TYPE(left) == AOP_ACC)
6191           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6192         else {
6193           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6194           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6195 /*
6196           if (IS_AOP_PREG(left)) {
6197             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6198             pic16_aopPut(AOP(result),"a",offset);
6199           } else
6200             pic16_emitcode("xrl","%s,a",
6201                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6202 */
6203         }
6204       }
6205     }
6206   } else {
6207     // left & result in different registers
6208     if(AOP_TYPE(result) == AOP_CRY){
6209       // result = bit
6210       // if(size), result in bit
6211       // if(!size && ifx), conditional oper: if(left ^ right)
6212       symbol *tlbl = newiTempLabel(NULL);
6213       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6214       if(size)
6215         pic16_emitcode("setb","c");
6216       while(sizer--){
6217         if((AOP_TYPE(right) == AOP_LIT) &&
6218            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6219           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6220         } else {
6221           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6222           pic16_emitcode("xrl","a,%s",
6223                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6224         }
6225         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6226         offset++;
6227       }
6228       if(size){
6229         CLRC;
6230         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6231         pic16_outBitC(result);
6232       } else if(ifx)
6233         jmpTrueOrFalse(ifx, tlbl);
6234     } else for(;(size--);offset++){
6235       // normal case
6236       // result = left & right
6237       if(AOP_TYPE(right) == AOP_LIT){
6238         int t = (lit >> (offset*8)) & 0x0FFL;
6239         switch(t) { 
6240         case 0x00:
6241           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6242           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6243           pic16_emitcode("movf","%s,w",
6244                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6245           pic16_emitcode("movwf","%s",
6246                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6247           break;
6248         case 0xff:
6249           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6250           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6251           pic16_emitcode("comf","%s,w",
6252                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6253           pic16_emitcode("movwf","%s",
6254                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6255           break;
6256         default:
6257           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6258           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6259           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6260           pic16_emitcode("movlw","0x%x",t);
6261           pic16_emitcode("xorwf","%s,w",
6262                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6263           pic16_emitcode("movwf","%s",
6264                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6265
6266         }
6267         continue;
6268       }
6269
6270       // faster than result <- left, anl result,right
6271       // and better if result is SFR
6272       if (AOP_TYPE(left) == AOP_ACC) {
6273         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6274         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6275       } else {
6276         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6277         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6278         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6279         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6280       }
6281       if ( AOP_TYPE(result) != AOP_ACC){
6282         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6283         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6284       }
6285     }
6286   }
6287
6288   release :
6289     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6290   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6291   pic16_freeAsmop(result,NULL,ic,TRUE);     
6292 }
6293
6294 /*-----------------------------------------------------------------*/
6295 /* genInline - write the inline code out                           */
6296 /*-----------------------------------------------------------------*/
6297 static void genInline (iCode *ic)
6298 {
6299     char *buffer, *bp, *bp1;
6300     
6301     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6302
6303     _G.inLine += (!options.asmpeep);
6304
6305     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6306     strcpy(buffer,IC_INLINE(ic));
6307
6308     /* emit each line as a code */
6309     while (*bp) {
6310         if (*bp == '\n') {
6311             *bp++ = '\0';
6312
6313             if(*bp1)
6314               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));       //pic16_AssembleLine(bp1, 0));
6315                                         // inline directly, no process
6316             bp1 = bp;
6317         } else {
6318             if (*bp == ':') {
6319                 bp++;
6320                 *bp = '\0';
6321                 bp++;
6322                 pic16_emitcode(bp1,"");
6323                 bp1 = bp;
6324             } else
6325                 bp++;
6326         }
6327     }
6328     if ((bp1 != bp) && *bp1)
6329       pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));               //pic16_AssembleLine(bp1, 0));
6330
6331     Safe_free(buffer);
6332
6333     _G.inLine -= (!options.asmpeep);
6334 }
6335
6336 /*-----------------------------------------------------------------*/
6337 /* genRRC - rotate right with carry                                */
6338 /*-----------------------------------------------------------------*/
6339 static void genRRC (iCode *ic)
6340 {
6341   operand *left , *result ;
6342   int size, offset = 0, same;
6343
6344   /* rotate right with carry */
6345   left = IC_LEFT(ic);
6346   result=IC_RESULT(ic);
6347   pic16_aopOp (left,ic,FALSE);
6348   pic16_aopOp (result,ic,FALSE);
6349
6350   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6351
6352   same = pic16_sameRegs(AOP(result),AOP(left));
6353
6354   size = AOP_SIZE(result);    
6355
6356   /* get the lsb and put it into the carry */
6357   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6358
6359   offset = 0 ;
6360
6361   while(size--) {
6362
6363     if(same) {
6364       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6365     } else {
6366       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6367       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6368     }
6369
6370     offset++;
6371   }
6372
6373   pic16_freeAsmop(left,NULL,ic,TRUE);
6374   pic16_freeAsmop(result,NULL,ic,TRUE);
6375 }
6376
6377 /*-----------------------------------------------------------------*/
6378 /* genRLC - generate code for rotate left with carry               */
6379 /*-----------------------------------------------------------------*/
6380 static void genRLC (iCode *ic)
6381 {    
6382   operand *left , *result ;
6383   int size, offset = 0;
6384   int same;
6385
6386   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6387   /* rotate right with carry */
6388   left = IC_LEFT(ic);
6389   result=IC_RESULT(ic);
6390   pic16_aopOp (left,ic,FALSE);
6391   pic16_aopOp (result,ic,FALSE);
6392
6393   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6394
6395   same = pic16_sameRegs(AOP(result),AOP(left));
6396
6397   /* move it to the result */
6398   size = AOP_SIZE(result);    
6399
6400   /* get the msb and put it into the carry */
6401   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6402
6403   offset = 0 ;
6404
6405   while(size--) {
6406
6407     if(same) {
6408       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6409     } else {
6410       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6411       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6412     }
6413
6414     offset++;
6415   }
6416
6417
6418   pic16_freeAsmop(left,NULL,ic,TRUE);
6419   pic16_freeAsmop(result,NULL,ic,TRUE);
6420 }
6421
6422 /*-----------------------------------------------------------------*/
6423 /* genGetHbit - generates code get highest order bit               */
6424 /*-----------------------------------------------------------------*/
6425 static void genGetHbit (iCode *ic)
6426 {
6427     operand *left, *result;
6428     left = IC_LEFT(ic);
6429     result=IC_RESULT(ic);
6430     pic16_aopOp (left,ic,FALSE);
6431     pic16_aopOp (result,ic,FALSE);
6432
6433     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6434     /* get the highest order byte into a */
6435     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6436     if(AOP_TYPE(result) == AOP_CRY){
6437         pic16_emitcode("rlc","a");
6438         pic16_outBitC(result);
6439     }
6440     else{
6441         pic16_emitcode("rl","a");
6442         pic16_emitcode("anl","a,#0x01");
6443         pic16_outAcc(result);
6444     }
6445
6446
6447     pic16_freeAsmop(left,NULL,ic,TRUE);
6448     pic16_freeAsmop(result,NULL,ic,TRUE);
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* AccRol - rotate left accumulator by known count                 */
6453 /*-----------------------------------------------------------------*/
6454 static void AccRol (int shCount)
6455 {
6456     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6457     shCount &= 0x0007;              // shCount : 0..7
6458     switch(shCount){
6459         case 0 :
6460             break;
6461         case 1 :
6462             pic16_emitcode("rl","a");
6463             break;
6464         case 2 :
6465             pic16_emitcode("rl","a");
6466             pic16_emitcode("rl","a");
6467             break;
6468         case 3 :
6469             pic16_emitcode("swap","a");
6470             pic16_emitcode("rr","a");
6471             break;
6472         case 4 :
6473             pic16_emitcode("swap","a");
6474             break;
6475         case 5 :
6476             pic16_emitcode("swap","a");
6477             pic16_emitcode("rl","a");
6478             break;
6479         case 6 :
6480             pic16_emitcode("rr","a");
6481             pic16_emitcode("rr","a");
6482             break;
6483         case 7 :
6484             pic16_emitcode("rr","a");
6485             break;
6486     }
6487 }
6488
6489 /*-----------------------------------------------------------------*/
6490 /* AccLsh - left shift accumulator by known count                  */
6491 /*-----------------------------------------------------------------*/
6492 static void AccLsh (int shCount)
6493 {
6494     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6495     if(shCount != 0){
6496         if(shCount == 1)
6497             pic16_emitcode("add","a,acc");
6498         else 
6499             if(shCount == 2) {
6500             pic16_emitcode("add","a,acc");
6501             pic16_emitcode("add","a,acc");
6502         } else {
6503             /* rotate left accumulator */
6504             AccRol(shCount);
6505             /* and kill the lower order bits */
6506             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6507         }
6508     }
6509 }
6510
6511 /*-----------------------------------------------------------------*/
6512 /* AccRsh - right shift accumulator by known count                 */
6513 /*-----------------------------------------------------------------*/
6514 static void AccRsh (int shCount)
6515 {
6516     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6517     if(shCount != 0){
6518         if(shCount == 1){
6519             CLRC;
6520             pic16_emitcode("rrc","a");
6521         } else {
6522             /* rotate right accumulator */
6523             AccRol(8 - shCount);
6524             /* and kill the higher order bits */
6525             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6526         }
6527     }
6528 }
6529
6530 #if 0
6531 /*-----------------------------------------------------------------*/
6532 /* AccSRsh - signed right shift accumulator by known count                 */
6533 /*-----------------------------------------------------------------*/
6534 static void AccSRsh (int shCount)
6535 {
6536     symbol *tlbl ;
6537     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6538     if(shCount != 0){
6539         if(shCount == 1){
6540             pic16_emitcode("mov","c,acc.7");
6541             pic16_emitcode("rrc","a");
6542         } else if(shCount == 2){
6543             pic16_emitcode("mov","c,acc.7");
6544             pic16_emitcode("rrc","a");
6545             pic16_emitcode("mov","c,acc.7");
6546             pic16_emitcode("rrc","a");
6547         } else {
6548             tlbl = newiTempLabel(NULL);
6549             /* rotate right accumulator */
6550             AccRol(8 - shCount);
6551             /* and kill the higher order bits */
6552             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6553             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6554             pic16_emitcode("orl","a,#0x%02x",
6555                      (unsigned char)~SRMask[shCount]);
6556             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6557         }
6558     }
6559 }
6560 #endif
6561 /*-----------------------------------------------------------------*/
6562 /* shiftR1Left2Result - shift right one byte from left to result   */
6563 /*-----------------------------------------------------------------*/
6564 static void shiftR1Left2ResultSigned (operand *left, int offl,
6565                                 operand *result, int offr,
6566                                 int shCount)
6567 {
6568   int same;
6569
6570   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6571
6572   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6573
6574   switch(shCount) {
6575   case 1:
6576     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6577     if(same) 
6578       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6579     else {
6580       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6581       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6582     }
6583
6584     break;
6585   case 2:
6586
6587     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6588     if(same) 
6589       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6590     else {
6591       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6592       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6593     }
6594     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6595     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6596
6597     break;
6598
6599   case 3:
6600     if(same)
6601       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6602     else {
6603       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6604       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6605     }
6606
6607     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6608     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6609     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6610
6611     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6612     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6613
6614     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6615     break;
6616
6617   case 4:
6618     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6619     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6620     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6621     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6622     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6623     break;
6624   case 5:
6625     if(same) {
6626       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6627     } else {
6628       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6629       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6630     }
6631     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6632     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6633     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6634     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6635     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6636     break;
6637
6638   case 6:
6639     if(same) {
6640       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6641       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6642       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6643       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6644       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6646     } else {
6647       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6648       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6649       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6650       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6651       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6652     }
6653     break;
6654
6655   case 7:
6656     if(same) {
6657       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6658       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6659       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6660       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6661     } else {
6662       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6663       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6664       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6665     }
6666
6667   default:
6668     break;
6669   }
6670 }
6671
6672 /*-----------------------------------------------------------------*/
6673 /* shiftR1Left2Result - shift right one byte from left to result   */
6674 /*-----------------------------------------------------------------*/
6675 static void shiftR1Left2Result (operand *left, int offl,
6676                                 operand *result, int offr,
6677                                 int shCount, int sign)
6678 {
6679   int same;
6680
6681   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6682
6683   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6684
6685   /* Copy the msb into the carry if signed. */
6686   if(sign) {
6687     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6688     return;
6689   }
6690
6691
6692
6693   switch(shCount) {
6694   case 1:
6695     emitCLRC;
6696     if(same) 
6697       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6698     else {
6699       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6700       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6701     }
6702     break;
6703   case 2:
6704     emitCLRC;
6705     if(same) {
6706       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6707     } else {
6708       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6710     }
6711     emitCLRC;
6712     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6713
6714     break;
6715   case 3:
6716     if(same)
6717       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6718     else {
6719       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6720       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6721     }
6722
6723     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6724     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6725     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6726     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6727     break;
6728       
6729   case 4:
6730     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6731     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6732     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6733     break;
6734
6735   case 5:
6736     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6737     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6738     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6739     emitCLRC;
6740     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6741
6742     break;
6743   case 6:
6744
6745     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6746     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6747     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6748     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6749     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6750     break;
6751
6752   case 7:
6753
6754     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6755     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6756     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6757
6758     break;
6759
6760   default:
6761     break;
6762   }
6763 }
6764
6765 /*-----------------------------------------------------------------*/
6766 /* shiftL1Left2Result - shift left one byte from left to result    */
6767 /*-----------------------------------------------------------------*/
6768 static void shiftL1Left2Result (operand *left, int offl,
6769                                 operand *result, int offr, int shCount)
6770 {
6771   int same;
6772
6773   //    char *l;
6774   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6775
6776   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6777   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6778     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6779     //    MOVA(l);
6780     /* shift left accumulator */
6781     //AccLsh(shCount); // don't comment out just yet...
6782   //    pic16_aopPut(AOP(result),"a",offr);
6783
6784   switch(shCount) {
6785   case 1:
6786     /* Shift left 1 bit position */
6787     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6788     if(same) {
6789       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6790     } else {
6791       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6792       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6793     }
6794     break;
6795   case 2:
6796     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6797     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6798     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6799     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6800     break;
6801   case 3:
6802     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6803     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6804     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6805     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6806     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6807     break;
6808   case 4:
6809     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6810     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6811     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6812     break;
6813   case 5:
6814     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6815     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6816     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6817     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6818     break;
6819   case 6:
6820     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6821     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6822     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6823     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6824     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6825     break;
6826   case 7:
6827     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6828     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6829     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6830     break;
6831
6832   default:
6833     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6834   }
6835
6836 }
6837
6838 /*-----------------------------------------------------------------*/
6839 /* movLeft2Result - move byte from left to result                  */
6840 /*-----------------------------------------------------------------*/
6841 static void movLeft2Result (operand *left, int offl,
6842                             operand *result, int offr)
6843 {
6844   char *l;
6845   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6846   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6847     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6848
6849     if (*l == '@' && (IS_AOP_PREG(result))) {
6850       pic16_emitcode("mov","a,%s",l);
6851       pic16_aopPut(AOP(result),"a",offr);
6852     } else {
6853       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6854       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6855     }
6856   }
6857 }
6858
6859 /*-----------------------------------------------------------------*/
6860 /* shiftL2Left2Result - shift left two bytes from left to result   */
6861 /*-----------------------------------------------------------------*/
6862 static void shiftL2Left2Result (operand *left, int offl,
6863                                 operand *result, int offr, int shCount)
6864 {
6865
6866
6867   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6868
6869   if(pic16_sameRegs(AOP(result), AOP(left))) {
6870     switch(shCount) {
6871     case 0:
6872       break;
6873     case 1:
6874     case 2:
6875     case 3:
6876
6877       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6878       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6879       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6880
6881       while(--shCount) {
6882         emitCLRC;
6883         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6884         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6885       }
6886
6887       break;
6888     case 4:
6889     case 5:
6890       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6891       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6892       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6893       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6894       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6895       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6896       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6897       if(shCount >=5) {
6898         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6899         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6900       }
6901       break;
6902     case 6:
6903       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6904       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6905       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6906       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6907       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6908       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6909       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6910       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6911       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6912       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6913       break;
6914     case 7:
6915       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6916       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6917       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6918       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6919       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6920     }
6921
6922   } else {
6923     switch(shCount) {
6924     case 0:
6925       break;
6926     case 1:
6927     case 2:
6928     case 3:
6929       /* note, use a mov/add for the shift since the mov has a
6930          chance of getting optimized out */
6931       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6932       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6933       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6934       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6935       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6936
6937       while(--shCount) {
6938         emitCLRC;
6939         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6940         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6941       }
6942       break;
6943
6944     case 4:
6945     case 5:
6946       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6947       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6948       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6949       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6950       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6951       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6952       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6953       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6954
6955
6956       if(shCount == 5) {
6957         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6958         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6959       }
6960       break;
6961     case 6:
6962       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6963       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6964       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6965       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6966
6967       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6968       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6969       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6970       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6971       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6972       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6973       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6974       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6975       break;
6976     case 7:
6977       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6979       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6980       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6981       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6982     }
6983   }
6984
6985 }
6986 /*-----------------------------------------------------------------*/
6987 /* shiftR2Left2Result - shift right two bytes from left to result  */
6988 /*-----------------------------------------------------------------*/
6989 static void shiftR2Left2Result (operand *left, int offl,
6990                                 operand *result, int offr,
6991                                 int shCount, int sign)
6992 {
6993   int same=0;
6994
6995   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6996   same = pic16_sameRegs(AOP(result), AOP(left));
6997
6998   if(same && ((offl + MSB16) == offr)){
6999     same=1;
7000     /* don't crash result[offr] */
7001     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7002     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7003   }
7004 /* else {
7005     movLeft2Result(left,offl, result, offr);
7006     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7007   }
7008 */
7009   /* a:x >> shCount (x = lsb(result))*/
7010 /*
7011   if(sign)
7012     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7013   else {
7014     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7015 */
7016   switch(shCount) {
7017   case 0:
7018     break;
7019   case 1:
7020   case 2:
7021   case 3:
7022     if(sign)
7023       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7024     else
7025       emitCLRC;
7026
7027     if(same) {
7028       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7029       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7030     } else {
7031       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7032       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7033       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7035     }
7036
7037     while(--shCount) {
7038       if(sign)
7039         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7040       else
7041         emitCLRC;
7042       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7043       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7044     }
7045     break;
7046   case 4:
7047   case 5:
7048     if(same) {
7049
7050       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7051       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7052       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7053
7054       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7055       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7056       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7057       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7058     } else {
7059       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7060       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7061       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7062
7063       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7064       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7065       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7066       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7067       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7068     }
7069
7070     if(shCount >=5) {
7071       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7072       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7073     }
7074
7075     if(sign) {
7076       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7077       pic16_emitpcode(POC_BTFSC, 
7078                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7079       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7080     }
7081
7082     break;
7083
7084   case 6:
7085     if(same) {
7086
7087       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7088       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7089
7090       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7091       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7092       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7093       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7094       if(sign) {
7095         pic16_emitpcode(POC_BTFSC, 
7096                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7097         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7098       }
7099       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7100       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7101       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7102       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7103     } else {
7104       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7105       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7106       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7107       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7108       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7109       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7110       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7111       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7112       if(sign) {
7113         pic16_emitpcode(POC_BTFSC, 
7114                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7115         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7116       }
7117       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7118       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7119
7120         
7121     }
7122
7123     break;
7124   case 7:
7125     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7126     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7127     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7128     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7129     if(sign) {
7130       emitSKPNC;
7131       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7132     } else 
7133       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7134   }
7135 }
7136
7137
7138 /*-----------------------------------------------------------------*/
7139 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7140 /*-----------------------------------------------------------------*/
7141 static void shiftLLeftOrResult (operand *left, int offl,
7142                                 operand *result, int offr, int shCount)
7143 {
7144     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7145     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7146     /* shift left accumulator */
7147     AccLsh(shCount);
7148     /* or with result */
7149     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
7150     /* back to result */
7151     pic16_aopPut(AOP(result),"a",offr);
7152 }
7153
7154 /*-----------------------------------------------------------------*/
7155 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7156 /*-----------------------------------------------------------------*/
7157 static void shiftRLeftOrResult (operand *left, int offl,
7158                                 operand *result, int offr, int shCount)
7159 {
7160     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7161     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7162     /* shift right accumulator */
7163     AccRsh(shCount);
7164     /* or with result */
7165     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
7166     /* back to result */
7167     pic16_aopPut(AOP(result),"a",offr);
7168 }
7169
7170 /*-----------------------------------------------------------------*/
7171 /* genlshOne - left shift a one byte quantity by known count       */
7172 /*-----------------------------------------------------------------*/
7173 static void genlshOne (operand *result, operand *left, int shCount)
7174 {       
7175     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7176     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7177 }
7178
7179 /*-----------------------------------------------------------------*/
7180 /* genlshTwo - left shift two bytes by known amount != 0           */
7181 /*-----------------------------------------------------------------*/
7182 static void genlshTwo (operand *result,operand *left, int shCount)
7183 {
7184     int size;
7185     
7186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7187     size = pic16_getDataSize(result);
7188
7189     /* if shCount >= 8 */
7190     if (shCount >= 8) {
7191         shCount -= 8 ;
7192
7193         if (size > 1){
7194             if (shCount)
7195                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7196             else 
7197                 movLeft2Result(left, LSB, result, MSB16);
7198         }
7199         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7200     }
7201
7202     /*  1 <= shCount <= 7 */
7203     else {  
7204         if(size == 1)
7205             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7206         else 
7207             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7208     }
7209 }
7210
7211 /*-----------------------------------------------------------------*/
7212 /* shiftLLong - shift left one long from left to result            */
7213 /* offl = LSB or MSB16                                             */
7214 /*-----------------------------------------------------------------*/
7215 static void shiftLLong (operand *left, operand *result, int offr )
7216 {
7217     char *l;
7218     int size = AOP_SIZE(result);
7219
7220     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7221     if(size >= LSB+offr){
7222         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7223         MOVA(l);
7224         pic16_emitcode("add","a,acc");
7225         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7226             size >= MSB16+offr && offr != LSB )
7227             pic16_emitcode("xch","a,%s",
7228                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7229         else        
7230             pic16_aopPut(AOP(result),"a",LSB+offr);
7231     }
7232
7233     if(size >= MSB16+offr){
7234         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7235             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7236             MOVA(l);
7237         }
7238         pic16_emitcode("rlc","a");
7239         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7240             size >= MSB24+offr && offr != LSB)
7241             pic16_emitcode("xch","a,%s",
7242                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7243         else        
7244             pic16_aopPut(AOP(result),"a",MSB16+offr);
7245     }
7246
7247     if(size >= MSB24+offr){
7248         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7249             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7250             MOVA(l);
7251         }
7252         pic16_emitcode("rlc","a");
7253         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7254             size >= MSB32+offr && offr != LSB )
7255             pic16_emitcode("xch","a,%s",
7256                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7257         else        
7258             pic16_aopPut(AOP(result),"a",MSB24+offr);
7259     }
7260
7261     if(size > MSB32+offr){
7262         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7263             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7264             MOVA(l);    
7265         }
7266         pic16_emitcode("rlc","a");
7267         pic16_aopPut(AOP(result),"a",MSB32+offr);
7268     }
7269     if(offr != LSB)
7270         pic16_aopPut(AOP(result),zero,LSB);       
7271 }
7272
7273 /*-----------------------------------------------------------------*/
7274 /* genlshFour - shift four byte by a known amount != 0             */
7275 /*-----------------------------------------------------------------*/
7276 static void genlshFour (operand *result, operand *left, int shCount)
7277 {
7278     int size;
7279
7280     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7281     size = AOP_SIZE(result);
7282
7283     /* if shifting more that 3 bytes */
7284     if (shCount >= 24 ) {
7285         shCount -= 24;
7286         if (shCount)
7287             /* lowest order of left goes to the highest
7288             order of the destination */
7289             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7290         else
7291             movLeft2Result(left, LSB, result, MSB32);
7292         pic16_aopPut(AOP(result),zero,LSB);
7293         pic16_aopPut(AOP(result),zero,MSB16);
7294         pic16_aopPut(AOP(result),zero,MSB32);
7295         return;
7296     }
7297
7298     /* more than two bytes */
7299     else if ( shCount >= 16 ) {
7300         /* lower order two bytes goes to higher order two bytes */
7301         shCount -= 16;
7302         /* if some more remaining */
7303         if (shCount)
7304             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7305         else {
7306             movLeft2Result(left, MSB16, result, MSB32);
7307             movLeft2Result(left, LSB, result, MSB24);
7308         }
7309         pic16_aopPut(AOP(result),zero,MSB16);
7310         pic16_aopPut(AOP(result),zero,LSB);
7311         return;
7312     }    
7313
7314     /* if more than 1 byte */
7315     else if ( shCount >= 8 ) {
7316         /* lower order three bytes goes to higher order  three bytes */
7317         shCount -= 8;
7318         if(size == 2){
7319             if(shCount)
7320                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7321             else
7322                 movLeft2Result(left, LSB, result, MSB16);
7323         }
7324         else{   /* size = 4 */
7325             if(shCount == 0){
7326                 movLeft2Result(left, MSB24, result, MSB32);
7327                 movLeft2Result(left, MSB16, result, MSB24);
7328                 movLeft2Result(left, LSB, result, MSB16);
7329                 pic16_aopPut(AOP(result),zero,LSB);
7330             }
7331             else if(shCount == 1)
7332                 shiftLLong(left, result, MSB16);
7333             else{
7334                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7335                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7336                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7337                 pic16_aopPut(AOP(result),zero,LSB);
7338             }
7339         }
7340     }
7341
7342     /* 1 <= shCount <= 7 */
7343     else if(shCount <= 2){
7344         shiftLLong(left, result, LSB);
7345         if(shCount == 2)
7346             shiftLLong(result, result, LSB);
7347     }
7348     /* 3 <= shCount <= 7, optimize */
7349     else{
7350         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7351         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7352         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7353     }
7354 }
7355
7356 /*-----------------------------------------------------------------*/
7357 /* genLeftShiftLiteral - left shifting by known count              */
7358 /*-----------------------------------------------------------------*/
7359 static void genLeftShiftLiteral (operand *left,
7360                                  operand *right,
7361                                  operand *result,
7362                                  iCode *ic)
7363 {    
7364     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7365     int size;
7366
7367     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7368     pic16_freeAsmop(right,NULL,ic,TRUE);
7369
7370     pic16_aopOp(left,ic,FALSE);
7371     pic16_aopOp(result,ic,FALSE);
7372
7373     size = getSize(operandType(result));
7374
7375 #if VIEW_SIZE
7376     pic16_emitcode("; shift left ","result %d, left %d",size,
7377              AOP_SIZE(left));
7378 #endif
7379
7380     /* I suppose that the left size >= result size */
7381     if(shCount == 0){
7382         while(size--){
7383             movLeft2Result(left, size, result, size);
7384         }
7385     }
7386
7387     else if(shCount >= (size * 8))
7388         while(size--)
7389             pic16_aopPut(AOP(result),zero,size);
7390     else{
7391         switch (size) {
7392             case 1:
7393                 genlshOne (result,left,shCount);
7394                 break;
7395
7396             case 2:
7397             case 3:
7398                 genlshTwo (result,left,shCount);
7399                 break;
7400
7401             case 4:
7402                 genlshFour (result,left,shCount);
7403                 break;
7404         }
7405     }
7406     pic16_freeAsmop(left,NULL,ic,TRUE);
7407     pic16_freeAsmop(result,NULL,ic,TRUE);
7408 }
7409
7410 /*-----------------------------------------------------------------*
7411  * genMultiAsm - repeat assembly instruction for size of register.
7412  * if endian == 1, then the high byte (i.e base address + size of 
7413  * register) is used first else the low byte is used first;
7414  *-----------------------------------------------------------------*/
7415 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7416 {
7417
7418   int offset = 0;
7419
7420   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7421
7422   if(!reg)
7423     return;
7424
7425   if(!endian) {
7426     endian = 1;
7427   } else {
7428     endian = -1;
7429     offset = size-1;
7430   }
7431
7432   while(size--) {
7433     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7434     offset += endian;
7435   }
7436
7437 }
7438 /*-----------------------------------------------------------------*/
7439 /* genLeftShift - generates code for left shifting                 */
7440 /*-----------------------------------------------------------------*/
7441 static void genLeftShift (iCode *ic)
7442 {
7443   operand *left,*right, *result;
7444   int size, offset;
7445   char *l;
7446   symbol *tlbl , *tlbl1;
7447   pCodeOp *pctemp;
7448
7449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7450
7451   right = IC_RIGHT(ic);
7452   left  = IC_LEFT(ic);
7453   result = IC_RESULT(ic);
7454
7455   pic16_aopOp(right,ic,FALSE);
7456
7457   /* if the shift count is known then do it 
7458      as efficiently as possible */
7459   if (AOP_TYPE(right) == AOP_LIT) {
7460     genLeftShiftLiteral (left,right,result,ic);
7461     return ;
7462   }
7463
7464   /* shift count is unknown then we have to form 
7465      a loop get the loop count in B : Note: we take
7466      only the lower order byte since shifting
7467      more that 32 bits make no sense anyway, ( the
7468      largest size of an object can be only 32 bits ) */  
7469
7470     
7471   pic16_aopOp(left,ic,FALSE);
7472   pic16_aopOp(result,ic,FALSE);
7473
7474   /* now move the left to the result if they are not the
7475      same */
7476   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7477       AOP_SIZE(result) > 1) {
7478
7479     size = AOP_SIZE(result);
7480     offset=0;
7481     while (size--) {
7482       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7483       if (*l == '@' && (IS_AOP_PREG(result))) {
7484
7485         pic16_emitcode("mov","a,%s",l);
7486         pic16_aopPut(AOP(result),"a",offset);
7487       } else {
7488         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7489         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7490         //pic16_aopPut(AOP(result),l,offset);
7491       }
7492       offset++;
7493     }
7494   }
7495
7496   size = AOP_SIZE(result);
7497
7498   /* if it is only one byte then */
7499   if (size == 1) {
7500     if(optimized_for_speed) {
7501       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7502       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7503       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7504       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7505       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7506       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7507       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7508       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7509       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7510       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7511       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7512       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7513     } else {
7514
7515       tlbl = newiTempLabel(NULL);
7516       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7517         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7518         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7519       }
7520
7521       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7522       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7523       pic16_emitpLabel(tlbl->key);
7524       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7525       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7526       emitSKPC;
7527       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7528     }
7529     goto release ;
7530   }
7531     
7532   if (pic16_sameRegs(AOP(left),AOP(result))) {
7533
7534     tlbl = newiTempLabel(NULL);
7535     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7536     genMultiAsm(POC_RRCF, result, size,1);
7537     pic16_emitpLabel(tlbl->key);
7538     genMultiAsm(POC_RLCF, result, size,0);
7539     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7540     emitSKPC;
7541     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7542     goto release;
7543   }
7544
7545   //tlbl = newiTempLabel(NULL);
7546   //offset = 0 ;   
7547   //tlbl1 = newiTempLabel(NULL);
7548
7549   //reAdjustPreg(AOP(result));    
7550     
7551   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7552   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7553   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7554   //MOVA(l);
7555   //pic16_emitcode("add","a,acc");         
7556   //pic16_aopPut(AOP(result),"a",offset++);
7557   //while (--size) {
7558   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7559   //  MOVA(l);
7560   //  pic16_emitcode("rlc","a");         
7561   //  pic16_aopPut(AOP(result),"a",offset++);
7562   //}
7563   //reAdjustPreg(AOP(result));
7564
7565   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7566   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7567
7568
7569   tlbl = newiTempLabel(NULL);
7570   tlbl1= newiTempLabel(NULL);
7571
7572   size = AOP_SIZE(result);
7573   offset = 1;
7574
7575   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7576
7577   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7578
7579   /* offset should be 0, 1 or 3 */
7580   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7581   emitSKPNZ;
7582   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7583
7584   pic16_emitpcode(POC_MOVWF, pctemp);
7585
7586
7587   pic16_emitpLabel(tlbl->key);
7588
7589   emitCLRC;
7590   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7591   while(--size)
7592     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7593
7594   pic16_emitpcode(POC_DECFSZ,  pctemp);
7595   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7596   pic16_emitpLabel(tlbl1->key);
7597
7598   pic16_popReleaseTempReg(pctemp);
7599
7600
7601  release:
7602   pic16_freeAsmop (right,NULL,ic,TRUE);
7603   pic16_freeAsmop(left,NULL,ic,TRUE);
7604   pic16_freeAsmop(result,NULL,ic,TRUE);
7605 }
7606
7607 /*-----------------------------------------------------------------*/
7608 /* genrshOne - right shift a one byte quantity by known count      */
7609 /*-----------------------------------------------------------------*/
7610 static void genrshOne (operand *result, operand *left,
7611                        int shCount, int sign)
7612 {
7613     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7614     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7615 }
7616
7617 /*-----------------------------------------------------------------*/
7618 /* genrshTwo - right shift two bytes by known amount != 0          */
7619 /*-----------------------------------------------------------------*/
7620 static void genrshTwo (operand *result,operand *left,
7621                        int shCount, int sign)
7622 {
7623   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7624   /* if shCount >= 8 */
7625   if (shCount >= 8) {
7626     shCount -= 8 ;
7627     if (shCount)
7628       shiftR1Left2Result(left, MSB16, result, LSB,
7629                          shCount, sign);
7630     else
7631       movLeft2Result(left, MSB16, result, LSB);
7632
7633     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7634
7635     if(sign) {
7636       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7637       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7638     }
7639   }
7640
7641   /*  1 <= shCount <= 7 */
7642   else
7643     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7644 }
7645
7646 /*-----------------------------------------------------------------*/
7647 /* shiftRLong - shift right one long from left to result           */
7648 /* offl = LSB or MSB16                                             */
7649 /*-----------------------------------------------------------------*/
7650 static void shiftRLong (operand *left, int offl,
7651                         operand *result, int sign)
7652 {
7653     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7654     if(!sign)
7655         pic16_emitcode("clr","c");
7656     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7657     if(sign)
7658         pic16_emitcode("mov","c,acc.7");
7659     pic16_emitcode("rrc","a");
7660     pic16_aopPut(AOP(result),"a",MSB32-offl);
7661     if(offl == MSB16)
7662         /* add sign of "a" */
7663         pic16_addSign(result, MSB32, sign);
7664
7665     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7666     pic16_emitcode("rrc","a");
7667     pic16_aopPut(AOP(result),"a",MSB24-offl);
7668
7669     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7670     pic16_emitcode("rrc","a");
7671     pic16_aopPut(AOP(result),"a",MSB16-offl);
7672
7673     if(offl == LSB){
7674         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7675         pic16_emitcode("rrc","a");
7676         pic16_aopPut(AOP(result),"a",LSB);
7677     }
7678 }
7679
7680 /*-----------------------------------------------------------------*/
7681 /* genrshFour - shift four byte by a known amount != 0             */
7682 /*-----------------------------------------------------------------*/
7683 static void genrshFour (operand *result, operand *left,
7684                         int shCount, int sign)
7685 {
7686   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7687   /* if shifting more that 3 bytes */
7688   if(shCount >= 24 ) {
7689     shCount -= 24;
7690     if(shCount)
7691       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7692     else
7693       movLeft2Result(left, MSB32, result, LSB);
7694
7695     pic16_addSign(result, MSB16, sign);
7696   }
7697   else if(shCount >= 16){
7698     shCount -= 16;
7699     if(shCount)
7700       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7701     else{
7702       movLeft2Result(left, MSB24, result, LSB);
7703       movLeft2Result(left, MSB32, result, MSB16);
7704     }
7705     pic16_addSign(result, MSB24, sign);
7706   }
7707   else if(shCount >= 8){
7708     shCount -= 8;
7709     if(shCount == 1)
7710       shiftRLong(left, MSB16, result, sign);
7711     else if(shCount == 0){
7712       movLeft2Result(left, MSB16, result, LSB);
7713       movLeft2Result(left, MSB24, result, MSB16);
7714       movLeft2Result(left, MSB32, result, MSB24);
7715       pic16_addSign(result, MSB32, sign);
7716     }
7717     else{
7718       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7719       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7720       /* the last shift is signed */
7721       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7722       pic16_addSign(result, MSB32, sign);
7723     }
7724   }
7725   else{   /* 1 <= shCount <= 7 */
7726     if(shCount <= 2){
7727       shiftRLong(left, LSB, result, sign);
7728       if(shCount == 2)
7729         shiftRLong(result, LSB, result, sign);
7730     }
7731     else{
7732       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7733       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7734       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7735     }
7736   }
7737 }
7738
7739 /*-----------------------------------------------------------------*/
7740 /* genRightShiftLiteral - right shifting by known count            */
7741 /*-----------------------------------------------------------------*/
7742 static void genRightShiftLiteral (operand *left,
7743                                   operand *right,
7744                                   operand *result,
7745                                   iCode *ic,
7746                                   int sign)
7747 {    
7748   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7749   int lsize,res_size;
7750
7751   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7752   pic16_freeAsmop(right,NULL,ic,TRUE);
7753
7754   pic16_aopOp(left,ic,FALSE);
7755   pic16_aopOp(result,ic,FALSE);
7756
7757 #if VIEW_SIZE
7758   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7759                  AOP_SIZE(left));
7760 #endif
7761
7762   lsize = pic16_getDataSize(left);
7763   res_size = pic16_getDataSize(result);
7764   /* test the LEFT size !!! */
7765
7766   /* I suppose that the left size >= result size */
7767   if(shCount == 0){
7768     while(res_size--)
7769       movLeft2Result(left, lsize, result, res_size);
7770   }
7771
7772   else if(shCount >= (lsize * 8)){
7773
7774     if(res_size == 1) {
7775       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7776       if(sign) {
7777         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7778         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7779       }
7780     } else {
7781
7782       if(sign) {
7783         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7784         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7785         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7786         while(res_size--)
7787           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7788
7789       } else {
7790
7791         while(res_size--)
7792           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7793       }
7794     }
7795   } else {
7796
7797     switch (res_size) {
7798     case 1:
7799       genrshOne (result,left,shCount,sign);
7800       break;
7801
7802     case 2:
7803       genrshTwo (result,left,shCount,sign);
7804       break;
7805
7806     case 4:
7807       genrshFour (result,left,shCount,sign);
7808       break;
7809     default :
7810       break;
7811     }
7812
7813   }
7814
7815   pic16_freeAsmop(left,NULL,ic,TRUE);
7816   pic16_freeAsmop(result,NULL,ic,TRUE);
7817 }
7818
7819 /*-----------------------------------------------------------------*/
7820 /* genSignedRightShift - right shift of signed number              */
7821 /*-----------------------------------------------------------------*/
7822 static void genSignedRightShift (iCode *ic)
7823 {
7824   operand *right, *left, *result;
7825   int size, offset;
7826   //  char *l;
7827   symbol *tlbl, *tlbl1 ;
7828   pCodeOp *pctemp;
7829
7830   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7831
7832   /* we do it the hard way put the shift count in b
7833      and loop thru preserving the sign */
7834   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7835
7836   right = IC_RIGHT(ic);
7837   left  = IC_LEFT(ic);
7838   result = IC_RESULT(ic);
7839
7840   pic16_aopOp(right,ic,FALSE);  
7841   pic16_aopOp(left,ic,FALSE);
7842   pic16_aopOp(result,ic,FALSE);
7843
7844
7845   if ( AOP_TYPE(right) == AOP_LIT) {
7846     genRightShiftLiteral (left,right,result,ic,1);
7847     return ;
7848   }
7849   /* shift count is unknown then we have to form 
7850      a loop get the loop count in B : Note: we take
7851      only the lower order byte since shifting
7852      more that 32 bits make no sense anyway, ( the
7853      largest size of an object can be only 32 bits ) */  
7854
7855   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7856   //pic16_emitcode("inc","b");
7857   //pic16_freeAsmop (right,NULL,ic,TRUE);
7858   //pic16_aopOp(left,ic,FALSE);
7859   //pic16_aopOp(result,ic,FALSE);
7860
7861   /* now move the left to the result if they are not the
7862      same */
7863   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7864       AOP_SIZE(result) > 1) {
7865
7866     size = AOP_SIZE(result);
7867     offset=0;
7868     while (size--) { 
7869       /*
7870         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7871         if (*l == '@' && IS_AOP_PREG(result)) {
7872
7873         pic16_emitcode("mov","a,%s",l);
7874         pic16_aopPut(AOP(result),"a",offset);
7875         } else
7876         pic16_aopPut(AOP(result),l,offset);
7877       */
7878       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7879       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7880
7881       offset++;
7882     }
7883   }
7884
7885   /* mov the highest order bit to OVR */    
7886   tlbl = newiTempLabel(NULL);
7887   tlbl1= newiTempLabel(NULL);
7888
7889   size = AOP_SIZE(result);
7890   offset = size - 1;
7891
7892   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7893
7894   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7895
7896   /* offset should be 0, 1 or 3 */
7897   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7898   emitSKPNZ;
7899   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7900
7901   pic16_emitpcode(POC_MOVWF, pctemp);
7902
7903
7904   pic16_emitpLabel(tlbl->key);
7905
7906   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7907   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7908
7909   while(--size) {
7910     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7911   }
7912
7913   pic16_emitpcode(POC_DECFSZ,  pctemp);
7914   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7915   pic16_emitpLabel(tlbl1->key);
7916
7917   pic16_popReleaseTempReg(pctemp);
7918 #if 0
7919   size = AOP_SIZE(result);
7920   offset = size - 1;
7921   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7922   pic16_emitcode("rlc","a");
7923   pic16_emitcode("mov","ov,c");
7924   /* if it is only one byte then */
7925   if (size == 1) {
7926     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7927     MOVA(l);
7928     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7929     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7930     pic16_emitcode("mov","c,ov");
7931     pic16_emitcode("rrc","a");
7932     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7933     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7934     pic16_aopPut(AOP(result),"a",0);
7935     goto release ;
7936   }
7937
7938   reAdjustPreg(AOP(result));
7939   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7940   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7941   pic16_emitcode("mov","c,ov");
7942   while (size--) {
7943     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7944     MOVA(l);
7945     pic16_emitcode("rrc","a");         
7946     pic16_aopPut(AOP(result),"a",offset--);
7947   }
7948   reAdjustPreg(AOP(result));
7949   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7950   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7951
7952  release:
7953 #endif
7954
7955   pic16_freeAsmop(left,NULL,ic,TRUE);
7956   pic16_freeAsmop(result,NULL,ic,TRUE);
7957   pic16_freeAsmop(right,NULL,ic,TRUE);
7958 }
7959
7960 /*-----------------------------------------------------------------*/
7961 /* genRightShift - generate code for right shifting                */
7962 /*-----------------------------------------------------------------*/
7963 static void genRightShift (iCode *ic)
7964 {
7965     operand *right, *left, *result;
7966     sym_link *retype ;
7967     int size, offset;
7968     char *l;
7969     symbol *tlbl, *tlbl1 ;
7970
7971     /* if signed then we do it the hard way preserve the
7972     sign bit moving it inwards */
7973     retype = getSpec(operandType(IC_RESULT(ic)));
7974     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7975
7976     if (!SPEC_USIGN(retype)) {
7977         genSignedRightShift (ic);
7978         return ;
7979     }
7980
7981     /* signed & unsigned types are treated the same : i.e. the
7982     signed is NOT propagated inwards : quoting from the
7983     ANSI - standard : "for E1 >> E2, is equivalent to division
7984     by 2**E2 if unsigned or if it has a non-negative value,
7985     otherwise the result is implementation defined ", MY definition
7986     is that the sign does not get propagated */
7987
7988     right = IC_RIGHT(ic);
7989     left  = IC_LEFT(ic);
7990     result = IC_RESULT(ic);
7991
7992     pic16_aopOp(right,ic,FALSE);
7993
7994     /* if the shift count is known then do it 
7995     as efficiently as possible */
7996     if (AOP_TYPE(right) == AOP_LIT) {
7997         genRightShiftLiteral (left,right,result,ic, 0);
7998         return ;
7999     }
8000
8001     /* shift count is unknown then we have to form 
8002     a loop get the loop count in B : Note: we take
8003     only the lower order byte since shifting
8004     more that 32 bits make no sense anyway, ( the
8005     largest size of an object can be only 32 bits ) */  
8006
8007     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8008     pic16_emitcode("inc","b");
8009     pic16_aopOp(left,ic,FALSE);
8010     pic16_aopOp(result,ic,FALSE);
8011
8012     /* now move the left to the result if they are not the
8013     same */
8014     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8015         AOP_SIZE(result) > 1) {
8016
8017         size = AOP_SIZE(result);
8018         offset=0;
8019         while (size--) {
8020             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8021             if (*l == '@' && IS_AOP_PREG(result)) {
8022
8023                 pic16_emitcode("mov","a,%s",l);
8024                 pic16_aopPut(AOP(result),"a",offset);
8025             } else
8026                 pic16_aopPut(AOP(result),l,offset);
8027             offset++;
8028         }
8029     }
8030
8031     tlbl = newiTempLabel(NULL);
8032     tlbl1= newiTempLabel(NULL);
8033     size = AOP_SIZE(result);
8034     offset = size - 1;
8035
8036     /* if it is only one byte then */
8037     if (size == 1) {
8038
8039       tlbl = newiTempLabel(NULL);
8040       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8041         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8042         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8043       }
8044
8045       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8046       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8047       pic16_emitpLabel(tlbl->key);
8048       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8049       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8050       emitSKPC;
8051       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8052
8053       goto release ;
8054     }
8055
8056     reAdjustPreg(AOP(result));
8057     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8058     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8059     CLRC;
8060     while (size--) {
8061         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8062         MOVA(l);
8063         pic16_emitcode("rrc","a");         
8064         pic16_aopPut(AOP(result),"a",offset--);
8065     }
8066     reAdjustPreg(AOP(result));
8067
8068     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8069     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8070
8071 release:
8072     pic16_freeAsmop(left,NULL,ic,TRUE);
8073     pic16_freeAsmop (right,NULL,ic,TRUE);
8074     pic16_freeAsmop(result,NULL,ic,TRUE);
8075 }
8076
8077 /*-----------------------------------------------------------------*/
8078 /* genUnpackBits - generates code for unpacking bits               */
8079 /*-----------------------------------------------------------------*/
8080 static void genUnpackBits (operand *result, char *rname, int ptype)
8081 {    
8082     int shCnt ;
8083     int rlen = 0 ;
8084     sym_link *etype;
8085     int offset = 0 ;
8086
8087     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8088     etype = getSpec(operandType(result));
8089
8090     /* read the first byte  */
8091     switch (ptype) {
8092
8093     case POINTER:
8094     case IPOINTER:
8095         pic16_emitcode("mov","a,@%s",rname);
8096         break;
8097         
8098     case PPOINTER:
8099         pic16_emitcode("movx","a,@%s",rname);
8100         break;
8101         
8102     case FPOINTER:
8103         pic16_emitcode("movx","a,@dptr");
8104         break;
8105
8106     case CPOINTER:
8107         pic16_emitcode("clr","a");
8108         pic16_emitcode("movc","a","@a+dptr");
8109         break;
8110
8111     case GPOINTER:
8112         pic16_emitcode("lcall","__gptrget");
8113         break;
8114     }
8115
8116     /* if we have bitdisplacement then it fits   */
8117     /* into this byte completely or if length is */
8118     /* less than a byte                          */
8119     if ((shCnt = SPEC_BSTR(etype)) || 
8120         (SPEC_BLEN(etype) <= 8))  {
8121
8122         /* shift right acc */
8123         AccRsh(shCnt);
8124
8125         pic16_emitcode("anl","a,#0x%02x",
8126                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8127         pic16_aopPut(AOP(result),"a",offset);
8128         return ;
8129     }
8130
8131     /* bit field did not fit in a byte  */
8132     rlen = SPEC_BLEN(etype) - 8;
8133     pic16_aopPut(AOP(result),"a",offset++);
8134
8135     while (1)  {
8136
8137         switch (ptype) {
8138         case POINTER:
8139         case IPOINTER:
8140             pic16_emitcode("inc","%s",rname);
8141             pic16_emitcode("mov","a,@%s",rname);
8142             break;
8143             
8144         case PPOINTER:
8145             pic16_emitcode("inc","%s",rname);
8146             pic16_emitcode("movx","a,@%s",rname);
8147             break;
8148
8149         case FPOINTER:
8150             pic16_emitcode("inc","dptr");
8151             pic16_emitcode("movx","a,@dptr");
8152             break;
8153             
8154         case CPOINTER:
8155             pic16_emitcode("clr","a");
8156             pic16_emitcode("inc","dptr");
8157             pic16_emitcode("movc","a","@a+dptr");
8158             break;
8159             
8160         case GPOINTER:
8161             pic16_emitcode("inc","dptr");
8162             pic16_emitcode("lcall","__gptrget");
8163             break;
8164         }
8165
8166         rlen -= 8;            
8167         /* if we are done */
8168         if ( rlen <= 0 )
8169             break ;
8170         
8171         pic16_aopPut(AOP(result),"a",offset++);
8172                               
8173     }
8174     
8175     if (rlen) {
8176         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8177         pic16_aopPut(AOP(result),"a",offset);          
8178     }
8179     
8180     return ;
8181 }
8182
8183 #if 0
8184 /*-----------------------------------------------------------------*/
8185 /* genDataPointerGet - generates code when ptr offset is known     */
8186 /*-----------------------------------------------------------------*/
8187 static void genDataPointerGet (operand *left, 
8188                                operand *result, 
8189                                iCode *ic)
8190 {
8191   int size , offset = 0;
8192
8193
8194   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8195
8196
8197   /* optimization - most of the time, left and result are the same
8198    * address, but different types. for the pic code, we could omit
8199    * the following
8200    */
8201
8202   pic16_aopOp(result,ic,TRUE);
8203
8204   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8205
8206   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8207
8208   size = AOP_SIZE(result);
8209
8210   while (size--) {
8211     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8212     offset++;
8213   }
8214
8215   pic16_freeAsmop(left,NULL,ic,TRUE);
8216   pic16_freeAsmop(result,NULL,ic,TRUE);
8217 }
8218 #endif
8219 /*-----------------------------------------------------------------*/
8220 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8221 /*-----------------------------------------------------------------*/
8222 static void genNearPointerGet (operand *left, 
8223                                operand *result, 
8224                                iCode *ic)
8225 {
8226     asmop *aop = NULL;
8227     //regs *preg = NULL ;
8228     char *rname ;
8229     sym_link *rtype, *retype;
8230     sym_link *ltype = operandType(left);    
8231     //char buffer[80];
8232
8233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8234
8235     rtype = operandType(result);
8236     retype= getSpec(rtype);
8237     
8238     pic16_aopOp(left,ic,FALSE);
8239     
8240     /* if left is rematerialisable and
8241        result is not bit variable type and
8242        the left is pointer to data space i.e
8243        lower 128 bytes of space */
8244     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8245         !IS_BITVAR(retype)         &&
8246         DCL_TYPE(ltype) == POINTER) {
8247       //genDataPointerGet (left,result,ic);
8248         return ;
8249     }
8250     
8251     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8252
8253         /* if the value is already in a pointer register
8254        then don't need anything more */
8255     if (!AOP_INPREG(AOP(left))) {
8256         /* otherwise get a free pointer register */
8257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8258 /*
8259         aop = newAsmop(0);
8260         preg = getFreePtr(ic,&aop,FALSE);
8261         pic16_emitcode("mov","%s,%s",
8262                 preg->name,
8263                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8264         rname = preg->name ;
8265 */
8266     rname ="BAD";
8267     } else
8268         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8269     
8270     pic16_aopOp (result,ic,FALSE);
8271     
8272       /* if bitfield then unpack the bits */
8273     if (IS_BITVAR(retype)) 
8274         genUnpackBits (result,rname,POINTER);
8275     else {
8276         /* we have can just get the values */
8277       int size = AOP_SIZE(result);
8278       int offset = 0 ;  
8279         
8280       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8281
8282       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8283       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8284       while(size--) {
8285         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8286         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8287         if(size)
8288           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8289       }
8290 /*
8291         while (size--) {
8292             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8293
8294                 pic16_emitcode("mov","a,@%s",rname);
8295                 pic16_aopPut(AOP(result),"a",offset);
8296             } else {
8297                 sprintf(buffer,"@%s",rname);
8298                 pic16_aopPut(AOP(result),buffer,offset);
8299             }
8300             offset++ ;
8301             if (size)
8302                 pic16_emitcode("inc","%s",rname);
8303         }
8304 */
8305     }
8306
8307     /* now some housekeeping stuff */
8308     if (aop) {
8309         /* we had to allocate for this iCode */
8310     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8311         pic16_freeAsmop(NULL,aop,ic,TRUE);
8312     } else { 
8313         /* we did not allocate which means left
8314            already in a pointer register, then
8315            if size > 0 && this could be used again
8316            we have to point it back to where it 
8317            belongs */
8318     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8319         if (AOP_SIZE(result) > 1 &&
8320             !OP_SYMBOL(left)->remat &&
8321             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8322               ic->depth )) {
8323             int size = AOP_SIZE(result) - 1;
8324             while (size--)
8325                 pic16_emitcode("dec","%s",rname);
8326         }
8327     }
8328
8329     /* done */
8330     pic16_freeAsmop(left,NULL,ic,TRUE);
8331     pic16_freeAsmop(result,NULL,ic,TRUE);
8332      
8333 }
8334
8335 /*-----------------------------------------------------------------*/
8336 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8337 /*-----------------------------------------------------------------*/
8338 static void genPagedPointerGet (operand *left, 
8339                                operand *result, 
8340                                iCode *ic)
8341 {
8342     asmop *aop = NULL;
8343     regs *preg = NULL ;
8344     char *rname ;
8345     sym_link *rtype, *retype;    
8346
8347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8348
8349     rtype = operandType(result);
8350     retype= getSpec(rtype);
8351     
8352     pic16_aopOp(left,ic,FALSE);
8353
8354   /* if the value is already in a pointer register
8355        then don't need anything more */
8356     if (!AOP_INPREG(AOP(left))) {
8357         /* otherwise get a free pointer register */
8358         aop = newAsmop(0);
8359         preg = getFreePtr(ic,&aop,FALSE);
8360         pic16_emitcode("mov","%s,%s",
8361                 preg->name,
8362                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8363         rname = preg->name ;
8364     } else
8365         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8366     
8367     pic16_freeAsmop(left,NULL,ic,TRUE);
8368     pic16_aopOp (result,ic,FALSE);
8369
8370     /* if bitfield then unpack the bits */
8371     if (IS_BITVAR(retype)) 
8372         genUnpackBits (result,rname,PPOINTER);
8373     else {
8374         /* we have can just get the values */
8375         int size = AOP_SIZE(result);
8376         int offset = 0 ;        
8377         
8378         while (size--) {
8379             
8380             pic16_emitcode("movx","a,@%s",rname);
8381             pic16_aopPut(AOP(result),"a",offset);
8382             
8383             offset++ ;
8384             
8385             if (size)
8386                 pic16_emitcode("inc","%s",rname);
8387         }
8388     }
8389
8390     /* now some housekeeping stuff */
8391     if (aop) {
8392         /* we had to allocate for this iCode */
8393         pic16_freeAsmop(NULL,aop,ic,TRUE);
8394     } else { 
8395         /* we did not allocate which means left
8396            already in a pointer register, then
8397            if size > 0 && this could be used again
8398            we have to point it back to where it 
8399            belongs */
8400         if (AOP_SIZE(result) > 1 &&
8401             !OP_SYMBOL(left)->remat &&
8402             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8403               ic->depth )) {
8404             int size = AOP_SIZE(result) - 1;
8405             while (size--)
8406                 pic16_emitcode("dec","%s",rname);
8407         }
8408     }
8409
8410     /* done */
8411     pic16_freeAsmop(result,NULL,ic,TRUE);
8412     
8413         
8414 }
8415
8416 /*-----------------------------------------------------------------*/
8417 /* genFarPointerGet - gget value from far space                    */
8418 /*-----------------------------------------------------------------*/
8419 static void genFarPointerGet (operand *left,
8420                               operand *result, iCode *ic)
8421 {
8422     int size, offset ;
8423     sym_link *retype = getSpec(operandType(result));
8424
8425     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8426
8427     pic16_aopOp(left,ic,FALSE);
8428
8429     /* if the operand is already in dptr 
8430     then we do nothing else we move the value to dptr */
8431     if (AOP_TYPE(left) != AOP_STR) {
8432         /* if this is remateriazable */
8433         if (AOP_TYPE(left) == AOP_IMMD)
8434             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8435         else { /* we need to get it byte by byte */
8436             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8437             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8438             if (options.model == MODEL_FLAT24)
8439             {
8440                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8441             }
8442         }
8443     }
8444     /* so dptr know contains the address */
8445     pic16_freeAsmop(left,NULL,ic,TRUE);
8446     pic16_aopOp(result,ic,FALSE);
8447
8448     /* if bit then unpack */
8449     if (IS_BITVAR(retype)) 
8450         genUnpackBits(result,"dptr",FPOINTER);
8451     else {
8452         size = AOP_SIZE(result);
8453         offset = 0 ;
8454
8455         while (size--) {
8456             pic16_emitcode("movx","a,@dptr");
8457             pic16_aopPut(AOP(result),"a",offset++);
8458             if (size)
8459                 pic16_emitcode("inc","dptr");
8460         }
8461     }
8462
8463     pic16_freeAsmop(result,NULL,ic,TRUE);
8464 }
8465 #if 0
8466 /*-----------------------------------------------------------------*/
8467 /* genCodePointerGet - get value from code space                  */
8468 /*-----------------------------------------------------------------*/
8469 static void genCodePointerGet (operand *left,
8470                                 operand *result, iCode *ic)
8471 {
8472     int size, offset ;
8473     sym_link *retype = getSpec(operandType(result));
8474
8475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8476
8477     pic16_aopOp(left,ic,FALSE);
8478
8479     /* if the operand is already in dptr 
8480     then we do nothing else we move the value to dptr */
8481     if (AOP_TYPE(left) != AOP_STR) {
8482         /* if this is remateriazable */
8483         if (AOP_TYPE(left) == AOP_IMMD)
8484             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8485         else { /* we need to get it byte by byte */
8486             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8487             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8488             if (options.model == MODEL_FLAT24)
8489             {
8490                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8491             }
8492         }
8493     }
8494     /* so dptr know contains the address */
8495     pic16_freeAsmop(left,NULL,ic,TRUE);
8496     pic16_aopOp(result,ic,FALSE);
8497
8498     /* if bit then unpack */
8499     if (IS_BITVAR(retype)) 
8500         genUnpackBits(result,"dptr",CPOINTER);
8501     else {
8502         size = AOP_SIZE(result);
8503         offset = 0 ;
8504
8505         while (size--) {
8506             pic16_emitcode("clr","a");
8507             pic16_emitcode("movc","a,@a+dptr");
8508             pic16_aopPut(AOP(result),"a",offset++);
8509             if (size)
8510                 pic16_emitcode("inc","dptr");
8511         }
8512     }
8513
8514     pic16_freeAsmop(result,NULL,ic,TRUE);
8515 }
8516 #endif
8517 /*-----------------------------------------------------------------*/
8518 /* genGenPointerGet - gget value from generic pointer space        */
8519 /*-----------------------------------------------------------------*/
8520 static void genGenPointerGet (operand *left,
8521                               operand *result, iCode *ic)
8522 {
8523   int size, offset ;
8524   sym_link *retype = getSpec(operandType(result));
8525
8526   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8527   pic16_aopOp(left,ic,FALSE);
8528   pic16_aopOp(result,ic,FALSE);
8529
8530
8531   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8532
8533   /* if the operand is already in dptr 
8534      then we do nothing else we move the value to dptr */
8535   //  if (AOP_TYPE(left) != AOP_STR) {
8536     /* if this is remateriazable */
8537     if (AOP_TYPE(left) == AOP_IMMD) {
8538       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8539       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8540     }
8541     else { /* we need to get it byte by byte */
8542
8543       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8544       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8545
8546       size = AOP_SIZE(result);
8547       offset = 0 ;
8548
8549       while(size--) {
8550         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8551         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8552         if(size)
8553           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8554       }
8555       goto release;
8556     }
8557     //}
8558   /* so dptr know contains the address */
8559
8560   /* if bit then unpack */
8561   //if (IS_BITVAR(retype)) 
8562   //  genUnpackBits(result,"dptr",GPOINTER);
8563
8564  release:
8565   pic16_freeAsmop(left,NULL,ic,TRUE);
8566   pic16_freeAsmop(result,NULL,ic,TRUE);
8567
8568 }
8569
8570 /*-----------------------------------------------------------------*/
8571 /* genConstPointerGet - get value from const generic pointer space */
8572 /*-----------------------------------------------------------------*/
8573 static void genConstPointerGet (operand *left,
8574                                 operand *result, iCode *ic)
8575 {
8576   //sym_link *retype = getSpec(operandType(result));
8577   symbol *albl = newiTempLabel(NULL);
8578   symbol *blbl = newiTempLabel(NULL);
8579   PIC_OPCODE poc;
8580
8581   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8582   pic16_aopOp(left,ic,FALSE);
8583   pic16_aopOp(result,ic,FALSE);
8584
8585
8586   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8587
8588   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8589
8590   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8591   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8592   pic16_emitpLabel(albl->key);
8593
8594   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8595     
8596   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8597   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8598   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8599   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8600   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8601
8602   pic16_emitpLabel(blbl->key);
8603
8604   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8605
8606
8607   pic16_freeAsmop(left,NULL,ic,TRUE);
8608   pic16_freeAsmop(result,NULL,ic,TRUE);
8609
8610 }
8611 /*-----------------------------------------------------------------*/
8612 /* genPointerGet - generate code for pointer get                   */
8613 /*-----------------------------------------------------------------*/
8614 static void genPointerGet (iCode *ic)
8615 {
8616     operand *left, *result ;
8617     sym_link *type, *etype;
8618     int p_type;
8619
8620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8621
8622     left = IC_LEFT(ic);
8623     result = IC_RESULT(ic) ;
8624
8625     /* depending on the type of pointer we need to
8626     move it to the correct pointer register */
8627     type = operandType(left);
8628     etype = getSpec(type);
8629
8630 #if 0
8631     if (IS_PTR_CONST(type))
8632 #else
8633     if (IS_CODEPTR(type))
8634 #endif
8635       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8636
8637     /* if left is of type of pointer then it is simple */
8638     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8639         p_type = DCL_TYPE(type);
8640     else {
8641         /* we have to go by the storage class */
8642         p_type = PTR_TYPE(SPEC_OCLS(etype));
8643
8644         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8645
8646         if (SPEC_OCLS(etype)->codesp ) {
8647           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8648           //p_type = CPOINTER ; 
8649         }
8650         else
8651             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8652               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8653                /*p_type = FPOINTER ;*/ 
8654             else
8655                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8656                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8657 /*                  p_type = PPOINTER; */
8658                 else
8659                     if (SPEC_OCLS(etype) == idata )
8660                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8661 /*                      p_type = IPOINTER; */
8662                     else
8663                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8664 /*                      p_type = POINTER ; */
8665     }
8666
8667     /* now that we have the pointer type we assign
8668     the pointer values */
8669     switch (p_type) {
8670
8671     case POINTER:       
8672     case IPOINTER:
8673         genNearPointerGet (left,result,ic);
8674         break;
8675
8676     case PPOINTER:
8677         genPagedPointerGet(left,result,ic);
8678         break;
8679
8680     case FPOINTER:
8681         genFarPointerGet (left,result,ic);
8682         break;
8683
8684     case CPOINTER:
8685         genConstPointerGet (left,result,ic);
8686         //pic16_emitcodePointerGet (left,result,ic);
8687         break;
8688
8689     case GPOINTER:
8690 #if 0
8691       if (IS_PTR_CONST(type))
8692         genConstPointerGet (left,result,ic);
8693       else
8694 #endif
8695         genGenPointerGet (left,result,ic);
8696       break;
8697     }
8698
8699 }
8700
8701 /*-----------------------------------------------------------------*/
8702 /* genPackBits - generates code for packed bit storage             */
8703 /*-----------------------------------------------------------------*/
8704 static void genPackBits (sym_link    *etype ,
8705                          operand *right ,
8706                          char *rname, int p_type)
8707 {
8708     int shCount = 0 ;
8709     int offset = 0  ;
8710     int rLen = 0 ;
8711     int blen, bstr ;   
8712     char *l ;
8713
8714     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8715     blen = SPEC_BLEN(etype);
8716     bstr = SPEC_BSTR(etype);
8717
8718     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8719     MOVA(l);   
8720
8721     /* if the bit lenth is less than or    */
8722     /* it exactly fits a byte then         */
8723     if (SPEC_BLEN(etype) <= 8 )  {
8724         shCount = SPEC_BSTR(etype) ;
8725
8726         /* shift left acc */
8727         AccLsh(shCount);
8728
8729         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8730
8731
8732             switch (p_type) {
8733                 case POINTER:
8734                     pic16_emitcode ("mov","b,a");
8735                     pic16_emitcode("mov","a,@%s",rname);
8736                     break;
8737
8738                 case FPOINTER:
8739                     pic16_emitcode ("mov","b,a");
8740                     pic16_emitcode("movx","a,@dptr");
8741                     break;
8742
8743                 case GPOINTER:
8744                     pic16_emitcode ("push","b");
8745                     pic16_emitcode ("push","acc");
8746                     pic16_emitcode ("lcall","__gptrget");
8747                     pic16_emitcode ("pop","b");
8748                     break;
8749             }
8750
8751             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8752                       ((unsigned char)(0xFF << (blen+bstr)) | 
8753                        (unsigned char)(0xFF >> (8-bstr)) ) );
8754             pic16_emitcode ("orl","a,b");
8755             if (p_type == GPOINTER)
8756                 pic16_emitcode("pop","b");
8757         }
8758     }
8759
8760     switch (p_type) {
8761         case POINTER:
8762             pic16_emitcode("mov","@%s,a",rname);
8763             break;
8764
8765         case FPOINTER:
8766             pic16_emitcode("movx","@dptr,a");
8767             break;
8768
8769         case GPOINTER:
8770             DEBUGpic16_emitcode(";lcall","__gptrput");
8771             break;
8772     }
8773
8774     /* if we r done */
8775     if ( SPEC_BLEN(etype) <= 8 )
8776         return ;
8777
8778     pic16_emitcode("inc","%s",rname);
8779     rLen = SPEC_BLEN(etype) ;     
8780
8781     /* now generate for lengths greater than one byte */
8782     while (1) {
8783
8784         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8785
8786         rLen -= 8 ;
8787         if (rLen <= 0 )
8788             break ;
8789
8790         switch (p_type) {
8791             case POINTER:
8792                 if (*l == '@') {
8793                     MOVA(l);
8794                     pic16_emitcode("mov","@%s,a",rname);
8795                 } else
8796                     pic16_emitcode("mov","@%s,%s",rname,l);
8797                 break;
8798
8799             case FPOINTER:
8800                 MOVA(l);
8801                 pic16_emitcode("movx","@dptr,a");
8802                 break;
8803
8804             case GPOINTER:
8805                 MOVA(l);
8806                 DEBUGpic16_emitcode(";lcall","__gptrput");
8807                 break;  
8808         }   
8809         pic16_emitcode ("inc","%s",rname);
8810     }
8811
8812     MOVA(l);
8813
8814     /* last last was not complete */
8815     if (rLen)   {
8816         /* save the byte & read byte */
8817         switch (p_type) {
8818             case POINTER:
8819                 pic16_emitcode ("mov","b,a");
8820                 pic16_emitcode("mov","a,@%s",rname);
8821                 break;
8822
8823             case FPOINTER:
8824                 pic16_emitcode ("mov","b,a");
8825                 pic16_emitcode("movx","a,@dptr");
8826                 break;
8827
8828             case GPOINTER:
8829                 pic16_emitcode ("push","b");
8830                 pic16_emitcode ("push","acc");
8831                 pic16_emitcode ("lcall","__gptrget");
8832                 pic16_emitcode ("pop","b");
8833                 break;
8834         }
8835
8836         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8837         pic16_emitcode ("orl","a,b");
8838     }
8839
8840     if (p_type == GPOINTER)
8841         pic16_emitcode("pop","b");
8842
8843     switch (p_type) {
8844
8845     case POINTER:
8846         pic16_emitcode("mov","@%s,a",rname);
8847         break;
8848         
8849     case FPOINTER:
8850         pic16_emitcode("movx","@dptr,a");
8851         break;
8852         
8853     case GPOINTER:
8854         DEBUGpic16_emitcode(";lcall","__gptrput");
8855         break;                  
8856     }
8857 }
8858 /*-----------------------------------------------------------------*/
8859 /* genDataPointerSet - remat pointer to data space                 */
8860 /*-----------------------------------------------------------------*/
8861 static void genDataPointerSet(operand *right,
8862                               operand *result,
8863                               iCode *ic)
8864 {
8865     int size, offset = 0 ;
8866     char *l, buffer[256];
8867
8868     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8869     pic16_aopOp(right,ic,FALSE);
8870     
8871     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8872     size = AOP_SIZE(right);
8873 /*
8874     if ( AOP_TYPE(result) == AOP_PCODE) {
8875       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8876               AOP(result)->aopu.pcop->name,
8877               PCOI(AOP(result)->aopu.pcop)->offset);
8878     }
8879 */
8880
8881     // tsd, was l+1 - the underline `_' prefix was being stripped
8882     while (size--) {
8883       if (offset) {
8884         sprintf(buffer,"(%s + %d)",l,offset);
8885         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
8886       } else
8887         sprintf(buffer,"%s",l);
8888
8889         if (AOP_TYPE(right) == AOP_LIT) {
8890           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8891           lit = lit >> (8*offset);
8892           if(lit&0xff) {
8893             pic16_emitcode("movlw","%d",lit);
8894             pic16_emitcode("movwf","%s",buffer);
8895
8896             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8897             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8898             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8899
8900           } else {
8901             pic16_emitcode("clrf","%s",buffer);
8902             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
8903             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8904           }
8905         }else {
8906           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8907           pic16_emitcode("movwf","%s",buffer);
8908
8909           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8910           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8911           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8912
8913         }
8914
8915         offset++;
8916     }
8917
8918     pic16_freeAsmop(right,NULL,ic,TRUE);
8919     pic16_freeAsmop(result,NULL,ic,TRUE);
8920 }
8921
8922 /*-----------------------------------------------------------------*/
8923 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8924 /*-----------------------------------------------------------------*/
8925 static void genNearPointerSet (operand *right,
8926                                operand *result, 
8927                                iCode *ic)
8928 {
8929   asmop *aop = NULL;
8930   char *l;
8931   sym_link *retype;
8932   sym_link *ptype = operandType(result);
8933
8934     
8935   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8936   retype= getSpec(operandType(right));
8937
8938   pic16_aopOp(result,ic,FALSE);
8939
8940     
8941   /* if the result is rematerializable &
8942      in data space & not a bit variable */
8943   //if (AOP_TYPE(result) == AOP_IMMD &&
8944   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8945       DCL_TYPE(ptype) == POINTER   &&
8946       !IS_BITVAR(retype)) {
8947     genDataPointerSet (right,result,ic);
8948     pic16_freeAsmop(result,NULL,ic,TRUE);
8949     return;
8950   }
8951
8952   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8953   pic16_aopOp(right,ic,FALSE);
8954   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8955
8956   /* if the value is already in a pointer register
8957      then don't need anything more */
8958   if (!AOP_INPREG(AOP(result))) {
8959     /* otherwise get a free pointer register */
8960     //aop = newAsmop(0);
8961     //preg = getFreePtr(ic,&aop,FALSE);
8962     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8963     //pic16_emitcode("mov","%s,%s",
8964     //         preg->name,
8965     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8966     //rname = preg->name ;
8967     //pic16_emitcode("movwf","fsr0");
8968     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8969     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8970     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8971     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8972     goto release;
8973
8974   }// else
8975   //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8976
8977
8978   /* if bitfield then unpack the bits */
8979   if (IS_BITVAR(retype)) {
8980     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8981            "The programmer is obviously confused");
8982     //genPackBits (retype,right,rname,POINTER);
8983     exit(1);
8984   }
8985   else {
8986     /* we have can just get the values */
8987     int size = AOP_SIZE(right);
8988     int offset = 0 ;    
8989
8990     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8991     while (size--) {
8992       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8993       if (*l == '@' ) {
8994         //MOVA(l);
8995         //pic16_emitcode("mov","@%s,a",rname);
8996         pic16_emitcode("movf","indf0,w ;1");
8997       } else {
8998
8999         if (AOP_TYPE(right) == AOP_LIT) {
9000           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9001           if(lit) {
9002             pic16_emitcode("movlw","%s",l);
9003             pic16_emitcode("movwf","indf0 ;2");
9004           } else 
9005             pic16_emitcode("clrf","indf0");
9006         }else {
9007           pic16_emitcode("movf","%s,w",l);
9008           pic16_emitcode("movwf","indf0 ;2");
9009         }
9010         //pic16_emitcode("mov","@%s,%s",rname,l);
9011       }
9012       if (size)
9013         pic16_emitcode("incf","fsr0,f ;3");
9014       //pic16_emitcode("inc","%s",rname);
9015       offset++;
9016     }
9017   }
9018
9019   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9020   /* now some housekeeping stuff */
9021   if (aop) {
9022     /* we had to allocate for this iCode */
9023     pic16_freeAsmop(NULL,aop,ic,TRUE);
9024   } else { 
9025     /* we did not allocate which means left
9026        already in a pointer register, then
9027        if size > 0 && this could be used again
9028        we have to point it back to where it 
9029        belongs */
9030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9031     if (AOP_SIZE(right) > 1 &&
9032         !OP_SYMBOL(result)->remat &&
9033         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9034           ic->depth )) {
9035       int size = AOP_SIZE(right) - 1;
9036       while (size--)
9037         pic16_emitcode("decf","fsr0,f");
9038       //pic16_emitcode("dec","%s",rname);
9039     }
9040   }
9041
9042   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9043   /* done */
9044  release:
9045   pic16_freeAsmop(right,NULL,ic,TRUE);
9046   pic16_freeAsmop(result,NULL,ic,TRUE);
9047 }
9048
9049 /*-----------------------------------------------------------------*/
9050 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9051 /*-----------------------------------------------------------------*/
9052 static void genPagedPointerSet (operand *right,
9053                                operand *result, 
9054                                iCode *ic)
9055 {
9056     asmop *aop = NULL;
9057     regs *preg = NULL ;
9058     char *rname , *l;
9059     sym_link *retype;
9060        
9061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9062
9063     retype= getSpec(operandType(right));
9064     
9065     pic16_aopOp(result,ic,FALSE);
9066     
9067     /* if the value is already in a pointer register
9068        then don't need anything more */
9069     if (!AOP_INPREG(AOP(result))) {
9070         /* otherwise get a free pointer register */
9071         aop = newAsmop(0);
9072         preg = getFreePtr(ic,&aop,FALSE);
9073         pic16_emitcode("mov","%s,%s",
9074                 preg->name,
9075                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9076         rname = preg->name ;
9077     } else
9078         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9079     
9080     pic16_freeAsmop(result,NULL,ic,TRUE);
9081     pic16_aopOp (right,ic,FALSE);
9082
9083     /* if bitfield then unpack the bits */
9084     if (IS_BITVAR(retype)) 
9085         genPackBits (retype,right,rname,PPOINTER);
9086     else {
9087         /* we have can just get the values */
9088         int size = AOP_SIZE(right);
9089         int offset = 0 ;        
9090         
9091         while (size--) {
9092             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9093             
9094             MOVA(l);
9095             pic16_emitcode("movx","@%s,a",rname);
9096
9097             if (size)
9098                 pic16_emitcode("inc","%s",rname);
9099
9100             offset++;
9101         }
9102     }
9103     
9104     /* now some housekeeping stuff */
9105     if (aop) {
9106         /* we had to allocate for this iCode */
9107         pic16_freeAsmop(NULL,aop,ic,TRUE);
9108     } else { 
9109         /* we did not allocate which means left
9110            already in a pointer register, then
9111            if size > 0 && this could be used again
9112            we have to point it back to where it 
9113            belongs */
9114         if (AOP_SIZE(right) > 1 &&
9115             !OP_SYMBOL(result)->remat &&
9116             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9117               ic->depth )) {
9118             int size = AOP_SIZE(right) - 1;
9119             while (size--)
9120                 pic16_emitcode("dec","%s",rname);
9121         }
9122     }
9123
9124     /* done */
9125     pic16_freeAsmop(right,NULL,ic,TRUE);
9126     
9127         
9128 }
9129
9130 /*-----------------------------------------------------------------*/
9131 /* genFarPointerSet - set value from far space                     */
9132 /*-----------------------------------------------------------------*/
9133 static void genFarPointerSet (operand *right,
9134                               operand *result, iCode *ic)
9135 {
9136     int size, offset ;
9137     sym_link *retype = getSpec(operandType(right));
9138
9139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9140     pic16_aopOp(result,ic,FALSE);
9141
9142     /* if the operand is already in dptr 
9143     then we do nothing else we move the value to dptr */
9144     if (AOP_TYPE(result) != AOP_STR) {
9145         /* if this is remateriazable */
9146         if (AOP_TYPE(result) == AOP_IMMD)
9147             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9148         else { /* we need to get it byte by byte */
9149             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9150             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9151             if (options.model == MODEL_FLAT24)
9152             {
9153                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9154             }
9155         }
9156     }
9157     /* so dptr know contains the address */
9158     pic16_freeAsmop(result,NULL,ic,TRUE);
9159     pic16_aopOp(right,ic,FALSE);
9160
9161     /* if bit then unpack */
9162     if (IS_BITVAR(retype)) 
9163         genPackBits(retype,right,"dptr",FPOINTER);
9164     else {
9165         size = AOP_SIZE(right);
9166         offset = 0 ;
9167
9168         while (size--) {
9169             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9170             MOVA(l);
9171             pic16_emitcode("movx","@dptr,a");
9172             if (size)
9173                 pic16_emitcode("inc","dptr");
9174         }
9175     }
9176
9177     pic16_freeAsmop(right,NULL,ic,TRUE);
9178 }
9179
9180 /*-----------------------------------------------------------------*/
9181 /* genGenPointerSet - set value from generic pointer space         */
9182 /*-----------------------------------------------------------------*/
9183 static void genGenPointerSet (operand *right,
9184                               operand *result, iCode *ic)
9185 {
9186   int size, offset ;
9187   sym_link *retype = getSpec(operandType(right));
9188
9189   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9190
9191   pic16_aopOp(result,ic,FALSE);
9192   pic16_aopOp(right,ic,FALSE);
9193   size = AOP_SIZE(right);
9194
9195   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9196
9197   /* if the operand is already in dptr 
9198      then we do nothing else we move the value to dptr */
9199   if (AOP_TYPE(result) != AOP_STR) {
9200     /* if this is remateriazable */
9201     if (AOP_TYPE(result) == AOP_IMMD) {
9202       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9203       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9204     }
9205     else { /* we need to get it byte by byte */
9206       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9207       size = AOP_SIZE(right);
9208       offset = 0 ;
9209
9210       /* hack hack! see if this the FSR. If so don't load W */
9211       if(AOP_TYPE(right) != AOP_ACC) {
9212
9213 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(result), pic16_popCopyReg(&pic16_pc_fsr0), 0));
9214
9215         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9216         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9217
9218         if(AOP_SIZE(result) > 1) {
9219           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9220           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9221           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9222
9223         }
9224
9225         //if(size==2)
9226         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9227         //if(size==4) {
9228         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9229         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9230         //}
9231
9232         while(size--) {
9233           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9234           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9235           
9236           if(size)
9237             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9238         }
9239
9240
9241         goto release;
9242       } 
9243
9244       if(aopIdx(AOP(result),0) != 4) {
9245
9246         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9247         goto release;
9248       }
9249
9250       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9251       goto release;
9252
9253     }
9254   }
9255   /* so dptr know contains the address */
9256
9257
9258   /* if bit then unpack */
9259   if (IS_BITVAR(retype)) 
9260     genPackBits(retype,right,"dptr",GPOINTER);
9261   else {
9262     size = AOP_SIZE(right);
9263     offset = 0 ;
9264
9265   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9266
9267     while (size--) {
9268
9269       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9270       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9271
9272       if (AOP_TYPE(right) == AOP_LIT) 
9273         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9274       else
9275         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9276
9277       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9278
9279       offset++;
9280     }
9281   }
9282
9283  release:
9284   pic16_freeAsmop(right,NULL,ic,TRUE);
9285   pic16_freeAsmop(result,NULL,ic,TRUE);
9286 }
9287
9288 /*-----------------------------------------------------------------*/
9289 /* genPointerSet - stores the value into a pointer location        */
9290 /*-----------------------------------------------------------------*/
9291 static void genPointerSet (iCode *ic)
9292 {    
9293     operand *right, *result ;
9294     sym_link *type, *etype;
9295     int p_type;
9296
9297     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9298
9299     right = IC_RIGHT(ic);
9300     result = IC_RESULT(ic) ;
9301
9302     /* depending on the type of pointer we need to
9303     move it to the correct pointer register */
9304     type = operandType(result);
9305     etype = getSpec(type);
9306     /* if left is of type of pointer then it is simple */
9307     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9308         p_type = DCL_TYPE(type);
9309     }
9310     else {
9311         /* we have to go by the storage class */
9312         p_type = PTR_TYPE(SPEC_OCLS(etype));
9313
9314 /*      if (SPEC_OCLS(etype)->codesp ) { */
9315 /*          p_type = CPOINTER ;  */
9316 /*      } */
9317 /*      else */
9318 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9319 /*              p_type = FPOINTER ; */
9320 /*          else */
9321 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9322 /*                  p_type = PPOINTER ; */
9323 /*              else */
9324 /*                  if (SPEC_OCLS(etype) == idata ) */
9325 /*                      p_type = IPOINTER ; */
9326 /*                  else */
9327 /*                      p_type = POINTER ; */
9328     }
9329
9330     /* now that we have the pointer type we assign
9331     the pointer values */
9332     switch (p_type) {
9333
9334     case POINTER:
9335     case IPOINTER:
9336         genNearPointerSet (right,result,ic);
9337         break;
9338
9339     case PPOINTER:
9340         genPagedPointerSet (right,result,ic);
9341         break;
9342
9343     case FPOINTER:
9344         genFarPointerSet (right,result,ic);
9345         break;
9346
9347     case GPOINTER:
9348         genGenPointerSet (right,result,ic);
9349         break;
9350
9351     default:
9352       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9353               "genPointerSet: illegal pointer type");
9354     }
9355 }
9356
9357 /*-----------------------------------------------------------------*/
9358 /* genIfx - generate code for Ifx statement                        */
9359 /*-----------------------------------------------------------------*/
9360 static void genIfx (iCode *ic, iCode *popIc)
9361 {
9362   operand *cond = IC_COND(ic);
9363   int isbit =0;
9364
9365   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9366
9367   pic16_aopOp(cond,ic,FALSE);
9368
9369   /* get the value into acc */
9370   if (AOP_TYPE(cond) != AOP_CRY)
9371     pic16_toBoolean(cond);
9372   else
9373     isbit = 1;
9374   /* the result is now in the accumulator */
9375   pic16_freeAsmop(cond,NULL,ic,TRUE);
9376
9377   /* if there was something to be popped then do it */
9378   if (popIc)
9379     genIpop(popIc);
9380
9381   /* if the condition is  a bit variable */
9382   if (isbit && IS_ITEMP(cond) && 
9383       SPIL_LOC(cond)) {
9384     genIfxJump(ic,SPIL_LOC(cond)->rname);
9385     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9386   }
9387   else {
9388     if (isbit && !IS_ITEMP(cond))
9389       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9390     else
9391       genIfxJump(ic,"a");
9392   }
9393   ic->generated = 1;
9394
9395 }
9396
9397 /*-----------------------------------------------------------------*/
9398 /* genAddrOf - generates code for address of                       */
9399 /*-----------------------------------------------------------------*/
9400 #if 0
9401 static void genAddrOf (iCode *ic)
9402 {
9403   operand *right, *result, *left;
9404   int size, offset ;
9405
9406   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9407
9408
9409   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9410
9411   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9412   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9413   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9414
9415   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9416
9417   size = AOP_SIZE(IC_RESULT(ic));
9418   offset = 0;
9419
9420
9421   while (size--) {
9422     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9423     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9424     offset++;
9425   }
9426
9427
9428   pic16_freeAsmop(left,NULL,ic,FALSE);
9429   pic16_freeAsmop(result,NULL,ic,TRUE);
9430
9431 }
9432
9433 #else   /* new genAddrOf */
9434
9435 static void genAddrOf (iCode *ic)
9436 {
9437   operand *result, *left;
9438   int size;
9439   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9440   pCodeOp *pcop0, *pcop1, *pcop2;
9441
9442         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9443
9444         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9445         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9446
9447         sym = OP_SYMBOL( left );
9448
9449         size = AOP_SIZE(IC_RESULT(ic));
9450
9451         if(pic16_debug_verbose) {
9452                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9453                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9454         }
9455         
9456         /* Assume that what we want the address of is in data space
9457          * since there is no stack on the PIC, yet! -- VR */
9458         /* low */
9459         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9460
9461         /* high */
9462         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9463         
9464         /* upper */
9465         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9466         
9467
9468         if (size == 3) {
9469                 pic16_emitpcode(POC_MOVLW, pcop0);
9470                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9471                 pic16_emitpcode(POC_MOVLW, pcop1);
9472                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9473                 pic16_emitpcode(POC_MOVLW, pcop2);
9474                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9475         } else
9476         if (size == 2) {
9477                 pic16_emitpcode(POC_MOVLW, pcop0);
9478                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9479                 pic16_emitpcode(POC_MOVLW, pcop1);
9480                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9481         } else {
9482                 pic16_emitpcode(POC_MOVLW, pcop0);
9483                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9484         }
9485
9486         pic16_freeAsmop(result,NULL,ic,TRUE);
9487         pic16_freeAsmop(left, NULL, ic, FALSE);
9488 }
9489
9490 #endif  /* new genAddrOf */
9491
9492 #if 0
9493 /*-----------------------------------------------------------------*/
9494 /* genFarFarAssign - assignment when both are in far space         */
9495 /*-----------------------------------------------------------------*/
9496 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9497 {
9498     int size = AOP_SIZE(right);
9499     int offset = 0;
9500     char *l ;
9501     /* first push the right side on to the stack */
9502     while (size--) {
9503         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9504         MOVA(l);
9505         pic16_emitcode ("push","acc");
9506     }
9507     
9508     pic16_freeAsmop(right,NULL,ic,FALSE);
9509     /* now assign DPTR to result */
9510     pic16_aopOp(result,ic,FALSE);
9511     size = AOP_SIZE(result);
9512     while (size--) {
9513         pic16_emitcode ("pop","acc");
9514         pic16_aopPut(AOP(result),"a",--offset);
9515     }
9516     pic16_freeAsmop(result,NULL,ic,FALSE);
9517         
9518 }
9519 #endif
9520
9521 /*-----------------------------------------------------------------*/
9522 /* genAssign - generate code for assignment                        */
9523 /*-----------------------------------------------------------------*/
9524 static void genAssign (iCode *ic)
9525 {
9526   operand *result, *right;
9527   int size, offset,know_W;
9528   unsigned long lit = 0L;
9529
9530   result = IC_RESULT(ic);
9531   right  = IC_RIGHT(ic) ;
9532
9533   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9534   
9535   /* if they are the same */
9536   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9537     return ;
9538
9539   pic16_aopOp(right,ic,FALSE);
9540   pic16_aopOp(result,ic,TRUE);
9541
9542   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9543
9544   /* if they are the same registers */
9545   if (pic16_sameRegs(AOP(right),AOP(result)))
9546     goto release;
9547
9548   /* if the result is a bit */
9549   if (AOP_TYPE(result) == AOP_CRY) {
9550     /* if the right size is a literal then
9551        we know what the value is */
9552     if (AOP_TYPE(right) == AOP_LIT) {
9553           
9554       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9555                   pic16_popGet(AOP(result),0));
9556
9557       if (((int) operandLitValue(right))) 
9558         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9559                        AOP(result)->aopu.aop_dir,
9560                        AOP(result)->aopu.aop_dir);
9561       else
9562         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9563                        AOP(result)->aopu.aop_dir,
9564                        AOP(result)->aopu.aop_dir);
9565       goto release;
9566     }
9567
9568     /* the right is also a bit variable */
9569     if (AOP_TYPE(right) == AOP_CRY) {
9570       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9571       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9572       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9573
9574       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9575                      AOP(result)->aopu.aop_dir,
9576                      AOP(result)->aopu.aop_dir);
9577       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9578                      AOP(right)->aopu.aop_dir,
9579                      AOP(right)->aopu.aop_dir);
9580       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9581                      AOP(result)->aopu.aop_dir,
9582                      AOP(result)->aopu.aop_dir);
9583       goto release ;
9584     }
9585
9586     /* we need to or */
9587     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9588     pic16_toBoolean(right);
9589     emitSKPZ;
9590     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9591     //pic16_aopPut(AOP(result),"a",0);
9592     goto release ;
9593   }
9594
9595   /* bit variables done */
9596   /* general case */
9597   size = AOP_SIZE(result);
9598   offset = 0 ;
9599   if(AOP_TYPE(right) == AOP_LIT)
9600     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9601
9602 /* VR - What is this?! */
9603   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9604   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9605     if(aopIdx(AOP(result),0) == 4) {
9606   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9607       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9608       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9609       goto release;
9610     } else
9611       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9612   }
9613
9614   know_W=-1;
9615   while (size--) {
9616   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9617     if(AOP_TYPE(right) == AOP_LIT) {
9618       if(lit&0xff) {
9619         if(know_W != (lit&0xff))
9620           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9621         know_W = lit&0xff;
9622         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9623       } else
9624         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9625
9626       lit >>= 8;
9627
9628     } else if (AOP_TYPE(right) == AOP_CRY) {
9629       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9630       if(offset == 0) {
9631         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9632         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9633       }
9634     } else {
9635   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9636
9637 #if 1
9638         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9639            normally should work, but mind that the W register live range
9640            is not checked, so if the code generator assumes that the W
9641            is already loaded after such a pair, wrong code will be generated.
9642            
9643            Checking the live range is the next step.
9644            This is experimental code yet and has not been fully tested yet.
9645            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9646            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9647            
9648         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9649 #else   
9650         /* This is the old code, which is assumed(?!) that works fine(!?) */
9651
9652         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9653         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9654 #endif
9655     }
9656             
9657     offset++;
9658   }
9659
9660     
9661  release:
9662   pic16_freeAsmop (right,NULL,ic,FALSE);
9663   pic16_freeAsmop (result,NULL,ic,TRUE);
9664 }   
9665
9666 /*-----------------------------------------------------------------*/
9667 /* genJumpTab - generates code for jump table                       */
9668 /*-----------------------------------------------------------------*/
9669 static void genJumpTab (iCode *ic)
9670 {
9671     symbol *jtab;
9672     char *l;
9673
9674     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9675
9676     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9677     /* get the condition into accumulator */
9678     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9679     MOVA(l);
9680     /* multiply by three */
9681     pic16_emitcode("add","a,acc");
9682     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9683
9684     jtab = newiTempLabel(NULL);
9685     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9686     pic16_emitcode("jmp","@a+dptr");
9687     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9688
9689     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9690     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9691     emitSKPNC;
9692     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9693     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9694     pic16_emitpLabel(jtab->key);
9695
9696     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9697
9698     /* now generate the jump labels */
9699     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9700          jtab = setNextItem(IC_JTLABELS(ic))) {
9701         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9702         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9703         
9704     }
9705
9706 }
9707
9708 /*-----------------------------------------------------------------*/
9709 /* genMixedOperation - gen code for operators between mixed types  */
9710 /*-----------------------------------------------------------------*/
9711 /*
9712   TSD - Written for the PIC port - but this unfortunately is buggy.
9713   This routine is good in that it is able to efficiently promote 
9714   types to different (larger) sizes. Unfortunately, the temporary
9715   variables that are optimized out by this routine are sometimes
9716   used in other places. So until I know how to really parse the 
9717   iCode tree, I'm going to not be using this routine :(.
9718 */
9719 static int genMixedOperation (iCode *ic)
9720 {
9721 #if 0
9722   operand *result = IC_RESULT(ic);
9723   sym_link *ctype = operandType(IC_LEFT(ic));
9724   operand *right = IC_RIGHT(ic);
9725   int ret = 0;
9726   int big,small;
9727   int offset;
9728
9729   iCode *nextic;
9730   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9731
9732   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9733
9734   nextic = ic->next;
9735   if(!nextic)
9736     return 0;
9737
9738   nextright = IC_RIGHT(nextic);
9739   nextleft  = IC_LEFT(nextic);
9740   nextresult = IC_RESULT(nextic);
9741
9742   pic16_aopOp(right,ic,FALSE);
9743   pic16_aopOp(result,ic,FALSE);
9744   pic16_aopOp(nextright,  nextic, FALSE);
9745   pic16_aopOp(nextleft,   nextic, FALSE);
9746   pic16_aopOp(nextresult, nextic, FALSE);
9747
9748   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9749
9750     operand *t = right;
9751     right = nextright;
9752     nextright = t; 
9753
9754     pic16_emitcode(";remove right +","");
9755
9756   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9757 /*
9758     operand *t = right;
9759     right = nextleft;
9760     nextleft = t; 
9761 */
9762     pic16_emitcode(";remove left +","");
9763   } else
9764     return 0;
9765
9766   big = AOP_SIZE(nextleft);
9767   small = AOP_SIZE(nextright);
9768
9769   switch(nextic->op) {
9770
9771   case '+':
9772     pic16_emitcode(";optimize a +","");
9773     /* if unsigned or not an integral type */
9774     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9775       pic16_emitcode(";add a bit to something","");
9776     } else {
9777
9778       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9779
9780       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9781         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9782         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9783       } else
9784         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9785
9786       offset = 0;
9787       while(--big) {
9788
9789         offset++;
9790
9791         if(--small) {
9792           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9793             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9794             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9795           }
9796
9797           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9798           emitSKPNC;
9799           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9800                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9801                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9802           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9803           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9804
9805         } else {
9806           pic16_emitcode("rlf","known_zero,w");
9807
9808           /*
9809             if right is signed
9810               btfsc  right,7
9811                addlw ff
9812           */
9813           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9814             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9815             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9816           } else {
9817             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9818           }
9819         }
9820       }
9821       ret = 1;
9822     }
9823   }
9824   ret = 1;
9825
9826 release:
9827   pic16_freeAsmop(right,NULL,ic,TRUE);
9828   pic16_freeAsmop(result,NULL,ic,TRUE);
9829   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9830   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9831   if(ret)
9832     nextic->generated = 1;
9833
9834   return ret;
9835 #else
9836   return 0;
9837 #endif
9838 }
9839 /*-----------------------------------------------------------------*/
9840 /* genCast - gen code for casting                                  */
9841 /*-----------------------------------------------------------------*/
9842 static void genCast (iCode *ic)
9843 {
9844   operand *result = IC_RESULT(ic);
9845   sym_link *ctype = operandType(IC_LEFT(ic));
9846   sym_link *rtype = operandType(IC_RIGHT(ic));
9847   operand *right = IC_RIGHT(ic);
9848   int size, offset ;
9849
9850         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9851         /* if they are equivalent then do nothing */
9852         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9853                 return ;
9854
9855         pic16_aopOp(right,ic,FALSE) ;
9856         pic16_aopOp(result,ic,FALSE);
9857
9858         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9859
9860         /* if the result is a bit */
9861         if (AOP_TYPE(result) == AOP_CRY) {
9862         
9863                 /* if the right size is a literal then
9864                  * we know what the value is */
9865                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9866
9867                 if (AOP_TYPE(right) == AOP_LIT) {
9868                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9869                                 pic16_popGet(AOP(result),0));
9870
9871                         if (((int) operandLitValue(right))) 
9872                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9873                                         AOP(result)->aopu.aop_dir,
9874                                         AOP(result)->aopu.aop_dir);
9875                         else
9876                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9877                                         AOP(result)->aopu.aop_dir,
9878                                         AOP(result)->aopu.aop_dir);
9879                         goto release;
9880                 }
9881
9882                 /* the right is also a bit variable */
9883                 if (AOP_TYPE(right) == AOP_CRY) {
9884                         emitCLRC;
9885                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9886
9887                         pic16_emitcode("clrc","");
9888                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9889                                 AOP(right)->aopu.aop_dir,
9890                                 AOP(right)->aopu.aop_dir);
9891                         pic16_aopPut(AOP(result),"c",0);
9892                         goto release ;
9893                 }
9894
9895                 /* we need to or */
9896                 if (AOP_TYPE(right) == AOP_REG) {
9897                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9898                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9899                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9900                 }
9901                 pic16_toBoolean(right);
9902                 pic16_aopPut(AOP(result),"a",0);
9903                 goto release ;
9904         }
9905
9906         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9907           int offset = 1;
9908
9909                 size = AOP_SIZE(result);
9910
9911                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9912
9913                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9914                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9915                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9916
9917                 while (size--)
9918                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9919
9920                 goto release;
9921         }
9922
9923         /* if they are the same size : or less */
9924         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9925
9926                 /* if they are in the same place */
9927                 if (pic16_sameRegs(AOP(right),AOP(result)))
9928                         goto release;
9929
9930                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9931 #if 0
9932                 if (IS_PTR_CONST(rtype))
9933 #else
9934                 if (IS_CODEPTR(rtype))
9935 #endif
9936                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9937
9938 #if 0
9939                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9940 #else
9941                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9942 #endif
9943                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9944
9945 #if 0
9946                 if(AOP_TYPE(right) == AOP_IMMD) {
9947                   pCodeOp *pcop0, *pcop1, *pcop2;
9948                   symbol *sym = OP_SYMBOL( right );
9949
9950                         size = AOP_SIZE(result);
9951                         /* low */
9952                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9953                         /* high */
9954                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9955                         /* upper */
9956                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9957         
9958                         if (size == 3) {
9959                                 pic16_emitpcode(POC_MOVLW, pcop0);
9960                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9961                                 pic16_emitpcode(POC_MOVLW, pcop1);
9962                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9963                                 pic16_emitpcode(POC_MOVLW, pcop2);
9964                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9965                         } else
9966                         if (size == 2) {
9967                                 pic16_emitpcode(POC_MOVLW, pcop0);
9968                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9969                                 pic16_emitpcode(POC_MOVLW, pcop1);
9970                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9971                         } else {
9972                                 pic16_emitpcode(POC_MOVLW, pcop0);
9973                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9974                         }
9975                 } else
9976 #endif
9977                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9978                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9979                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9980                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9981                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9982                         if(AOP_SIZE(result) <2)
9983                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9984                 } else {
9985                         /* if they in different places then copy */
9986                         size = AOP_SIZE(result);
9987                         offset = 0 ;
9988                         while (size--) {
9989                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9990                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9991                                 offset++;
9992                         }
9993                 }
9994                 goto release;
9995         }
9996
9997         /* if the result is of type pointer */
9998         if (IS_PTR(ctype)) {
9999           int p_type;
10000           sym_link *type = operandType(right);
10001           sym_link *etype = getSpec(type);
10002
10003                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10004
10005                 /* pointer to generic pointer */
10006                 if (IS_GENPTR(ctype)) {
10007                   char *l = zero;
10008             
10009                         if (IS_PTR(type)) 
10010                                 p_type = DCL_TYPE(type);
10011                         else {
10012                 /* we have to go by the storage class */
10013                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10014
10015 /*              if (SPEC_OCLS(etype)->codesp )  */
10016 /*                  p_type = CPOINTER ;  */
10017 /*              else */
10018 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10019 /*                      p_type = FPOINTER ; */
10020 /*                  else */
10021 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10022 /*                          p_type = PPOINTER; */
10023 /*                      else */
10024 /*                          if (SPEC_OCLS(etype) == idata ) */
10025 /*                              p_type = IPOINTER ; */
10026 /*                          else */
10027 /*                              p_type = POINTER ; */
10028             }
10029                 
10030             /* the first two bytes are known */
10031       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10032             size = GPTRSIZE - 1; 
10033             offset = 0 ;
10034             while (size--) {
10035               if(offset < AOP_SIZE(right)) {
10036       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10037                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10038                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10039                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10040                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10041                 } else { 
10042                   pic16_aopPut(AOP(result),
10043                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10044                          offset);
10045                 }
10046               } else 
10047                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10048               offset++;
10049             }
10050             /* the last byte depending on type */
10051             switch (p_type) {
10052             case IPOINTER:
10053             case POINTER:
10054                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10055                 break;
10056             case FPOINTER:
10057               pic16_emitcode(";BUG!? ","%d",__LINE__);
10058                 l = one;
10059                 break;
10060             case CPOINTER:
10061               pic16_emitcode(";BUG!? ","%d",__LINE__);
10062                 l = "#0x02";
10063                 break;                          
10064             case PPOINTER:
10065               pic16_emitcode(";BUG!? ","%d",__LINE__);
10066                 l = "#0x03";
10067                 break;
10068                 
10069             default:
10070                 /* this should never happen */
10071                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10072                        "got unknown pointer type");
10073                 exit(1);
10074             }
10075             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10076             goto release ;
10077         }
10078         
10079         /* just copy the pointers */
10080         size = AOP_SIZE(result);
10081         offset = 0 ;
10082         while (size--) {
10083             pic16_aopPut(AOP(result),
10084                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10085                    offset);
10086             offset++;
10087         }
10088         goto release ;
10089     }
10090     
10091
10092
10093     /* so we now know that the size of destination is greater
10094     than the size of the source.
10095     Now, if the next iCode is an operator then we might be
10096     able to optimize the operation without performing a cast.
10097     */
10098     if(genMixedOperation(ic))
10099       goto release;
10100
10101     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10102     
10103     /* we move to result for the size of source */
10104     size = AOP_SIZE(right);
10105     offset = 0 ;
10106     while (size--) {
10107       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10108       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10109       offset++;
10110     }
10111
10112     /* now depending on the sign of the destination */
10113     size = AOP_SIZE(result) - AOP_SIZE(right);
10114     /* if unsigned or not an integral type */
10115     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10116       while (size--)
10117         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10118     } else {
10119       /* we need to extend the sign :( */
10120
10121       if(size == 1) {
10122         /* Save one instruction of casting char to int */
10123         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10124         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10125         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10126       } else {
10127         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10128
10129         if(offset)
10130           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10131         else
10132           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10133         
10134         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10135
10136         while (size--)
10137           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10138       }
10139     }
10140
10141 release:
10142     pic16_freeAsmop(right,NULL,ic,TRUE);
10143     pic16_freeAsmop(result,NULL,ic,TRUE);
10144
10145 }
10146
10147 /*-----------------------------------------------------------------*/
10148 /* genDjnz - generate decrement & jump if not zero instrucion      */
10149 /*-----------------------------------------------------------------*/
10150 static int genDjnz (iCode *ic, iCode *ifx)
10151 {
10152     symbol *lbl, *lbl1;
10153     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10154
10155     if (!ifx)
10156         return 0;
10157     
10158     /* if the if condition has a false label
10159        then we cannot save */
10160     if (IC_FALSE(ifx))
10161         return 0;
10162
10163     /* if the minus is not of the form 
10164        a = a - 1 */
10165     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10166         !IS_OP_LITERAL(IC_RIGHT(ic)))
10167         return 0;
10168
10169     if (operandLitValue(IC_RIGHT(ic)) != 1)
10170         return 0;
10171
10172     /* if the size of this greater than one then no
10173        saving */
10174     if (getSize(operandType(IC_RESULT(ic))) > 1)
10175         return 0;
10176
10177     /* otherwise we can save BIG */
10178     lbl = newiTempLabel(NULL);
10179     lbl1= newiTempLabel(NULL);
10180
10181     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10182     
10183     if (IS_AOP_PREG(IC_RESULT(ic))) {
10184         pic16_emitcode("dec","%s",
10185                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10186         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10187         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10188     } else {    
10189
10190
10191       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10192       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10193
10194       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10195       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10196
10197     }
10198 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10199 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10200 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10201 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10202
10203     
10204     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10205     ifx->generated = 1;
10206     return 1;
10207 }
10208
10209 /*-----------------------------------------------------------------*/
10210 /* genReceive - generate code for a receive iCode                  */
10211 /*-----------------------------------------------------------------*/
10212 static void genReceive (iCode *ic)
10213 {    
10214         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10215
10216         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10217                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10218                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10219
10220           int size = getSize(operandType(IC_RESULT(ic)));
10221           int offset =  pic16_fReturnSizePic - size;
10222
10223                 while (size--) {
10224                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10225                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10226                         offset++;
10227                 }
10228
10229                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10230
10231                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10232                 size = AOP_SIZE(IC_RESULT(ic));
10233                 offset = 0;
10234                 while (size--) {
10235                         pic16_emitcode ("pop","acc");
10236                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10237                 }
10238         } else {
10239                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10240
10241                 _G.accInUse++;
10242                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10243                 _G.accInUse--;
10244                 assignResultValue(IC_RESULT(ic));       
10245         }
10246
10247         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10248 }
10249
10250 /*-----------------------------------------------------------------*/
10251 /* genDummyRead - generate code for dummy read of volatiles        */
10252 /*-----------------------------------------------------------------*/
10253 static void
10254 genDummyRead (iCode * ic)
10255 {
10256   pic16_emitcode ("; genDummyRead","");
10257   pic16_emitcode ("; not implemented","");
10258
10259   ic = ic;
10260 }
10261
10262 /*-----------------------------------------------------------------*/
10263 /* genpic16Code - generate code for pic16 based controllers        */
10264 /*-----------------------------------------------------------------*/
10265 /*
10266  * At this point, ralloc.c has gone through the iCode and attempted
10267  * to optimize in a way suitable for a PIC. Now we've got to generate
10268  * PIC instructions that correspond to the iCode.
10269  *
10270  * Once the instructions are generated, we'll pass through both the
10271  * peep hole optimizer and the pCode optimizer.
10272  *-----------------------------------------------------------------*/
10273
10274 void genpic16Code (iCode *lic)
10275 {
10276     iCode *ic;
10277     int cln = 0;
10278
10279     lineHead = lineCurr = NULL;
10280
10281     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10282     pic16_addpBlock(pb);
10283
10284 #if 0
10285     /* if debug information required */
10286     if (options.debug && currFunc) {
10287       if (currFunc) {
10288         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10289         _G.debugLine = 1;
10290         if (IS_STATIC(currFunc->etype)) {
10291           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10292           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10293         } else {
10294           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10295           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10296         }
10297         _G.debugLine = 0;
10298       }
10299     }
10300 #endif
10301
10302 //    dumpiCode(lic);
10303
10304     for (ic = lic ; ic ; ic = ic->next ) {
10305
10306 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10307 //      DEBUGpic16_emitcode("; VR", "");
10308       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10309         if ( cln != ic->lineno ) {
10310             if ( options.debug ) {
10311                 _G.debugLine = 1;
10312                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10313                          FileBaseName(ic->filename),ic->lineno,
10314                          ic->level,ic->block);
10315                 _G.debugLine = 0;
10316             }
10317             
10318             if(!options.noCcodeInAsm) {
10319                 pic16_addpCode2pBlock(pb,
10320                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10321                                 printCLine(ic->filename, ic->lineno)));
10322             }
10323
10324             cln = ic->lineno ;
10325         }
10326         
10327         if(options.iCodeInAsm) {
10328                 /* insert here code to print iCode as comment */
10329         }
10330         
10331         /* if the result is marked as
10332            spilt and rematerializable or code for
10333            this has already been generated then
10334            do nothing */
10335         if (resultRemat(ic) || ic->generated ) 
10336             continue ;
10337         
10338         /* depending on the operation */
10339         switch (ic->op) {
10340         case '!' :
10341             pic16_genNot(ic);
10342             break;
10343             
10344         case '~' :
10345             pic16_genCpl(ic);
10346             break;
10347             
10348         case UNARYMINUS:
10349             genUminus (ic);
10350             break;
10351             
10352         case IPUSH:
10353             genIpush (ic);
10354             break;
10355             
10356         case IPOP:
10357             /* IPOP happens only when trying to restore a 
10358                spilt live range, if there is an ifx statement
10359                following this pop then the if statement might
10360                be using some of the registers being popped which
10361                would destroy the contents of the register so
10362                we need to check for this condition and handle it */
10363             if (ic->next            && 
10364                 ic->next->op == IFX &&
10365                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10366                 genIfx (ic->next,ic);
10367             else
10368                 genIpop (ic);
10369             break; 
10370             
10371         case CALL:
10372             genCall (ic);
10373             break;
10374             
10375         case PCALL:
10376             genPcall (ic);
10377             break;
10378             
10379         case FUNCTION:
10380             genFunction (ic);
10381             break;
10382             
10383         case ENDFUNCTION:
10384             genEndFunction (ic);
10385             break;
10386             
10387         case RETURN:
10388             genRet (ic);
10389             break;
10390             
10391         case LABEL:
10392             genLabel (ic);
10393             break;
10394             
10395         case GOTO:
10396             genGoto (ic);
10397             break;
10398             
10399         case '+' :
10400             pic16_genPlus (ic) ;
10401             break;
10402             
10403         case '-' :
10404             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10405                 pic16_genMinus (ic);
10406             break;
10407             
10408         case '*' :
10409             genMult (ic);
10410             break;
10411             
10412         case '/' :
10413             genDiv (ic) ;
10414             break;
10415             
10416         case '%' :
10417             genMod (ic);
10418             break;
10419             
10420         case '>' :
10421             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10422             break;
10423             
10424         case '<' :
10425             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10426             break;
10427             
10428         case LE_OP:
10429         case GE_OP:
10430         case NE_OP:
10431             
10432             /* note these two are xlated by algebraic equivalence
10433                during parsing SDCC.y */
10434             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10435                    "got '>=' or '<=' shouldn't have come here");
10436             break;      
10437             
10438         case EQ_OP:
10439             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10440             break;          
10441             
10442         case AND_OP:
10443             genAndOp (ic);
10444             break;
10445             
10446         case OR_OP:
10447             genOrOp (ic);
10448             break;
10449             
10450         case '^' :
10451             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10452             break;
10453             
10454         case '|' :
10455                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10456             break;
10457             
10458         case BITWISEAND:
10459             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10460             break;
10461             
10462         case INLINEASM:
10463             genInline (ic);
10464             break;
10465             
10466         case RRC:
10467             genRRC (ic);
10468             break;
10469             
10470         case RLC:
10471             genRLC (ic);
10472             break;
10473             
10474         case GETHBIT:
10475             genGetHbit (ic);
10476             break;
10477             
10478         case LEFT_OP:
10479             genLeftShift (ic);
10480             break;
10481             
10482         case RIGHT_OP:
10483             genRightShift (ic);
10484             break;
10485             
10486         case GET_VALUE_AT_ADDRESS:
10487             genPointerGet(ic);
10488             break;
10489             
10490         case '=' :
10491             if (POINTER_SET(ic))
10492                 genPointerSet(ic);
10493             else
10494                 genAssign(ic);
10495             break;
10496             
10497         case IFX:
10498             genIfx (ic,NULL);
10499             break;
10500             
10501         case ADDRESS_OF:
10502             genAddrOf (ic);
10503             break;
10504             
10505         case JUMPTABLE:
10506             genJumpTab (ic);
10507             break;
10508             
10509         case CAST:
10510             genCast (ic);
10511             break;
10512             
10513         case RECEIVE:
10514             genReceive(ic);
10515             break;
10516             
10517         case SEND:
10518               DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\tSEND",ic->op, ic->op);
10519
10520             addSet(&_G.sendSet,ic);
10521             break;
10522
10523         case DUMMY_READ_VOLATILE:
10524           genDummyRead (ic);
10525           break;
10526
10527         default :
10528             ic = ic;
10529         }
10530     }
10531
10532
10533     /* now we are ready to call the
10534        peep hole optimizer */
10535     if (!options.nopeep) {
10536       peepHole (&lineHead);
10537     }
10538     /* now do the actual printing */
10539     printLine (lineHead,codeOutFile);
10540
10541 #ifdef PCODE_DEBUG
10542     DFPRINTF((stderr,"printing pBlock\n\n"));
10543     pic16_printpBlock(stdout,pb);
10544 #endif
10545
10546     return;
10547 }
10548