2004-01-06 Vangelis Rokas <vrokas@otenet.gr>
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47
48 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
49 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 void pic16_genMult8X8_8 (operand *, operand *,operand *);
51 pCode *pic16_AssembleLine(char *line);
52 extern void pic16_printpBlock(FILE *of, pBlock *pb);
53 static asmop *newAsmop (short type);
54 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
55 static void mov2w (asmop *aop, int offset);
56 static int aopIdx (asmop *aop, int offset);
57
58 static int labelOffset=0;
59 extern int pic16_debug_verbose;
60 static int optimized_for_speed = 0;
61 /*
62   hack hack
63
64 */
65
66 /* max_key keeps track of the largest label number used in 
67    a function. This is then used to adjust the label offset
68    for the next function.
69 */
70 static int max_key=0;
71 static int GpsuedoStkPtr=0;
72
73 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
74 unsigned int pic16aopLiteral (value *val, int offset);
75 const char *pic16_AopType(short type);
76 static iCode *ifxForOp ( operand *op, iCode *ic );
77
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
79
80 /* this is the down and dirty file with all kinds of 
81    kludgy & hacky stuff. This is what it is all about
82    CODE GENERATION for a specific MCU . some of the
83    routines may be reusable, will have to see */
84
85 static char *zero = "#0x00";
86 static char *one  = "#0x01";
87 static char *spname = "sp";
88
89 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
90 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
91 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
92 static char **fReturn = fReturnpic16;
93
94 static char *accUse[] = {"a","b"};
95
96 //static short rbank = -1;
97
98 static struct {
99     short r0Pushed;
100     short r1Pushed;
101     short accInUse;
102     short inLine;
103     short debugLine;
104     short nRegsSaved;
105     set *sendSet;
106 } _G;
107
108 /* Resolved ifx structure. This structure stores information
109    about an iCode ifx that makes it easier to generate code.
110 */
111 typedef struct resolvedIfx {
112   symbol *lbl;     /* pointer to a label */
113   int condition;   /* true or false ifx */
114   int generated;   /* set true when the code associated with the ifx
115                     * is generated */
116 } resolvedIfx;
117
118 extern int pic16_ptrRegReq ;
119 extern int pic16_nRegs;
120 extern FILE *codeOutFile;
121 static void saverbank (int, iCode *,bool);
122
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
125
126 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
130
131 static  pBlock *pb;
132
133 /*-----------------------------------------------------------------*/
134 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
135 /*                 exponent of 2 is returned, otherwise -1 is      */
136 /*                 returned.                                       */
137 /* note that this is similar to the function `powof2' in SDCCsymt  */
138 /* if(n == 2^y)                                                    */
139 /*   return y;                                                     */
140 /* return -1;                                                      */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
143 {
144   if(num) {
145     if( (num & (num-1)) == 0) {
146       int nshifts = -1;
147       while(num) {
148         num>>=1;
149         nshifts++;
150       }
151       return nshifts;
152     }
153   }
154
155   return -1;
156 }
157
158 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
159 {
160
161   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
162                        line_no,
163                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
164                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
166                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
168                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
169                        ((result) ? AOP_SIZE(result) : 0));
170
171 }
172
173 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
174 {
175
176   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
177                        line_no,
178                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
179                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
180                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
181                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
182                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
183                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
184
185 }
186
187 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
188 {
189     va_list ap;
190     char lb[INITIAL_INLINEASM];  
191     char *lbp = lb;
192
193     if(!pic16_debug_verbose)
194       return;
195
196     va_start(ap,fmt);   
197
198     if (inst && *inst) {
199         if (fmt && *fmt)
200             sprintf(lb,"%s\t",inst);
201         else
202             sprintf(lb,"%s",inst);
203         vsprintf(lb+(strlen(lb)),fmt,ap);
204     }  else
205         vsprintf(lb,fmt,ap);
206
207     while (isspace(*lbp)) lbp++;
208
209     if (lbp && *lbp) 
210         lineCurr = (lineCurr ?
211                     connectLine(lineCurr,newLineNode(lb)) :
212                     (lineHead = newLineNode(lb)));
213     lineCurr->isInline = _G.inLine;
214     lineCurr->isDebug  = _G.debugLine;
215
216     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
217     va_end(ap);
218
219 //      fprintf(stderr, "%s\n", lb);
220 }
221
222
223 void pic16_emitpLabel(int key)
224 {
225   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
226 }
227
228 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
229 {
230
231   if(pcop)
232     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
233   else
234     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
235     
236 //    fprintf(stderr, "%s\n", pcop->name);
237 }
238
239 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
240 {
241
242   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
243
244 }
245
246 /*-----------------------------------------------------------------*/
247 /* pic16_emitcode - writes the code into a file : for now it is simple    */
248 /*-----------------------------------------------------------------*/
249 void pic16_emitcode (char *inst,char *fmt, ...)
250 {
251     va_list ap;
252     char lb[INITIAL_INLINEASM];  
253     char *lbp = lb;
254
255     va_start(ap,fmt);   
256
257     if (inst && *inst) {
258         if (fmt && *fmt)
259             sprintf(lb,"%s\t",inst);
260         else
261             sprintf(lb,"%s",inst);
262         vsprintf(lb+(strlen(lb)),fmt,ap);
263     }  else
264         vsprintf(lb,fmt,ap);
265
266     while (isspace(*lbp)) lbp++;
267
268     if (lbp && *lbp) 
269         lineCurr = (lineCurr ?
270                     connectLine(lineCurr,newLineNode(lb)) :
271                     (lineHead = newLineNode(lb)));
272     lineCurr->isInline = _G.inLine;
273     lineCurr->isDebug  = _G.debugLine;
274
275 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
276
277 //    if(pic16_debug_verbose)
278 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
279
280     va_end(ap);
281 }
282
283
284 /*-----------------------------------------------------------------*/
285 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
286 /*-----------------------------------------------------------------*/
287 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
288 {
289     bool r0iu = FALSE , r1iu = FALSE;
290     bool r0ou = FALSE , r1ou = FALSE;
291
292         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
293
294     /* the logic: if r0 & r1 used in the instruction
295     then we are in trouble otherwise */
296
297     /* first check if r0 & r1 are used by this
298     instruction, in which case we are in trouble */
299     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
300         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
301     {
302         goto endOfWorld;      
303     }
304
305     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
306     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
307
308     /* if no usage of r0 then return it */
309     if (!r0iu && !r0ou) {
310         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
311         (*aopp)->type = AOP_R0;
312         
313         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
314     }
315
316     /* if no usage of r1 then return it */
317     if (!r1iu && !r1ou) {
318         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
319         (*aopp)->type = AOP_R1;
320
321         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
322     }    
323
324     /* now we know they both have usage */
325     /* if r0 not used in this instruction */
326     if (!r0iu) {
327         /* push it if not already pushed */
328         if (!_G.r0Pushed) {
329           //pic16_emitcode ("push","%s",
330           //          pic16_regWithIdx(R0_IDX)->dname);
331             _G.r0Pushed++ ;
332         }
333         
334         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
335         (*aopp)->type = AOP_R0;
336
337         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
338     }
339
340     /* if r1 not used then */
341
342     if (!r1iu) {
343         /* push it if not already pushed */
344         if (!_G.r1Pushed) {
345           //pic16_emitcode ("push","%s",
346           //          pic16_regWithIdx(R1_IDX)->dname);
347             _G.r1Pushed++ ;
348         }
349         
350         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
351         (*aopp)->type = AOP_R1;
352         return pic16_regWithIdx(R1_IDX);
353     }
354
355 endOfWorld :
356     /* I said end of world but not quite end of world yet */
357     /* if this is a result then we can push it on the stack*/
358     if (result) {
359         (*aopp)->type = AOP_STK;    
360         return NULL;
361     }
362
363     /* other wise this is true end of the world */
364     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
365            "getFreePtr should never reach here");
366     exit(0);
367 }
368
369 /*-----------------------------------------------------------------*/
370 /* newAsmop - creates a new asmOp                                  */
371 /*-----------------------------------------------------------------*/
372 static asmop *newAsmop (short type)
373 {
374     asmop *aop;
375
376     aop = Safe_calloc(1,sizeof(asmop));
377     aop->type = type;
378     return aop;
379 }
380
381 static void genSetDPTR(int n)
382 {
383     if (!n)
384     {
385         pic16_emitcode(";", "Select standard DPTR");
386         pic16_emitcode("mov", "dps, #0x00");
387     }
388     else
389     {
390         pic16_emitcode(";", "Select alternate DPTR");
391         pic16_emitcode("mov", "dps, #0x01");
392     }
393 }
394
395 /*-----------------------------------------------------------------*/
396 /* resolveIfx - converts an iCode ifx into a form more useful for  */
397 /*              generating code                                    */
398 /*-----------------------------------------------------------------*/
399 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
400 {
401   if(!resIfx) 
402     return;
403
404   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
405
406   resIfx->condition = 1;    /* assume that the ifx is true */
407   resIfx->generated = 0;    /* indicate that the ifx has not been used */
408
409   if(!ifx) {
410     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
411 /*
412     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
413                         __FUNCTION__,__LINE__,resIfx->lbl->key);
414 */
415   } else {
416     if(IC_TRUE(ifx)) {
417       resIfx->lbl = IC_TRUE(ifx);
418     } else {
419       resIfx->lbl = IC_FALSE(ifx);
420       resIfx->condition = 0;
421     }
422 /*
423     if(IC_TRUE(ifx)) 
424       DEBUGpic16_emitcode("; ***","ifx true is non-null");
425     if(IC_FALSE(ifx)) 
426       DEBUGpic16_emitcode("; ***","ifx false is non-null");
427 */
428   }
429
430   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
431
432 }
433 /*-----------------------------------------------------------------*/
434 /* pointerCode - returns the code for a pointer type               */
435 /*-----------------------------------------------------------------*/
436 static int pointerCode (sym_link *etype)
437 {
438
439     return PTR_TYPE(SPEC_OCLS(etype));
440
441 }
442
443 /*-----------------------------------------------------------------*/
444 /* aopForSym - for a true symbol                                   */
445 /*-----------------------------------------------------------------*/
446 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
447 {
448     asmop *aop;
449     memmap *space= SPEC_OCLS(sym->etype);
450
451     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
452     /* if already has one */
453     if (sym->aop) {
454             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
455         return sym->aop;
456     }
457
458     /* assign depending on the storage class */
459     /* if it is on the stack or indirectly addressable */
460     /* space we need to assign either r0 or r1 to it   */    
461     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
462         sym->aop = aop = newAsmop(0);
463         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
464         aop->size = getSize(sym->type);
465
466         /* now assign the address of the variable to 
467         the pointer register */
468         if (aop->type != AOP_STK) {
469
470             if (sym->onStack) {
471                     if ( _G.accInUse )
472                         pic16_emitcode("push","acc");
473
474                     pic16_emitcode("mov","a,_bp");
475                     pic16_emitcode("add","a,#0x%02x",
476                              ((sym->stack < 0) ?
477                               ((char)(sym->stack - _G.nRegsSaved )) :
478                               ((char)sym->stack)) & 0xff);
479                     pic16_emitcode("mov","%s,a",
480                              aop->aopu.aop_ptr->name);
481
482                     if ( _G.accInUse )
483                         pic16_emitcode("pop","acc");
484             } else
485                 pic16_emitcode("mov","%s,#%s",
486                          aop->aopu.aop_ptr->name,
487                          sym->rname);
488             aop->paged = space->paged;
489         } else
490             aop->aopu.aop_stk = sym->stack;
491         return aop;
492     }
493     
494     if (sym->onStack && options.stack10bit)
495     {
496         /* It's on the 10 bit stack, which is located in
497          * far data space.
498          */
499          
500       //DEBUGpic16_emitcode(";","%d",__LINE__);
501
502         if ( _G.accInUse )
503                 pic16_emitcode("push","acc");
504
505         pic16_emitcode("mov","a,_bp");
506         pic16_emitcode("add","a,#0x%02x",
507                  ((sym->stack < 0) ?
508                    ((char)(sym->stack - _G.nRegsSaved )) :
509                    ((char)sym->stack)) & 0xff);
510         
511         genSetDPTR(1);
512         pic16_emitcode ("mov","dpx1,#0x40");
513         pic16_emitcode ("mov","dph1,#0x00");
514         pic16_emitcode ("mov","dpl1, a");
515         genSetDPTR(0);
516         
517         if ( _G.accInUse )
518             pic16_emitcode("pop","acc");
519             
520         sym->aop = aop = newAsmop(AOP_DPTR2);
521         aop->size = getSize(sym->type); 
522         return aop;
523     }
524
525     //DEBUGpic16_emitcode(";","%d",__LINE__);
526     /* if in bit space */
527     if (IN_BITSPACE(space)) {
528         sym->aop = aop = newAsmop (AOP_CRY);
529         aop->aopu.aop_dir = sym->rname ;
530         aop->size = getSize(sym->type);
531         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
532         return aop;
533     }
534     /* if it is in direct space */
535     if (IN_DIRSPACE(space)) {
536         sym->aop = aop = newAsmop (AOP_DIR);
537         aop->aopu.aop_dir = sym->rname ;
538         aop->size = getSize(sym->type);
539         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
540         return aop;
541     }
542
543     /* special case for a function */
544     if (IS_FUNC(sym->type)) {   
545         sym->aop = aop = newAsmop(AOP_IMMD);    
546         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
547         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
548         strcpy(aop->aopu.aop_immd,sym->rname);
549         aop->size = FPTRSIZE; 
550         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
551         return aop;
552     }
553
554
555     /* only remaining is far space */
556     /* in which case DPTR gets the address */
557     sym->aop = aop = newAsmop(AOP_PCODE);
558
559     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
560     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561     PCOI(aop->aopu.pcop)->index = 0;
562
563     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
564                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
565
566     pic16_allocDirReg (IC_LEFT(ic));
567
568     aop->size = FPTRSIZE; 
569 /*
570     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571     sym->aop = aop = newAsmop(AOP_DPTR);
572     pic16_emitcode ("mov","dptr,#%s", sym->rname);
573     aop->size = getSize(sym->type);
574
575     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
576 */
577
578     /* if it is in code space */
579     if (IN_CODESPACE(space))
580         aop->code = 1;
581
582     return aop;     
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                           */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
589 {
590   symbol *sym = OP_SYMBOL(op);
591   iCode *ic = NULL;
592   asmop *aop = newAsmop(AOP_PCODE);
593   int val = 0;
594   int offset = 0;
595
596   ic = sym->rematiCode;
597
598   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599   if(IS_OP_POINTER(op)) {
600     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
601   }
602   for (;;) {
603     if (ic->op == '+') {
604       val += (int) operandLitValue(IC_RIGHT(ic));
605     } else if (ic->op == '-') {
606       val -= (int) operandLitValue(IC_RIGHT(ic));
607     } else
608       break;
609         
610     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
611   }
612
613   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
615 #if 0
616   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
617 #else
618   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
619 #endif
620   PCOI(aop->aopu.pcop)->index = val;
621
622   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
623                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
624 #if 0
625                       val, IS_PTR_CONST(operandType(op)));
626 #else
627                       val, IS_CODEPTR(operandType(op)));
628 #endif
629
630   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
631
632   pic16_allocDirReg (IC_LEFT(ic));
633
634   return aop;        
635 }
636
637 static int aopIdx (asmop *aop, int offset)
638 {
639   if(!aop)
640     return -1;
641
642   if(aop->type !=  AOP_REG)
643     return -2;
644         
645   return aop->aopu.aop_reg[offset]->rIdx;
646
647 }
648 /*-----------------------------------------------------------------*/
649 /* regsInCommon - two operands have some registers in common       */
650 /*-----------------------------------------------------------------*/
651 static bool regsInCommon (operand *op1, operand *op2)
652 {
653     symbol *sym1, *sym2;
654     int i;
655
656     /* if they have registers in common */
657     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
658         return FALSE ;
659
660     sym1 = OP_SYMBOL(op1);
661     sym2 = OP_SYMBOL(op2);
662
663     if (sym1->nRegs == 0 || sym2->nRegs == 0)
664         return FALSE ;
665
666     for (i = 0 ; i < sym1->nRegs ; i++) {
667         int j;
668         if (!sym1->regs[i])
669             continue ;
670
671         for (j = 0 ; j < sym2->nRegs ;j++ ) {
672             if (!sym2->regs[j])
673                 continue ;
674
675             if (sym2->regs[j] == sym1->regs[i])
676                 return TRUE ;
677         }
678     }
679
680     return FALSE ;
681 }
682
683 /*-----------------------------------------------------------------*/
684 /* operandsEqu - equivalent                                        */
685 /*-----------------------------------------------------------------*/
686 static bool operandsEqu ( operand *op1, operand *op2)
687 {
688     symbol *sym1, *sym2;
689
690     /* if they not symbols */
691     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
692         return FALSE;
693
694     sym1 = OP_SYMBOL(op1);
695     sym2 = OP_SYMBOL(op2);
696
697     /* if both are itemps & one is spilt
698        and the other is not then false */
699     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
700         sym1->isspilt != sym2->isspilt )
701         return FALSE ;
702
703     /* if they are the same */
704     if (sym1 == sym2)
705         return TRUE ;
706
707     if (strcmp(sym1->rname,sym2->rname) == 0)
708         return TRUE;
709
710
711     /* if left is a tmp & right is not */
712     if (IS_ITEMP(op1)  && 
713         !IS_ITEMP(op2) &&
714         sym1->isspilt  &&
715         (sym1->usl.spillLoc == sym2))
716         return TRUE;
717
718     if (IS_ITEMP(op2)  && 
719         !IS_ITEMP(op1) &&
720         sym2->isspilt  &&
721         sym1->level > 0 &&
722         (sym2->usl.spillLoc == sym1))
723         return TRUE ;
724
725     return FALSE ;
726 }
727
728 /*-----------------------------------------------------------------*/
729 /* pic16_sameRegs - two asmops have the same registers                   */
730 /*-----------------------------------------------------------------*/
731 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
732 {
733     int i;
734
735     if (aop1 == aop2)
736         return TRUE ;
737
738     if (aop1->type != AOP_REG ||
739         aop2->type != AOP_REG )
740         return FALSE ;
741
742     if (aop1->size != aop2->size )
743         return FALSE ;
744
745     for (i = 0 ; i < aop1->size ; i++ )
746         if (aop1->aopu.aop_reg[i] !=
747             aop2->aopu.aop_reg[i] )
748             return FALSE ;
749
750     return TRUE ;
751 }
752
753 /*-----------------------------------------------------------------*/
754 /* pic16_aopOp - allocates an asmop for an operand  :                    */
755 /*-----------------------------------------------------------------*/
756 void pic16_aopOp (operand *op, iCode *ic, bool result)
757 {
758     asmop *aop;
759     symbol *sym;
760     int i;
761
762     if (!op)
763         return ;
764
765 //      DEBUGpic16_emitcode(";","%d",__LINE__);
766
767     /* if this a literal */
768     if (IS_OP_LITERAL(op)) {
769         op->aop = aop = newAsmop(AOP_LIT);
770         aop->aopu.aop_lit = op->operand.valOperand;
771         aop->size = getSize(operandType(op));
772         return;
773     }
774
775     {
776       sym_link *type = operandType(op);
777 #if 0
778       if(IS_PTR_CONST(type))
779 #else
780       if(IS_CODEPTR(type))
781 #endif
782         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
783     }
784
785     /* if already has a asmop then continue */
786     if (op->aop)
787         return ;
788
789     /* if the underlying symbol has a aop */
790     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
791       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
792         op->aop = OP_SYMBOL(op)->aop;
793         return;
794     }
795
796     /* if this is a true symbol */
797     if (IS_TRUE_SYMOP(op)) {    
798         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
799       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
800       return ;
801     }
802
803     /* this is a temporary : this has
804     only four choices :
805     a) register
806     b) spillocation
807     c) rematerialize 
808     d) conditional   
809     e) can be a return use only */
810
811     sym = OP_SYMBOL(op);
812
813         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
814     /* if the type is a conditional */
815     if (sym->regType == REG_CND) {
816         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
817         aop->size = 0;
818         return;
819     }
820
821     /* if it is spilt then two situations
822     a) is rematerialize 
823     b) has a spill location */
824     if (sym->isspilt || sym->nRegs == 0) {
825
826       DEBUGpic16_emitcode(";","%d",__LINE__);
827         /* rematerialize it NOW */
828         if (sym->remat) {
829
830             sym->aop = op->aop = aop =
831                                       aopForRemat (op);
832             aop->size = getSize(sym->type);
833             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
834             return;
835         }
836
837         if (sym->accuse) {
838             int i;
839             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
840             aop->size = getSize(sym->type);
841             for ( i = 0 ; i < 2 ; i++ )
842                 aop->aopu.aop_str[i] = accUse[i];
843             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
844             return;  
845         }
846
847         if (sym->ruonly ) {
848           /*
849           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
850           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
851           //pic16_allocDirReg (IC_LEFT(ic));
852           aop->size = getSize(sym->type);
853           */
854
855           unsigned i;
856
857           aop = op->aop = sym->aop = newAsmop(AOP_STR);
858           aop->size = getSize(sym->type);
859           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
860             aop->aopu.aop_str[i] = fReturn[i];
861
862           DEBUGpic16_emitcode(";","%d",__LINE__);
863           return;
864         }
865
866         /* else spill location  */
867         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
868             /* force a new aop if sizes differ */
869             sym->usl.spillLoc->aop = NULL;
870         }
871         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
872                             __FUNCTION__,__LINE__,
873                             sym->usl.spillLoc->rname,
874                             sym->rname, sym->usl.spillLoc->offset);
875
876         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
877         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
878         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
879                                           getSize(sym->type), 
880                                           sym->usl.spillLoc->offset);
881         aop->size = getSize(sym->type);
882
883         return;
884     }
885
886     {
887       sym_link *type = operandType(op);
888 #if 0
889       if(IS_PTR_CONST(type)) 
890 #else
891       if(IS_CODEPTR(type)) 
892 #endif
893         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
894     }
895
896     /* must be in a register */
897     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
898     sym->aop = op->aop = aop = newAsmop(AOP_REG);
899     aop->size = sym->nRegs;
900     for ( i = 0 ; i < sym->nRegs ;i++)
901         aop->aopu.aop_reg[i] = sym->regs[i];
902 }
903
904 /*-----------------------------------------------------------------*/
905 /* pic16_freeAsmop - free up the asmop given to an operand               */
906 /*----------------------------------------------------------------*/
907 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
908 {   
909     asmop *aop ;
910
911     if (!op)
912         aop = aaop;
913     else 
914         aop = op->aop;
915
916     if (!aop)
917         return ;
918
919     if (aop->freed)
920         goto dealloc; 
921
922     aop->freed = 1;
923
924     /* depending on the asmop type only three cases need work AOP_RO
925        , AOP_R1 && AOP_STK */
926 #if 0
927     switch (aop->type) {
928         case AOP_R0 :
929             if (_G.r0Pushed ) {
930                 if (pop) {
931                     pic16_emitcode ("pop","ar0");     
932                     _G.r0Pushed--;
933                 }
934             }
935             bitVectUnSetBit(ic->rUsed,R0_IDX);
936             break;
937
938         case AOP_R1 :
939             if (_G.r1Pushed ) {
940                 if (pop) {
941                     pic16_emitcode ("pop","ar1");
942                     _G.r1Pushed--;
943                 }
944             }
945             bitVectUnSetBit(ic->rUsed,R1_IDX);          
946             break;
947
948         case AOP_STK :
949         {
950             int sz = aop->size;    
951             int stk = aop->aopu.aop_stk + aop->size;
952             bitVectUnSetBit(ic->rUsed,R0_IDX);
953             bitVectUnSetBit(ic->rUsed,R1_IDX);          
954
955             getFreePtr(ic,&aop,FALSE);
956             
957             if (options.stack10bit)
958             {
959                 /* I'm not sure what to do here yet... */
960                 /* #STUB */
961                 fprintf(stderr, 
962                         "*** Warning: probably generating bad code for "
963                         "10 bit stack mode.\n");
964             }
965             
966             if (stk) {
967                 pic16_emitcode ("mov","a,_bp");
968                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
969                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
970             } else {
971                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
972             }
973
974             while (sz--) {
975                 pic16_emitcode("pop","acc");
976                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
977                 if (!sz) break;
978                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
979             }
980             op->aop = aop;
981             pic16_freeAsmop(op,NULL,ic,TRUE);
982             if (_G.r0Pushed) {
983                 pic16_emitcode("pop","ar0");
984                 _G.r0Pushed--;
985             }
986
987             if (_G.r1Pushed) {
988                 pic16_emitcode("pop","ar1");
989                 _G.r1Pushed--;
990             }       
991         }
992     }
993 #endif
994
995 dealloc:
996     /* all other cases just dealloc */
997     if (op ) {
998         op->aop = NULL;
999         if (IS_SYMOP(op)) {
1000             OP_SYMBOL(op)->aop = NULL;    
1001             /* if the symbol has a spill */
1002             if (SPIL_LOC(op))
1003                 SPIL_LOC(op)->aop = NULL;
1004         }
1005     }
1006 }
1007
1008 /*-----------------------------------------------------------------*/
1009 /* pic16_aopGet - for fetching value of the aop                          */
1010 /*-----------------------------------------------------------------*/
1011 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1012 {
1013     char *s = buffer ;
1014     char *rs;
1015
1016     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1017     /* offset is greater than
1018     size then zero */
1019     if (offset > (aop->size - 1) &&
1020         aop->type != AOP_LIT)
1021         return zero;
1022
1023     /* depending on type */
1024     switch (aop->type) {
1025         
1026     case AOP_R0:
1027     case AOP_R1:
1028         DEBUGpic16_emitcode(";","%d",__LINE__);
1029         /* if we need to increment it */       
1030         while (offset > aop->coff) {        
1031             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1032             aop->coff++;
1033         }
1034         
1035         while (offset < aop->coff) {
1036             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1037             aop->coff--;
1038         }
1039         
1040         aop->coff = offset ;
1041         if (aop->paged) {
1042             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1043             return (dname ? "acc" : "a");
1044         }       
1045         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1046         rs = Safe_calloc(1,strlen(s)+1);
1047         strcpy(rs,s);   
1048         return rs;
1049         
1050     case AOP_DPTR:
1051     case AOP_DPTR2:
1052         DEBUGpic16_emitcode(";","%d",__LINE__);
1053     if (aop->type == AOP_DPTR2)
1054     {
1055         genSetDPTR(1);
1056     }
1057     
1058         while (offset > aop->coff) {
1059             pic16_emitcode ("inc","dptr");
1060             aop->coff++;
1061         }
1062         
1063         while (offset < aop->coff) {        
1064             pic16_emitcode("lcall","__decdptr");
1065             aop->coff--;
1066         }
1067         
1068         aop->coff = offset;
1069         if (aop->code) {
1070             pic16_emitcode("clr","a");
1071             pic16_emitcode("movc","a,@a+dptr");
1072         }
1073     else {
1074             pic16_emitcode("movx","a,@dptr");
1075     }
1076             
1077     if (aop->type == AOP_DPTR2)
1078     {
1079         genSetDPTR(0);
1080     }
1081             
1082     return (dname ? "acc" : "a");
1083         
1084         
1085     case AOP_IMMD:
1086         if (bit16) 
1087             sprintf (s,"%s",aop->aopu.aop_immd);
1088         else
1089             if (offset) 
1090                 sprintf(s,"(%s >> %d)",
1091                         aop->aopu.aop_immd,
1092                         offset*8);
1093             else
1094                 sprintf(s,"%s",
1095                         aop->aopu.aop_immd);
1096         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1097         rs = Safe_calloc(1,strlen(s)+1);
1098         strcpy(rs,s);   
1099         return rs;
1100         
1101     case AOP_DIR:
1102       if (offset) {
1103         sprintf(s,"(%s + %d)",
1104                 aop->aopu.aop_dir,
1105                 offset);
1106         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1107       } else
1108             sprintf(s,"%s",aop->aopu.aop_dir);
1109         rs = Safe_calloc(1,strlen(s)+1);
1110         strcpy(rs,s);   
1111         return rs;
1112         
1113     case AOP_REG:
1114       //if (dname) 
1115       //    return aop->aopu.aop_reg[offset]->dname;
1116       //else
1117             return aop->aopu.aop_reg[offset]->name;
1118         
1119     case AOP_CRY:
1120       //pic16_emitcode(";","%d",__LINE__);
1121       return aop->aopu.aop_dir;
1122         
1123     case AOP_ACC:
1124         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1125         return "AOP_accumulator_bug";
1126
1127     case AOP_LIT:
1128         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1129         rs = Safe_calloc(1,strlen(s)+1);
1130         strcpy(rs,s);   
1131         return rs;
1132         
1133     case AOP_STR:
1134         aop->coff = offset ;
1135         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1136             dname)
1137             return "acc";
1138         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1139         
1140         return aop->aopu.aop_str[offset];
1141         
1142     case AOP_PCODE:
1143       {
1144         pCodeOp *pcop = aop->aopu.pcop;
1145         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1146         if(pcop->name) {
1147           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1148           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1149           sprintf(s,"%s", pcop->name);
1150         } else
1151           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1152
1153       }
1154       rs = Safe_calloc(1,strlen(s)+1);
1155       strcpy(rs,s);   
1156       return rs;
1157
1158     }
1159
1160     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1161            "aopget got unsupported aop->type");
1162     exit(0);
1163 }
1164
1165
1166 /*-----------------------------------------------------------------*/
1167 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1168 /*-----------------------------------------------------------------*/
1169 pCodeOp *pic16_popGetTempReg(void)
1170 {
1171
1172   pCodeOp *pcop;
1173
1174   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1175   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1176     PCOR(pcop)->r->wasUsed=1;
1177     PCOR(pcop)->r->isFree=0;
1178   }
1179
1180   return pcop;
1181 }
1182
1183 /*-----------------------------------------------------------------*/
1184 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1185 /*-----------------------------------------------------------------*/
1186 void pic16_popReleaseTempReg(pCodeOp *pcop)
1187 {
1188
1189   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1190     PCOR(pcop)->r->isFree = 1;
1191
1192 }
1193 /*-----------------------------------------------------------------*/
1194 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1195 /*-----------------------------------------------------------------*/
1196 pCodeOp *pic16_popGetLabel(unsigned int key)
1197 {
1198
1199   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1200
1201   if(key>max_key)
1202     max_key = key;
1203
1204   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1205 }
1206
1207 /*-----------------------------------------------------------------*/
1208 /* pic16_popCopyReg - copy a pcode operator                              */
1209 /*-----------------------------------------------------------------*/
1210 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1211 {
1212   pCodeOpReg *pcor;
1213
1214   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1215   pcor->pcop.type = pc->pcop.type;
1216   if(pc->pcop.name) {
1217     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1218       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1219   } else
1220     pcor->pcop.name = NULL;
1221
1222   pcor->r = pc->r;
1223   pcor->rIdx = pc->rIdx;
1224   pcor->r->wasUsed=1;
1225
1226   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1227
1228   return PCOP(pcor);
1229 }
1230
1231 /*-----------------------------------------------------------------*/
1232 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1233 /*-----------------------------------------------------------------*/
1234 pCodeOp *pic16_popGetLit(unsigned int lit)
1235 {
1236   return pic16_newpCodeOpLit(lit);
1237 }
1238
1239 /*-----------------------------------------------------------------*/
1240 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1241 /*-----------------------------------------------------------------*/
1242 pCodeOp *pic16_popGetLit2(unsigned int lit, unsigned int lit2)
1243 {
1244   return pic16_newpCodeOpLit2(lit, lit2);
1245 }
1246
1247
1248 /*-----------------------------------------------------------------*/
1249 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1250 /*-----------------------------------------------------------------*/
1251 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1252 {
1253
1254   return pic16_newpCodeOpImmd(name, offset,index, 0);
1255 }
1256
1257
1258 /*-----------------------------------------------------------------*/
1259 /* pic16_popGet - asm operator to pcode operator conversion              */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *pic16_popGetWithString(char *str)
1262 {
1263   pCodeOp *pcop;
1264
1265
1266   if(!str) {
1267     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1268     exit (1);
1269   }
1270
1271   pcop = pic16_newpCodeOp(str,PO_STR);
1272
1273   return pcop;
1274 }
1275
1276 /*-----------------------------------------------------------------*/
1277 /* pic16_popRegFromString -                                        */
1278 /*-----------------------------------------------------------------*/
1279 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1280 {
1281
1282   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1283   pcop->type = PO_DIR;
1284
1285   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1286 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1287
1288   if(!str)
1289     str = "BAD_STRING";
1290
1291   pcop->name = Safe_calloc(1,strlen(str)+1);
1292   strcpy(pcop->name,str);
1293
1294   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1295
1296   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1297   if(PCOR(pcop)->r == NULL) {
1298 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1299 //              __FUNCTION__, __LINE__, str, size, offset);
1300     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1301
1302         //fprintf(stderr, "allocating new register -> %s\n", str);
1303
1304     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1305   } else {
1306     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1307   }
1308   PCOR(pcop)->instance = offset;
1309
1310   return pcop;
1311 }
1312
1313 static pCodeOp *popRegFromIdx(int rIdx)
1314 {
1315   pCodeOp *pcop;
1316
1317   DEBUGpic16_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1318                        __FUNCTION__,__LINE__,rIdx);
1319
1320   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1321
1322   PCOR(pcop)->rIdx = rIdx;
1323   PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1324   PCOR(pcop)->r->isFree = 0;
1325   PCOR(pcop)->r->wasUsed = 1;
1326
1327   pcop->type = PCOR(pcop)->r->pc_type;
1328
1329
1330   return pcop;
1331 }
1332
1333 /*---------------------------------------------------------------------------------*/
1334 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1335 /*                 VR 030601                                                       */
1336 /*---------------------------------------------------------------------------------*/
1337 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1338 {
1339   pCodeOpReg2 *pcop2;
1340   pCodeOp *temp;
1341   
1342         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1343         temp = pic16_popGet(aop_dst, offset);
1344         pcop2->pcop2 = temp;
1345         
1346   return PCOP(pcop2);
1347 }
1348
1349 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst)
1350 {
1351   pCodeOpReg2 *pcop2;
1352
1353         pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1354         pcop2->pcop2 = pic16_popCopyReg(dst);
1355
1356   return PCOP(pcop2);
1357 }
1358
1359 /*-----------------------------------------------------------------*/
1360 /* pic16_popGet - asm operator to pcode operator conversion              */
1361 /*-----------------------------------------------------------------*/
1362 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1363 {
1364   //char *s = buffer ;
1365     //char *rs;
1366
1367     pCodeOp *pcop;
1368
1369     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1370     /* offset is greater than
1371     size then zero */
1372
1373     if (offset > (aop->size - 1) &&
1374         aop->type != AOP_LIT)
1375       return NULL;  //zero;
1376
1377     /* depending on type */
1378     switch (aop->type) {
1379         
1380     case AOP_R0:
1381     case AOP_R1:
1382     case AOP_DPTR:
1383     case AOP_DPTR2:
1384     case AOP_ACC:
1385         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1386         return NULL;
1387         
1388     case AOP_IMMD:
1389       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1390       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1391
1392     case AOP_DIR:
1393       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1394       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1395         
1396     case AOP_REG:
1397       {
1398         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1399
1400         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1401         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1402         PCOR(pcop)->rIdx = rIdx;
1403         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1404         PCOR(pcop)->r->wasUsed=1;
1405         PCOR(pcop)->r->isFree=0;
1406
1407         PCOR(pcop)->instance = offset;
1408         pcop->type = PCOR(pcop)->r->pc_type;
1409         //rs = aop->aopu.aop_reg[offset]->name;
1410         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1411         return pcop;
1412       }
1413
1414     case AOP_CRY:
1415         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1416
1417       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1418       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1419       //if(PCOR(pcop)->r == NULL)
1420       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1421       return pcop;
1422         
1423     case AOP_LIT:
1424         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1425       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1426
1427     case AOP_STR:
1428       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1429       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1430
1431       /*
1432       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1433       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1434       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1435       pcop->type = PCOR(pcop)->r->pc_type;
1436       pcop->name = PCOR(pcop)->r->name;
1437
1438       return pcop;
1439       */
1440
1441     case AOP_PCODE:
1442       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1443                           __LINE__, 
1444                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1445       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1446       PCOI(pcop)->offset = offset;
1447       return pcop;
1448     }
1449
1450     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1451            "pic16_popGet got unsupported aop->type");
1452     exit(0);
1453 }
1454 /*-----------------------------------------------------------------*/
1455 /* pic16_aopPut - puts a string for a aop                                */
1456 /*-----------------------------------------------------------------*/
1457 void pic16_aopPut (asmop *aop, char *s, int offset)
1458 {
1459     char *d = buffer ;
1460     symbol *lbl ;
1461
1462     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1463
1464     if (aop->size && offset > ( aop->size - 1)) {
1465         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1466                "pic16_aopPut got offset > aop->size");
1467         exit(0);
1468     }
1469
1470     /* will assign value to value */
1471     /* depending on where it is ofcourse */
1472     switch (aop->type) {
1473     case AOP_DIR:
1474       if (offset) {
1475         sprintf(d,"(%s + %d)",
1476                 aop->aopu.aop_dir,offset);
1477         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1478
1479       } else
1480             sprintf(d,"%s",aop->aopu.aop_dir);
1481         
1482         if (strcmp(d,s)) {
1483           DEBUGpic16_emitcode(";","%d",__LINE__);
1484           if(strcmp(s,"W"))
1485             pic16_emitcode("movf","%s,w",s);
1486           pic16_emitcode("movwf","%s",d);
1487
1488           if(strcmp(s,"W")) {
1489             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1490             if(offset >= aop->size) {
1491               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1492               break;
1493             } else
1494               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1495           }
1496
1497           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1498
1499
1500         }
1501         break;
1502         
1503     case AOP_REG:
1504       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1505         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1506           /*
1507             if (*s == '@'           ||
1508                 strcmp(s,"r0") == 0 ||
1509                 strcmp(s,"r1") == 0 ||
1510                 strcmp(s,"r2") == 0 ||
1511                 strcmp(s,"r3") == 0 ||
1512                 strcmp(s,"r4") == 0 ||
1513                 strcmp(s,"r5") == 0 ||
1514                 strcmp(s,"r6") == 0 || 
1515                 strcmp(s,"r7") == 0 )
1516                 pic16_emitcode("mov","%s,%s  ; %d",
1517                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1518             else
1519           */
1520
1521           if(strcmp(s,"W")==0 )
1522             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1523
1524           pic16_emitcode("movwf","%s",
1525                    aop->aopu.aop_reg[offset]->name);
1526
1527           if(strcmp(s,zero)==0) {
1528             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1529
1530           } else if(strcmp(s,"W")==0) {
1531             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1532             pcop->type = PO_GPR_REGISTER;
1533
1534             PCOR(pcop)->rIdx = -1;
1535             PCOR(pcop)->r = NULL;
1536
1537             DEBUGpic16_emitcode(";","%d",__LINE__);
1538             pcop->name = Safe_strdup(s);
1539             pic16_emitpcode(POC_MOVFW,pcop);
1540             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1541           } else if(strcmp(s,one)==0) {
1542             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1543             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1544           } else {
1545             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1546           }
1547         }
1548         break;
1549         
1550     case AOP_DPTR:
1551     case AOP_DPTR2:
1552     
1553     if (aop->type == AOP_DPTR2)
1554     {
1555         genSetDPTR(1);
1556     }
1557     
1558         if (aop->code) {
1559             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1560                    "pic16_aopPut writting to code space");
1561             exit(0);
1562         }
1563         
1564         while (offset > aop->coff) {
1565             aop->coff++;
1566             pic16_emitcode ("inc","dptr");
1567         }
1568         
1569         while (offset < aop->coff) {
1570             aop->coff-- ;
1571             pic16_emitcode("lcall","__decdptr");
1572         }
1573         
1574         aop->coff = offset;
1575         
1576         /* if not in accumulater */
1577         MOVA(s);        
1578         
1579         pic16_emitcode ("movx","@dptr,a");
1580         
1581     if (aop->type == AOP_DPTR2)
1582     {
1583         genSetDPTR(0);
1584     }
1585         break;
1586         
1587     case AOP_R0:
1588     case AOP_R1:
1589         while (offset > aop->coff) {
1590             aop->coff++;
1591             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1592         }
1593         while (offset < aop->coff) {
1594             aop->coff-- ;
1595             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1596         }
1597         aop->coff = offset;
1598         
1599         if (aop->paged) {
1600             MOVA(s);           
1601             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1602             
1603         } else
1604             if (*s == '@') {
1605                 MOVA(s);
1606                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1607             } else
1608                 if (strcmp(s,"r0") == 0 ||
1609                     strcmp(s,"r1") == 0 ||
1610                     strcmp(s,"r2") == 0 ||
1611                     strcmp(s,"r3") == 0 ||
1612                     strcmp(s,"r4") == 0 ||
1613                     strcmp(s,"r5") == 0 ||
1614                     strcmp(s,"r6") == 0 || 
1615                     strcmp(s,"r7") == 0 ) {
1616                     char buffer[10];
1617                     sprintf(buffer,"a%s",s);
1618                     pic16_emitcode("mov","@%s,%s",
1619                              aop->aopu.aop_ptr->name,buffer);
1620                 } else
1621                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1622         
1623         break;
1624         
1625     case AOP_STK:
1626         if (strcmp(s,"a") == 0)
1627             pic16_emitcode("push","acc");
1628         else
1629             pic16_emitcode("push","%s",s);
1630         
1631         break;
1632         
1633     case AOP_CRY:
1634         /* if bit variable */
1635         if (!aop->aopu.aop_dir) {
1636             pic16_emitcode("clr","a");
1637             pic16_emitcode("rlc","a");
1638         } else {
1639             if (s == zero) 
1640                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1641             else
1642                 if (s == one)
1643                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1644                 else
1645                     if (!strcmp(s,"c"))
1646                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1647                     else {
1648                         lbl = newiTempLabel(NULL);
1649                         
1650                         if (strcmp(s,"a")) {
1651                             MOVA(s);
1652                         }
1653                         pic16_emitcode("clr","c");
1654                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1655                         pic16_emitcode("cpl","c");
1656                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1657                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1658                     }
1659         }
1660         break;
1661         
1662     case AOP_STR:
1663         aop->coff = offset;
1664         if (strcmp(aop->aopu.aop_str[offset],s))
1665             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1666         break;
1667         
1668     case AOP_ACC:
1669         aop->coff = offset;
1670         if (!offset && (strcmp(s,"acc") == 0))
1671             break;
1672         
1673         if (strcmp(aop->aopu.aop_str[offset],s))
1674             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1675         break;
1676
1677     default :
1678         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1679                "pic16_aopPut got unsupported aop->type");
1680         exit(0);    
1681     }    
1682
1683 }
1684
1685 /*-----------------------------------------------------------------*/
1686 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1687 /*-----------------------------------------------------------------*/
1688 static void mov2w (asmop *aop, int offset)
1689 {
1690
1691   if(!aop)
1692     return;
1693
1694   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1695
1696   if ( aop->type == AOP_PCODE ||
1697        aop->type == AOP_LIT )
1698     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1699   else
1700     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1701
1702 }
1703
1704
1705 /*-----------------------------------------------------------------*/
1706 /* pushw - pushes wreg to stack                                    */
1707 /*-----------------------------------------------------------------*/
1708 void pushw(void)
1709 {
1710         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1711         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1712 }
1713
1714                 
1715 /*-----------------------------------------------------------------*/
1716 /* pushaop - pushes aop to stack                                   */
1717 /*-----------------------------------------------------------------*/
1718 void pushaop(asmop *aop, int offset)
1719 {
1720         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1721         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1));
1722 }
1723
1724 #if 0
1725 /*-----------------------------------------------------------------*/
1726 /* popaop - pops aop from stack                                    */
1727 /*-----------------------------------------------------------------*/
1728 void popaop(asmop *aop, int offset)
1729 {
1730         DEBUG
1731 }
1732 #endif
1733
1734 void popaopidx(asmop *aop, int offset, int index)
1735 {
1736   int ofs=1;
1737
1738         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1739
1740         if(STACK_MODEL_LARGE)ofs++;
1741
1742         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1743         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset))));
1744 }
1745
1746 /*-----------------------------------------------------------------*/
1747 /* reAdjustPreg - points a register back to where it should        */
1748 /*-----------------------------------------------------------------*/
1749 static void reAdjustPreg (asmop *aop)
1750 {
1751     int size ;
1752
1753     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1754     aop->coff = 0;
1755     if ((size = aop->size) <= 1)
1756         return ;
1757     size-- ;
1758     switch (aop->type) {
1759         case AOP_R0 :
1760         case AOP_R1 :
1761             while (size--)
1762                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1763             break;          
1764         case AOP_DPTR :
1765         case AOP_DPTR2:
1766             if (aop->type == AOP_DPTR2)
1767             {
1768                 genSetDPTR(1);
1769             } 
1770             while (size--)
1771             {
1772                 pic16_emitcode("lcall","__decdptr");
1773             }
1774                 
1775             if (aop->type == AOP_DPTR2)
1776             {
1777                 genSetDPTR(0);
1778             }                
1779             break;  
1780
1781     }   
1782
1783 }
1784
1785
1786 #if 0
1787 /*-----------------------------------------------------------------*/
1788 /* opIsGptr: returns non-zero if the passed operand is             */   
1789 /* a generic pointer type.                                         */
1790 /*-----------------------------------------------------------------*/ 
1791 static int opIsGptr(operand *op)
1792 {
1793     sym_link *type = operandType(op);
1794     
1795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1796     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1797     {
1798         return 1;
1799     }
1800     return 0;        
1801 }
1802 #endif
1803
1804 /*-----------------------------------------------------------------*/
1805 /* pic16_getDataSize - get the operand data size                         */
1806 /*-----------------------------------------------------------------*/
1807 int pic16_getDataSize(operand *op)
1808 {
1809     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1810
1811
1812     return AOP_SIZE(op);
1813
1814     // tsd- in the pic port, the genptr size is 1, so this code here
1815     // fails. ( in the 8051 port, the size was 4).
1816 #if 0
1817     int size;
1818     size = AOP_SIZE(op);
1819     if (size == GPTRSIZE)
1820     {
1821         sym_link *type = operandType(op);
1822         if (IS_GENPTR(type))
1823         {
1824             /* generic pointer; arithmetic operations
1825              * should ignore the high byte (pointer type).
1826              */
1827             size--;
1828     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1829         }
1830     }
1831     return size;
1832 #endif
1833 }
1834
1835 /*-----------------------------------------------------------------*/
1836 /* pic16_outAcc - output Acc                                             */
1837 /*-----------------------------------------------------------------*/
1838 void pic16_outAcc(operand *result)
1839 {
1840   int size,offset;
1841   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1842   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1843
1844
1845   size = pic16_getDataSize(result);
1846   if(size){
1847     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1848     size--;
1849     offset = 1;
1850     /* unsigned or positive */
1851     while(size--)
1852       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1853   }
1854
1855 }
1856
1857 /*-----------------------------------------------------------------*/
1858 /* pic16_outBitC - output a bit C                                        */
1859 /*-----------------------------------------------------------------*/
1860 void pic16_outBitC(operand *result)
1861 {
1862
1863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1864     /* if the result is bit */
1865     if (AOP_TYPE(result) == AOP_CRY) 
1866         pic16_aopPut(AOP(result),"c",0);
1867     else {
1868         pic16_emitcode("clr","a  ; %d", __LINE__);
1869         pic16_emitcode("rlc","a");
1870         pic16_outAcc(result);
1871     }
1872 }
1873
1874 /*-----------------------------------------------------------------*/
1875 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1876 /*-----------------------------------------------------------------*/
1877 void pic16_toBoolean(operand *oper)
1878 {
1879     int size = AOP_SIZE(oper) - 1;
1880     int offset = 1;
1881
1882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1883
1884     if ( AOP_TYPE(oper) != AOP_ACC) {
1885       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1886     }
1887     while (size--) {
1888       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1889     }
1890 }
1891
1892
1893 #if !defined(GEN_Not)
1894 /*-----------------------------------------------------------------*/
1895 /* genNot - generate code for ! operation                          */
1896 /*-----------------------------------------------------------------*/
1897 static void pic16_genNot (iCode *ic)
1898 {
1899   symbol *tlbl;
1900   int size;
1901
1902   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1903   /* assign asmOps to operand & result */
1904   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1905   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1906
1907   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1908   /* if in bit space then a special case */
1909   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1910     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1911       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1912       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1913     } else {
1914       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1915       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1916       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1917     }
1918     goto release;
1919   }
1920
1921   size = AOP_SIZE(IC_LEFT(ic));
1922   if(size == 1) {
1923     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1924     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1925     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1926     goto release;
1927   }
1928   pic16_toBoolean(IC_LEFT(ic));
1929
1930   tlbl = newiTempLabel(NULL);
1931   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1932   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1933   pic16_outBitC(IC_RESULT(ic));
1934
1935  release:    
1936   /* release the aops */
1937   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1938   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1939 }
1940 #endif
1941
1942
1943 #if !defined(GEN_Cpl)
1944 /*-----------------------------------------------------------------*/
1945 /* genCpl - generate code for complement                           */
1946 /*-----------------------------------------------------------------*/
1947 static void pic16_genCpl (iCode *ic)
1948 {
1949     int offset = 0;
1950     int size ;
1951
1952
1953     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1954     /* assign asmOps to operand & result */
1955     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1956     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1957
1958     /* if both are in bit space then 
1959     a special case */
1960     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1961         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1962
1963         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1964         pic16_emitcode("cpl","c"); 
1965         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1966         goto release; 
1967     } 
1968
1969     size = AOP_SIZE(IC_RESULT(ic));
1970     while (size--) {
1971 /*
1972         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1973         MOVA(l);       
1974         pic16_emitcode("cpl","a");
1975         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1976 */
1977         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1978               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
1979         } else {
1980                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
1981                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1982         }
1983         offset++;
1984
1985     }
1986
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 /* genUminusFloat - unary minus for floating points                */
1997 /*-----------------------------------------------------------------*/
1998 static void genUminusFloat(operand *op,operand *result)
1999 {
2000     int size ,offset =0 ;
2001     char *l;
2002
2003     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2004     /* for this we just need to flip the 
2005     first it then copy the rest in place */
2006     size = AOP_SIZE(op) - 1;
2007     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2008
2009     MOVA(l);    
2010
2011     pic16_emitcode("cpl","acc.7");
2012     pic16_aopPut(AOP(result),"a",3);    
2013
2014     while(size--) {
2015         pic16_aopPut(AOP(result),
2016                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2017                offset);
2018         offset++;
2019     }          
2020 }
2021
2022 /*-----------------------------------------------------------------*/
2023 /* genUminus - unary minus code generation                         */
2024 /*-----------------------------------------------------------------*/
2025 static void genUminus (iCode *ic)
2026 {
2027   int size, i;
2028   sym_link *optype, *rtype;
2029
2030
2031   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2032   /* assign asmops */
2033   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2034   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2035
2036   /* if both in bit space then special
2037      case */
2038   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2039       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2040
2041     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2042     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2043     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2044
2045     goto release; 
2046   } 
2047
2048   optype = operandType(IC_LEFT(ic));
2049   rtype = operandType(IC_RESULT(ic));
2050
2051   /* if float then do float stuff */
2052   if (IS_FLOAT(optype)) {
2053     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2054     goto release;
2055   }
2056
2057   /* otherwise subtract from zero by taking the 2's complement */
2058   size = AOP_SIZE(IC_LEFT(ic));
2059
2060   for(i=0; i<size; i++) {
2061     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2062       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2063     else {
2064       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2065       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2066     }
2067   }
2068
2069   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2070   for(i=1; i<size; i++) {
2071     emitSKPNZ;
2072     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2073   }
2074
2075  release:
2076   /* release the aops */
2077   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2078   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2079 }
2080
2081 /*-----------------------------------------------------------------*/
2082 /* saveRegisters - will look for a call and save the registers     */
2083 /*-----------------------------------------------------------------*/
2084 static void saveRegisters(iCode *lic) 
2085 {
2086     int i;
2087     iCode *ic;
2088     bitVect *rsave;
2089     sym_link *dtype;
2090
2091     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2092     /* look for call */
2093     for (ic = lic ; ic ; ic = ic->next) 
2094         if (ic->op == CALL || ic->op == PCALL)
2095             break;
2096
2097     if (!ic) {
2098         fprintf(stderr,"found parameter push with no function call\n");
2099         return ;
2100     }
2101
2102     /* if the registers have been saved already then
2103     do nothing */
2104     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2105         return ;
2106
2107     /* find the registers in use at this time 
2108     and push them away to safety */
2109     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2110                           ic->rUsed);
2111
2112     ic->regsSaved = 1;
2113     if (options.useXstack) {
2114         if (bitVectBitValue(rsave,R0_IDX))
2115             pic16_emitcode("mov","b,r0");
2116         pic16_emitcode("mov","r0,%s",spname);
2117         for (i = 0 ; i < pic16_nRegs ; i++) {
2118             if (bitVectBitValue(rsave,i)) {
2119                 if (i == R0_IDX)
2120                     pic16_emitcode("mov","a,b");
2121                 else
2122                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2123                 pic16_emitcode("movx","@r0,a");
2124                 pic16_emitcode("inc","r0");
2125             }
2126         }
2127         pic16_emitcode("mov","%s,r0",spname);
2128         if (bitVectBitValue(rsave,R0_IDX))
2129             pic16_emitcode("mov","r0,b");           
2130     }// else
2131     //for (i = 0 ; i < pic16_nRegs ; i++) {
2132     //    if (bitVectBitValue(rsave,i))
2133     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2134     //}
2135
2136     dtype = operandType(IC_LEFT(ic));
2137     if (currFunc && dtype && 
2138         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2139         IFFUNC_ISISR(currFunc->type) &&
2140         !ic->bankSaved) 
2141
2142         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2143
2144 }
2145 /*-----------------------------------------------------------------*/
2146 /* unsaveRegisters - pop the pushed registers                      */
2147 /*-----------------------------------------------------------------*/
2148 static void unsaveRegisters (iCode *ic)
2149 {
2150     int i;
2151     bitVect *rsave;
2152
2153     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2154     /* find the registers in use at this time 
2155     and push them away to safety */
2156     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2157                           ic->rUsed);
2158     
2159     if (options.useXstack) {
2160         pic16_emitcode("mov","r0,%s",spname);   
2161         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2162             if (bitVectBitValue(rsave,i)) {
2163                 pic16_emitcode("dec","r0");
2164                 pic16_emitcode("movx","a,@r0");
2165                 if (i == R0_IDX)
2166                     pic16_emitcode("mov","b,a");
2167                 else
2168                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2169             }       
2170
2171         }
2172         pic16_emitcode("mov","%s,r0",spname);
2173         if (bitVectBitValue(rsave,R0_IDX))
2174             pic16_emitcode("mov","r0,b");
2175     } //else
2176     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2177     //    if (bitVectBitValue(rsave,i))
2178     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2179     //}
2180
2181 }  
2182
2183
2184 /*-----------------------------------------------------------------*/
2185 /* pushSide -                                                      */
2186 /*-----------------------------------------------------------------*/
2187 static void pushSide(operand * oper, int size)
2188 {
2189 #if 0
2190         int offset = 0;
2191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2192         while (size--) {
2193                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2194                 if (AOP_TYPE(oper) != AOP_REG &&
2195                     AOP_TYPE(oper) != AOP_DIR &&
2196                     strcmp(l,"a") ) {
2197                         pic16_emitcode("mov","a,%s",l);
2198                         pic16_emitcode("push","acc");
2199                 } else
2200                         pic16_emitcode("push","%s",l);
2201         }
2202 #endif
2203 }
2204
2205 /*-----------------------------------------------------------------*/
2206 /* assignResultValue -                                             */
2207 /*-----------------------------------------------------------------*/
2208 static void assignResultValue(operand * oper)
2209 {
2210   int size = AOP_SIZE(oper);
2211
2212         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2213         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2214
2215         if(!GpsuedoStkPtr) {
2216 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2217                 /* The last byte in the assignment is in W */
2218                 size--;
2219                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2220                 GpsuedoStkPtr++;
2221         }
2222
2223         while (size--) {
2224 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2225 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2226                 
2227 #if STACK_SUPPORT
2228                 if(USE_STACK) {
2229                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2230                 } else {
2231                         pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2232                 }
2233 #else
2234                 pic16_emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2235 #endif  /* STACK_SUPPORT */
2236                 GpsuedoStkPtr++;
2237
2238 #if STACK_SUPPORT
2239                 if(!USE_STACK)
2240                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2241 #else
2242                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2243 #endif
2244
2245         }
2246                 
2247 }
2248
2249
2250 /*-----------------------------------------------------------------*/
2251 /* genIpush - genrate code for pushing this gets a little complex  */
2252 /*-----------------------------------------------------------------*/
2253 static void genIpush (iCode *ic)
2254 {
2255
2256   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2257 #if 0
2258     int size, offset = 0 ;
2259     char *l;
2260
2261
2262     /* if this is not a parm push : ie. it is spill push 
2263     and spill push is always done on the local stack */
2264     if (!ic->parmPush) {
2265
2266         /* and the item is spilt then do nothing */
2267         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2268             return ;
2269
2270         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2271         size = AOP_SIZE(IC_LEFT(ic));
2272         /* push it on the stack */
2273         while(size--) {
2274             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2275             if (*l == '#') {
2276                 MOVA(l);
2277                 l = "acc";
2278             }
2279             pic16_emitcode("push","%s",l);
2280         }
2281         return ;        
2282     }
2283
2284     /* this is a paramter push: in this case we call
2285     the routine to find the call and save those
2286     registers that need to be saved */   
2287     saveRegisters(ic);
2288
2289     /* then do the push */
2290     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2291
2292
2293         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2294     size = AOP_SIZE(IC_LEFT(ic));
2295
2296     while (size--) {
2297         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2298         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2299             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2300             strcmp(l,"a") ) {
2301             pic16_emitcode("mov","a,%s",l);
2302             pic16_emitcode("push","acc");
2303         } else
2304             pic16_emitcode("push","%s",l);
2305     }       
2306
2307     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2308 #endif
2309 }
2310
2311 /*-----------------------------------------------------------------*/
2312 /* genIpop - recover the registers: can happen only for spilling   */
2313 /*-----------------------------------------------------------------*/
2314 static void genIpop (iCode *ic)
2315 {
2316   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2317 #if 0
2318     int size,offset ;
2319
2320
2321     /* if the temp was not pushed then */
2322     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2323         return ;
2324
2325     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2326     size = AOP_SIZE(IC_LEFT(ic));
2327     offset = (size-1);
2328     while (size--) 
2329         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2330                                    FALSE,TRUE));
2331
2332     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2333 #endif
2334 }
2335
2336 /*-----------------------------------------------------------------*/
2337 /* unsaverbank - restores the resgister bank from stack            */
2338 /*-----------------------------------------------------------------*/
2339 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2340 {
2341   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2342 #if 0
2343     int i;
2344     asmop *aop ;
2345     regs *r = NULL;
2346
2347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2348     if (popPsw) {
2349         if (options.useXstack) {
2350             aop = newAsmop(0);
2351             r = getFreePtr(ic,&aop,FALSE);
2352             
2353             
2354             pic16_emitcode("mov","%s,_spx",r->name);
2355             pic16_emitcode("movx","a,@%s",r->name);
2356             pic16_emitcode("mov","psw,a");
2357             pic16_emitcode("dec","%s",r->name);
2358             
2359         }else
2360             pic16_emitcode ("pop","psw");
2361     }
2362
2363     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2364         if (options.useXstack) {       
2365             pic16_emitcode("movx","a,@%s",r->name);
2366             //pic16_emitcode("mov","(%s+%d),a",
2367             //       regspic16[i].base,8*bank+regspic16[i].offset);
2368             pic16_emitcode("dec","%s",r->name);
2369
2370         } else 
2371           pic16_emitcode("pop",""); //"(%s+%d)",
2372         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2373     }
2374
2375     if (options.useXstack) {
2376
2377         pic16_emitcode("mov","_spx,%s",r->name);
2378         pic16_freeAsmop(NULL,aop,ic,TRUE);
2379
2380     }
2381 #endif 
2382 }
2383
2384 /*-----------------------------------------------------------------*/
2385 /* saverbank - saves an entire register bank on the stack          */
2386 /*-----------------------------------------------------------------*/
2387 static void saverbank (int bank, iCode *ic, bool pushPsw)
2388 {
2389   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2390 #if 0
2391     int i;
2392     asmop *aop ;
2393     regs *r = NULL;
2394
2395     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2396     if (options.useXstack) {
2397
2398         aop = newAsmop(0);
2399         r = getFreePtr(ic,&aop,FALSE);  
2400         pic16_emitcode("mov","%s,_spx",r->name);
2401
2402     }
2403
2404     for (i = 0 ; i < pic16_nRegs ;i++) {
2405         if (options.useXstack) {
2406             pic16_emitcode("inc","%s",r->name);
2407             //pic16_emitcode("mov","a,(%s+%d)",
2408             //         regspic16[i].base,8*bank+regspic16[i].offset);
2409             pic16_emitcode("movx","@%s,a",r->name);           
2410         } else 
2411           pic16_emitcode("push","");// "(%s+%d)",
2412                      //regspic16[i].base,8*bank+regspic16[i].offset);
2413     }
2414     
2415     if (pushPsw) {
2416         if (options.useXstack) {
2417             pic16_emitcode("mov","a,psw");
2418             pic16_emitcode("movx","@%s,a",r->name);     
2419             pic16_emitcode("inc","%s",r->name);
2420             pic16_emitcode("mov","_spx,%s",r->name);       
2421             pic16_freeAsmop (NULL,aop,ic,TRUE);
2422             
2423         } else
2424             pic16_emitcode("push","psw");
2425         
2426         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2427     }
2428     ic->bankSaved = 1;
2429 #endif
2430 }
2431
2432
2433
2434 /*-----------------------------------------------------------------*/
2435 /* genCall - generates a call statement                            */
2436 /*-----------------------------------------------------------------*/
2437 static void genCall (iCode *ic)
2438 {
2439   sym_link *dtype;   
2440   int stackParms=0;
2441   
2442         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2443
2444         /* if caller saves & we have not saved then */
2445         if (!ic->regsSaved)
2446                 saveRegisters(ic);
2447
2448         /* if we are calling a function that is not using
2449          * the same register bank then we need to save the
2450          * destination registers on the stack */
2451         dtype = operandType(IC_LEFT(ic));
2452         if (currFunc && dtype && 
2453                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2454                 IFFUNC_ISISR(currFunc->type) &&
2455                 !ic->bankSaved) 
2456
2457                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2458
2459         /* if send set is not empty the assign */
2460         if (_G.sendSet) {
2461           iCode *sic;
2462
2463                 /* For the Pic port, there is no data stack.
2464                  * So parameters passed to functions are stored
2465                  * in registers. (The pCode optimizer will get
2466                  * rid of most of these :). */
2467
2468           int psuedoStkPtr=-1; 
2469           int firstTimeThruLoop = 1;
2470
2471                 _G.sendSet = reverseSet(_G.sendSet);
2472
2473                 /* First figure how many parameters are getting passed */
2474                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2475                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2476                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2477                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2478                 }
2479
2480                 stackParms = psuedoStkPtr;
2481
2482                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2483                   int size, offset = 0;
2484
2485                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2486                         size = AOP_SIZE(IC_LEFT(sic));
2487
2488                         while (size--) {
2489                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2490                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2491                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2492
2493                                 if(!firstTimeThruLoop) {
2494                                         /* If this is not the first time we've been through the loop
2495                                          * then we need to save the parameter in a temporary
2496                                          * register. The last byte of the last parameter is
2497                                          * passed in W. */
2498
2499 #if STACK_SUPPORT
2500                                         if(USE_STACK) {
2501                                                 pushw();
2502                                                 --psuedoStkPtr;         // sanity check
2503                                         } else {
2504                                                 pic16_emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2505                                         }
2506 #else
2507                                         pic16_emitpcode(POC_MOVWF, popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2508 #endif  /* STACK_SUPPORT */
2509                                 }
2510                         
2511                                 firstTimeThruLoop=0;
2512
2513                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2514                                 offset++;
2515                         }
2516                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2517                 }
2518                 _G.sendSet = NULL;
2519         }
2520
2521         /* make the call */
2522         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2523                         OP_SYMBOL(IC_LEFT(ic))->rname :
2524                         OP_SYMBOL(IC_LEFT(ic))->name));
2525
2526         GpsuedoStkPtr=0;
2527         /* if we need assign a result value */
2528         if ((IS_ITEMP(IC_RESULT(ic)) && 
2529                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2530                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2531                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2532
2533                 _G.accInUse++;
2534                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2535                 _G.accInUse--;
2536
2537                 assignResultValue(IC_RESULT(ic));
2538
2539                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2540                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2541                 
2542                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2543         }
2544
2545 #if STACK_SUPPORT
2546         if(USE_STACK) {
2547                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2548                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2549                 if(STACK_MODEL_LARGE) {
2550                         emitSKPNC;
2551                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2552                 }
2553         }
2554 #endif
2555
2556         /* adjust the stack for parameters if required */
2557         fprintf(stderr, "%s:%d: ic->parmBytes= %d\n", __FILE__, __LINE__, ic->parmBytes);
2558
2559         if (ic->parmBytes) {
2560           int i;
2561
2562                 if (ic->parmBytes > 3) {
2563                         pic16_emitcode("mov","a,%s",spname);
2564                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2565                         pic16_emitcode("mov","%s,a",spname);
2566                 } else 
2567                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2568                                 pic16_emitcode("dec","%s",spname);
2569         }
2570
2571         /* if register bank was saved then pop them */
2572         if (ic->bankSaved)
2573                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2574
2575         /* if we hade saved some registers then unsave them */
2576         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2577                 unsaveRegisters (ic);
2578 }
2579
2580 /*-----------------------------------------------------------------*/
2581 /* genPcall - generates a call by pointer statement                */
2582 /*-----------------------------------------------------------------*/
2583 static void genPcall (iCode *ic)
2584 {
2585     sym_link *dtype;
2586     symbol *rlbl = newiTempLabel(NULL);
2587
2588
2589     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2590     /* if caller saves & we have not saved then */
2591     if (!ic->regsSaved)
2592         saveRegisters(ic);
2593
2594     /* if we are calling a function that is not using
2595     the same register bank then we need to save the
2596     destination registers on the stack */
2597     dtype = operandType(IC_LEFT(ic));
2598     if (currFunc && dtype && 
2599         IFFUNC_ISISR(currFunc->type) &&
2600         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2601         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2602
2603
2604     /* push the return address on to the stack */
2605     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2606     pic16_emitcode("push","acc");    
2607     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2608     pic16_emitcode("push","acc");
2609     
2610     if (options.model == MODEL_FLAT24)
2611     {
2612         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2613         pic16_emitcode("push","acc");    
2614     }
2615
2616     /* now push the calling address */
2617     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2618
2619     pushSide(IC_LEFT(ic), FPTRSIZE);
2620
2621     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2622
2623     /* if send set is not empty the assign */
2624     if (_G.sendSet) {
2625         iCode *sic ;
2626
2627         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2628              sic = setNextItem(_G.sendSet)) {
2629             int size, offset = 0;
2630             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2631             size = AOP_SIZE(IC_LEFT(sic));
2632             while (size--) {
2633                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2634                                 FALSE,FALSE);
2635                 if (strcmp(l,fReturn[offset]))
2636                     pic16_emitcode("mov","%s,%s",
2637                              fReturn[offset],
2638                              l);
2639                 offset++;
2640             }
2641             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2642         }
2643         _G.sendSet = NULL;
2644     }
2645
2646     pic16_emitcode("ret","");
2647     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2648
2649
2650     /* if we need assign a result value */
2651     if ((IS_ITEMP(IC_RESULT(ic)) &&
2652          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2653           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2654         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2655
2656         _G.accInUse++;
2657         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2658         _G.accInUse--;
2659         
2660         assignResultValue(IC_RESULT(ic));
2661
2662         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2663     }
2664
2665     /* adjust the stack for parameters if 
2666     required */
2667     if (ic->parmBytes) {
2668         int i;
2669         if (ic->parmBytes > 3) {
2670             pic16_emitcode("mov","a,%s",spname);
2671             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2672             pic16_emitcode("mov","%s,a",spname);
2673         } else 
2674             for ( i = 0 ; i <  ic->parmBytes ;i++)
2675                 pic16_emitcode("dec","%s",spname);
2676
2677     }
2678
2679     /* if register bank was saved then unsave them */
2680     if (currFunc && dtype && 
2681         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2682         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2683
2684     /* if we hade saved some registers then
2685     unsave them */
2686     if (ic->regsSaved)
2687         unsaveRegisters (ic);
2688
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* resultRemat - result  is rematerializable                       */
2693 /*-----------------------------------------------------------------*/
2694 static int resultRemat (iCode *ic)
2695 {
2696   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2697   if (SKIP_IC(ic) || ic->op == IFX)
2698     return 0;
2699
2700   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2701     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2702     if (sym->remat && !POINTER_SET(ic)) 
2703       return 1;
2704   }
2705
2706   return 0;
2707 }
2708
2709 #if defined(__BORLANDC__) || defined(_MSC_VER)
2710 #define STRCASECMP stricmp
2711 #else
2712 #define STRCASECMP strcasecmp
2713 #endif
2714
2715 #if 0
2716 /*-----------------------------------------------------------------*/
2717 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2718 /*-----------------------------------------------------------------*/
2719 static bool inExcludeList(char *s)
2720 {
2721   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2722     int i =0;
2723     
2724     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2725     if (options.excludeRegs[i] &&
2726     STRCASECMP(options.excludeRegs[i],"none") == 0)
2727         return FALSE ;
2728
2729     for ( i = 0 ; options.excludeRegs[i]; i++) {
2730         if (options.excludeRegs[i] &&
2731         STRCASECMP(s,options.excludeRegs[i]) == 0)
2732             return TRUE;
2733     }
2734     return FALSE ;
2735 }
2736 #endif
2737
2738 /*-----------------------------------------------------------------*/
2739 /* genFunction - generated code for function entry                 */
2740 /*-----------------------------------------------------------------*/
2741 static void genFunction (iCode *ic)
2742 {
2743     symbol *sym;
2744     sym_link *ftype;
2745
2746     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2747
2748     labelOffset += (max_key+4);
2749     max_key=0;
2750     GpsuedoStkPtr=0;
2751     _G.nRegsSaved = 0;
2752     /* create the function header */
2753     pic16_emitcode(";","-----------------------------------------");
2754     pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2755     pic16_emitcode(";","-----------------------------------------");
2756
2757     pic16_emitcode("","%s:",sym->rname);
2758     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,sym->rname));
2759
2760     ftype = operandType(IC_LEFT(ic));
2761
2762     /* if critical function then turn interrupts off */
2763     if (IFFUNC_ISCRITICAL(ftype))
2764         pic16_emitcode("clr","ea");
2765
2766     /* here we need to generate the equates for the
2767        register bank if required */
2768 #if 0
2769     if (FUNC_REGBANK(ftype) != rbank) {
2770         int i ;
2771
2772         rbank = FUNC_REGBANK(ftype);
2773         for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2774             if (strcmp(regspic16[i].base,"0") == 0)
2775                 pic16_emitcode("","%s = 0x%02x",
2776                          regspic16[i].dname,
2777                          8*rbank+regspic16[i].offset);
2778             else
2779                 pic16_emitcode ("","%s = %s + 0x%02x",
2780                           regspic16[i].dname,
2781                           regspic16[i].base,
2782                           8*rbank+regspic16[i].offset);
2783         }
2784     }
2785 #endif
2786
2787     /* if this is an interrupt service routine then
2788     save acc, b, dpl, dph  */
2789     if (IFFUNC_ISISR(sym->type)) {
2790
2791 #if 0
2792         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_BRA,pic16_newpCodeOp("END_OF_INTERRUPT+2",PO_STR)));
2793         
2794         /* what is the reason of having these 3 NOPS? VR - 030701 */
2795         pic16_emitpcodeNULLop(POC_NOP);
2796         pic16_emitpcodeNULLop(POC_NOP);
2797         pic16_emitpcodeNULLop(POC_NOP);
2798 #endif
2799
2800       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2801       pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2802       pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2803       pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2804
2805       pic16_pBlockConvert2ISR(pb);
2806 #if 0  
2807         if (!inExcludeList("acc"))          
2808             pic16_emitcode ("push","acc");      
2809         if (!inExcludeList("b"))
2810             pic16_emitcode ("push","b");
2811         if (!inExcludeList("dpl"))
2812             pic16_emitcode ("push","dpl");
2813         if (!inExcludeList("dph"))
2814             pic16_emitcode ("push","dph");
2815         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2816         {
2817             pic16_emitcode ("push", "dpx");
2818             /* Make sure we're using standard DPTR */
2819             pic16_emitcode ("push", "dps");
2820             pic16_emitcode ("mov", "dps, #0x00");
2821             if (options.stack10bit)
2822             {   
2823                 /* This ISR could conceivably use DPTR2. Better save it. */
2824                 pic16_emitcode ("push", "dpl1");
2825                 pic16_emitcode ("push", "dph1");
2826                 pic16_emitcode ("push", "dpx1");
2827             }
2828         }
2829         /* if this isr has no bank i.e. is going to
2830            run with bank 0 , then we need to save more
2831            registers :-) */
2832         if (!FUNC_REGBANK(sym->type)) {
2833
2834             /* if this function does not call any other
2835                function then we can be economical and
2836                save only those registers that are used */
2837             if (! IFFUNC_HASFCALL(sym->type)) {
2838                 int i;
2839
2840                 /* if any registers used */
2841                 if (sym->regsUsed) {
2842                     /* save the registers used */
2843                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2844                         if (bitVectBitValue(sym->regsUsed,i) ||
2845                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2846                           pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                         
2847                     }
2848                 }
2849                 
2850             } else {
2851                 /* this function has  a function call cannot
2852                    determines register usage so we will have the
2853                    entire bank */
2854                 saverbank(0,ic,FALSE);
2855             }       
2856         }
2857 #endif
2858     } else {
2859         /* if callee-save to be used for this function
2860            then save the registers being used in this function */
2861         if (IFFUNC_CALLEESAVES(sym->type)) {
2862             int i;
2863             
2864             /* if any registers used */
2865             if (sym->regsUsed) {
2866                 /* save the registers used */
2867                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2868                     if (bitVectBitValue(sym->regsUsed,i) ||
2869                       (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2870                       //pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2871                         _G.nRegsSaved++;
2872                     }
2873                 }
2874             }
2875         }
2876         
2877 #if STACK_SUPPORT
2878         /* emit code to setup stack frame if user enabled,
2879          * and function is not main() */
2880          
2881         fprintf(stderr, "function name: %s\n", sym->name);
2882         if(USE_STACK && strcmp(sym->name, "main")) {
2883                 /* setup the stack frame */
2884                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1));
2885                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l));
2886                 if(STACK_MODEL_LARGE)
2887                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h));
2888         }
2889 #endif
2890
2891     }
2892
2893     /* set the register bank to the desired value */
2894     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2895         pic16_emitcode("push","psw");
2896         pic16_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2897     }
2898
2899     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2900
2901         if (options.useXstack) {
2902             pic16_emitcode("mov","r0,%s",spname);
2903             pic16_emitcode("mov","a,_bp");
2904             pic16_emitcode("movx","@r0,a");
2905             pic16_emitcode("inc","%s",spname);
2906         }
2907         else
2908         {
2909             /* set up the stack */
2910             pic16_emitcode ("push","_bp");     /* save the callers stack  */
2911         }
2912         pic16_emitcode ("mov","_bp,%s",spname);
2913     }
2914
2915         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
2916
2917     /* adjust the stack for the function */
2918     if (sym->stack) {
2919
2920         int i = sym->stack;
2921         if (i > 256 ) 
2922             werror(W_STACK_OVERFLOW,sym->name);
2923
2924         if (i > 3 && sym->recvSize < 4) {              
2925             pic16_emitcode ("mov","a,sp");
2926             pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2927             pic16_emitcode ("mov","sp,a");
2928            
2929         }
2930         else
2931             while(i--)
2932                 pic16_emitcode("inc","sp");
2933     }
2934
2935      if (sym->xstack) {
2936                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
2937         pic16_emitcode ("mov","a,_spx");
2938         pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2939         pic16_emitcode ("mov","_spx,a");
2940     }    
2941
2942 }
2943
2944 /*-----------------------------------------------------------------*/
2945 /* genEndFunction - generates epilogue for functions               */
2946 /*-----------------------------------------------------------------*/
2947 static void genEndFunction (iCode *ic)
2948 {
2949     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2950
2951     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2952
2953     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2954     {
2955         pic16_emitcode ("mov","%s,_bp",spname);
2956     }
2957
2958     /* if use external stack but some variables were
2959     added to the local stack then decrement the
2960     local stack */
2961     if (options.useXstack && sym->stack) {      
2962         pic16_emitcode("mov","a,sp");
2963         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2964         pic16_emitcode("mov","sp,a");
2965     }
2966
2967
2968     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2969         if (options.useXstack) {
2970             pic16_emitcode("mov","r0,%s",spname);
2971             pic16_emitcode("movx","a,@r0");
2972             pic16_emitcode("mov","_bp,a");
2973             pic16_emitcode("dec","%s",spname);
2974         }
2975         else
2976         {
2977             pic16_emitcode ("pop","_bp");
2978         }
2979     }
2980
2981     /* restore the register bank  */    
2982     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2983         pic16_emitcode ("pop","psw");
2984
2985     if (IFFUNC_ISISR(sym->type)) {
2986
2987         /* now we need to restore the registers */
2988         /* if this isr has no bank i.e. is going to
2989            run with bank 0 , then we need to save more
2990            registers :-) */
2991         if (!FUNC_REGBANK(sym->type)) {
2992             
2993             /* if this function does not call any other
2994                function then we can be economical and
2995                save only those registers that are used */
2996             if (! IFFUNC_HASFCALL(sym->type)) {
2997                 int i;
2998                 
2999                 /* if any registers used */
3000                 if (sym->regsUsed) {
3001                     /* save the registers used */
3002                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3003                         if (bitVectBitValue(sym->regsUsed,i) ||
3004                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3005                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3006                     }
3007                 }
3008                 
3009             } else {
3010                 /* this function has  a function call cannot
3011                    determines register usage so we will have the
3012                    entire bank */
3013                 unsaverbank(0,ic,FALSE);
3014             }       
3015         }
3016 #if 0
3017         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3018         {
3019             if (options.stack10bit)
3020             {
3021                 pic16_emitcode ("pop", "dpx1");
3022                 pic16_emitcode ("pop", "dph1");
3023                 pic16_emitcode ("pop", "dpl1");
3024             }   
3025             pic16_emitcode ("pop", "dps");
3026             pic16_emitcode ("pop", "dpx");
3027         }
3028         if (!inExcludeList("dph"))
3029             pic16_emitcode ("pop","dph");
3030         if (!inExcludeList("dpl"))
3031             pic16_emitcode ("pop","dpl");
3032         if (!inExcludeList("b"))
3033             pic16_emitcode ("pop","b");
3034         if (!inExcludeList("acc"))
3035             pic16_emitcode ("pop","acc");
3036
3037         if (IFFUNC_ISCRITICAL(sym->type))
3038             pic16_emitcode("setb","ea");
3039 #endif
3040
3041         /* if debug then send end of function */
3042 /*      if (options.debug && currFunc) { */
3043         if (currFunc) {
3044             _G.debugLine = 1;
3045             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3046                      FileBaseName(ic->filename),currFunc->lastLine,
3047                      ic->level,ic->block); 
3048             if (IS_STATIC(currFunc->etype))         
3049                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3050             else
3051                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3052             _G.debugLine = 0;
3053         }
3054         
3055 //      pic16_emitcode ("reti","");
3056
3057         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3058         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3059         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3060         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3061         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3062
3063 #if 0
3064         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3065 #endif
3066
3067         pic16_emitpcodeNULLop(POC_RETFIE);
3068
3069     }
3070     else {
3071         if (IFFUNC_ISCRITICAL(sym->type))
3072             pic16_emitcode("setb","ea");
3073         
3074         if (IFFUNC_CALLEESAVES(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         }
3088
3089         /* if debug then send end of function */
3090         if (currFunc) {
3091             _G.debugLine = 1;
3092             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3093                      FileBaseName(ic->filename),currFunc->lastLine,
3094                      ic->level,ic->block); 
3095             if (IS_STATIC(currFunc->etype))         
3096                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3097             else
3098                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3099             _G.debugLine = 0;
3100         }
3101
3102 #if STACK_SUPPORT
3103         /* insert code to restore stack frame, if user enabled it
3104          * and function is not main() */
3105          
3106         if(USE_STACK && strcmp(sym->name, "main")) {
3107                 /* restore stack frame */
3108                 if(STACK_MODEL_LARGE)
3109                         pic16_emitpcode(POC_MOVFF,
3110                                 pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h ));
3111                 pic16_emitpcode(POC_MOVFF,
3112                                 pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l ));
3113
3114 /*
3115         * I added this because of a mistake in the stack pointers design
3116         * They should be removed though
3117         
3118                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc2, &pic16_pc_fsr2h));
3119                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc2, &pic16_pc_fsr2l));
3120 */
3121         }
3122 #endif
3123
3124         pic16_emitcode ("return","");
3125         pic16_emitpcodeNULLop(POC_RETURN);
3126
3127         /* Mark the end of a function */
3128         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3129     }
3130
3131 }
3132
3133 /*-----------------------------------------------------------------*/
3134 /* genRet - generate code for return statement                     */
3135 /*-----------------------------------------------------------------*/
3136 static void genRet (iCode *ic)
3137 {
3138   int size,offset = 0 , pushed = 0;
3139     
3140   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3141   /* if we have no return value then
3142      just generate the "ret" */
3143   if (!IC_LEFT(ic)) 
3144     goto jumpret;       
3145     
3146   /* we have something to return then
3147      move the return value into place */
3148   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3149   size = AOP_SIZE(IC_LEFT(ic));
3150     
3151   while (size--) {
3152     char *l ;
3153     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3154       /* #NOCHANGE */
3155       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3156                  FALSE,TRUE);
3157       pic16_emitcode("push","%s",l);
3158       pushed++;
3159     } else {
3160         DEBUGpic16_emitcode(";", "%d", __LINE__);
3161       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3162                  FALSE,FALSE);
3163         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3164       if (strcmp(fReturn[offset],l)) {
3165         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3166             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3167           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3168         }else {
3169           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3170         }
3171         if(size) {
3172           pic16_emitpcode(POC_MOVWF,popRegFromIdx(offset + pic16_Gstack_base_addr));
3173         }
3174         offset++;
3175       }
3176     }
3177   }    
3178
3179   if (pushed) {
3180     while(pushed) {
3181       pushed--;
3182       if (strcmp(fReturn[pushed],"a"))
3183         pic16_emitcode("pop",fReturn[pushed]);
3184       else
3185         pic16_emitcode("pop","acc");
3186     }
3187   }
3188   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3189     
3190  jumpret:
3191   /* generate a jump to the return label
3192      if the next is not the return statement */
3193   if (!(ic->next && ic->next->op == LABEL &&
3194         IC_LABEL(ic->next) == returnLabel)) {
3195         
3196     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3197     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3198   }
3199     
3200 }
3201
3202 /*-----------------------------------------------------------------*/
3203 /* genLabel - generates a label                                    */
3204 /*-----------------------------------------------------------------*/
3205 static void genLabel (iCode *ic)
3206 {
3207     /* special case never generate */
3208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3209     if (IC_LABEL(ic) == entryLabel)
3210         return ;
3211
3212     pic16_emitpLabel(IC_LABEL(ic)->key);
3213     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3214 }
3215
3216 /*-----------------------------------------------------------------*/
3217 /* genGoto - generates a goto                                      */
3218 /*-----------------------------------------------------------------*/
3219 //tsd
3220 static void genGoto (iCode *ic)
3221 {
3222   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3223   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3224 }
3225
3226
3227 /*-----------------------------------------------------------------*/
3228 /* genMultbits :- multiplication of bits                           */
3229 /*-----------------------------------------------------------------*/
3230 static void genMultbits (operand *left, 
3231                          operand *right, 
3232                          operand *result)
3233 {
3234   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3235
3236   if(!pic16_sameRegs(AOP(result),AOP(right)))
3237     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3238
3239   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3240   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3241   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3242
3243 }
3244
3245
3246 /*-----------------------------------------------------------------*/
3247 /* genMultOneByte : 8 bit multiplication & division                */
3248 /*-----------------------------------------------------------------*/
3249 static void genMultOneByte (operand *left,
3250                             operand *right,
3251                             operand *result)
3252 {
3253   sym_link *opetype = operandType(result);
3254
3255   // symbol *lbl ;
3256   int size,offset;
3257
3258   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3259   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3260   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3261
3262   /* (if two literals, the value is computed before) */
3263   /* if one literal, literal on the right */
3264   if (AOP_TYPE(left) == AOP_LIT){
3265     operand *t = right;
3266     right = left;
3267     left = t;
3268   }
3269
3270   size = AOP_SIZE(result);
3271   if(size == 1) {
3272
3273     if (AOP_TYPE(right) == AOP_LIT){
3274       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3275                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3276                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3277                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3278       pic16_emitcode("call","genMultLit");
3279     } else {
3280       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3281                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3282                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3283                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3284       pic16_emitcode("call","pic16_genMult8X8_8");
3285
3286     }
3287     pic16_genMult8X8_8 (left, right,result);
3288
3289
3290     /* signed or unsigned */
3291     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3292     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3293     //MOVA(l);       
3294     //pic16_emitcode("mul","ab");
3295     /* if result size = 1, mul signed = mul unsigned */
3296     //pic16_aopPut(AOP(result),"a",0);
3297
3298   } else {  // (size > 1)
3299
3300     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3301                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3302                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3303                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3304
3305     if (SPEC_USIGN(opetype)){
3306       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3307       pic16_genUMult8X8_16 (left, right, result, NULL);
3308
3309       if (size > 2) {
3310         /* for filling the MSBs */
3311         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3312         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3313       }
3314     }
3315     else{
3316       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3317
3318       pic16_emitcode("mov","a,b");
3319
3320       /* adjust the MSB if left or right neg */
3321
3322       /* if one literal */
3323       if (AOP_TYPE(right) == AOP_LIT){
3324         pic16_emitcode("multiply ","right is a lit");
3325         /* AND literal negative */
3326         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3327           /* adjust MSB (c==0 after mul) */
3328           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3329         }
3330       }
3331       else{
3332         pic16_genSMult8X8_16 (left, right, result, NULL);
3333       }
3334
3335       if(size > 2){
3336         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3337         /* get the sign */
3338         pic16_emitcode("rlc","a");
3339         pic16_emitcode("subb","a,acc");
3340       }
3341     }
3342
3343     size -= 2;   
3344     offset = 2;
3345     if (size > 0)
3346       while (size--)
3347         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3348     //pic16_aopPut(AOP(result),"a",offset++);
3349   }
3350 }
3351
3352 /*-----------------------------------------------------------------*/
3353 /* genMult - generates code for multiplication                     */
3354 /*-----------------------------------------------------------------*/
3355 static void genMult (iCode *ic)
3356 {
3357     operand *left = IC_LEFT(ic);
3358     operand *right = IC_RIGHT(ic);
3359     operand *result= IC_RESULT(ic);   
3360
3361     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3362     /* assign the amsops */
3363     pic16_aopOp (left,ic,FALSE);
3364     pic16_aopOp (right,ic,FALSE);
3365     pic16_aopOp (result,ic,TRUE);
3366
3367   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3368
3369     /* special cases first */
3370     /* both are bits */
3371     if (AOP_TYPE(left) == AOP_CRY &&
3372         AOP_TYPE(right)== AOP_CRY) {
3373         genMultbits(left,right,result);
3374         goto release ;
3375     }
3376
3377     /* if both are of size == 1 */
3378     if (AOP_SIZE(left) == 1 &&
3379         AOP_SIZE(right) == 1 ) {
3380         genMultOneByte(left,right,result);
3381         goto release ;
3382     }
3383
3384     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3385
3386     /* should have been converted to function call */
3387     //assert(0) ;
3388
3389 release :
3390     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3391     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3392     pic16_freeAsmop(result,NULL,ic,TRUE); 
3393 }
3394
3395 /*-----------------------------------------------------------------*/
3396 /* genDivbits :- division of bits                                  */
3397 /*-----------------------------------------------------------------*/
3398 static void genDivbits (operand *left, 
3399                         operand *right, 
3400                         operand *result)
3401 {
3402
3403     char *l;
3404
3405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3406     /* the result must be bit */    
3407     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3408     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3409
3410     MOVA(l);    
3411
3412     pic16_emitcode("div","ab");
3413     pic16_emitcode("rrc","a");
3414     pic16_aopPut(AOP(result),"c",0);
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* genDivOneByte : 8 bit division                                  */
3419 /*-----------------------------------------------------------------*/
3420 static void genDivOneByte (operand *left,
3421                            operand *right,
3422                            operand *result)
3423 {
3424     sym_link *opetype = operandType(result);
3425     char *l ;
3426     symbol *lbl ;
3427     int size,offset;
3428
3429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3430     size = AOP_SIZE(result) - 1;
3431     offset = 1;
3432     /* signed or unsigned */
3433     if (SPEC_USIGN(opetype)) {
3434         /* unsigned is easy */
3435         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3436         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3437         MOVA(l);        
3438         pic16_emitcode("div","ab");
3439         pic16_aopPut(AOP(result),"a",0);
3440         while (size--)
3441             pic16_aopPut(AOP(result),zero,offset++);
3442         return ;
3443     }
3444
3445     /* signed is a little bit more difficult */
3446
3447     /* save the signs of the operands */
3448     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3449     MOVA(l);    
3450     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3451     pic16_emitcode("push","acc"); /* save it on the stack */
3452
3453     /* now sign adjust for both left & right */
3454     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3455     MOVA(l);       
3456     lbl = newiTempLabel(NULL);
3457     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3458     pic16_emitcode("cpl","a");   
3459     pic16_emitcode("inc","a");
3460     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3461     pic16_emitcode("mov","b,a");
3462
3463     /* sign adjust left side */
3464     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3465     MOVA(l);
3466
3467     lbl = newiTempLabel(NULL);
3468     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3469     pic16_emitcode("cpl","a");
3470     pic16_emitcode("inc","a");
3471     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3472
3473     /* now the division */
3474     pic16_emitcode("div","ab");
3475     /* we are interested in the lower order
3476     only */
3477     pic16_emitcode("mov","b,a");
3478     lbl = newiTempLabel(NULL);
3479     pic16_emitcode("pop","acc");   
3480     /* if there was an over flow we don't 
3481     adjust the sign of the result */
3482     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3483     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3484     CLRC;
3485     pic16_emitcode("clr","a");
3486     pic16_emitcode("subb","a,b");
3487     pic16_emitcode("mov","b,a");
3488     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3489
3490     /* now we are done */
3491     pic16_aopPut(AOP(result),"b",0);
3492     if(size > 0){
3493         pic16_emitcode("mov","c,b.7");
3494         pic16_emitcode("subb","a,acc");   
3495     }
3496     while (size--)
3497         pic16_aopPut(AOP(result),"a",offset++);
3498
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /* genDiv - generates code for division                            */
3503 /*-----------------------------------------------------------------*/
3504 static void genDiv (iCode *ic)
3505 {
3506     operand *left = IC_LEFT(ic);
3507     operand *right = IC_RIGHT(ic);
3508     operand *result= IC_RESULT(ic);   
3509
3510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3511     /* assign the amsops */
3512     pic16_aopOp (left,ic,FALSE);
3513     pic16_aopOp (right,ic,FALSE);
3514     pic16_aopOp (result,ic,TRUE);
3515
3516     /* special cases first */
3517     /* both are bits */
3518     if (AOP_TYPE(left) == AOP_CRY &&
3519         AOP_TYPE(right)== AOP_CRY) {
3520         genDivbits(left,right,result);
3521         goto release ;
3522     }
3523
3524     /* if both are of size == 1 */
3525     if (AOP_SIZE(left) == 1 &&
3526         AOP_SIZE(right) == 1 ) {
3527         genDivOneByte(left,right,result);
3528         goto release ;
3529     }
3530
3531     /* should have been converted to function call */
3532     assert(0);
3533 release :
3534     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3535     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3536     pic16_freeAsmop(result,NULL,ic,TRUE); 
3537 }
3538
3539 /*-----------------------------------------------------------------*/
3540 /* genModbits :- modulus of bits                                   */
3541 /*-----------------------------------------------------------------*/
3542 static void genModbits (operand *left, 
3543                         operand *right, 
3544                         operand *result)
3545 {
3546
3547     char *l;
3548
3549     /* the result must be bit */    
3550     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3551     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3552
3553     MOVA(l);       
3554
3555     pic16_emitcode("div","ab");
3556     pic16_emitcode("mov","a,b");
3557     pic16_emitcode("rrc","a");
3558     pic16_aopPut(AOP(result),"c",0);
3559 }
3560
3561 /*-----------------------------------------------------------------*/
3562 /* genModOneByte : 8 bit modulus                                   */
3563 /*-----------------------------------------------------------------*/
3564 static void genModOneByte (operand *left,
3565                            operand *right,
3566                            operand *result)
3567 {
3568     sym_link *opetype = operandType(result);
3569     char *l ;
3570     symbol *lbl ;
3571
3572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3573     /* signed or unsigned */
3574     if (SPEC_USIGN(opetype)) {
3575         /* unsigned is easy */
3576         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3577         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3578         MOVA(l);    
3579         pic16_emitcode("div","ab");
3580         pic16_aopPut(AOP(result),"b",0);
3581         return ;
3582     }
3583
3584     /* signed is a little bit more difficult */
3585
3586     /* save the signs of the operands */
3587     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3588     MOVA(l);
3589
3590     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3591     pic16_emitcode("push","acc"); /* save it on the stack */
3592
3593     /* now sign adjust for both left & right */
3594     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3595     MOVA(l);
3596
3597     lbl = newiTempLabel(NULL);
3598     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3599     pic16_emitcode("cpl","a");   
3600     pic16_emitcode("inc","a");
3601     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3602     pic16_emitcode("mov","b,a"); 
3603
3604     /* sign adjust left side */
3605     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3606     MOVA(l);
3607
3608     lbl = newiTempLabel(NULL);
3609     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3610     pic16_emitcode("cpl","a");   
3611     pic16_emitcode("inc","a");
3612     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3613
3614     /* now the multiplication */
3615     pic16_emitcode("div","ab");
3616     /* we are interested in the lower order
3617     only */
3618     lbl = newiTempLabel(NULL);
3619     pic16_emitcode("pop","acc");   
3620     /* if there was an over flow we don't 
3621     adjust the sign of the result */
3622     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3623     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3624     CLRC ;
3625     pic16_emitcode("clr","a");
3626     pic16_emitcode("subb","a,b");
3627     pic16_emitcode("mov","b,a");
3628     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3629
3630     /* now we are done */
3631     pic16_aopPut(AOP(result),"b",0);
3632
3633 }
3634
3635 /*-----------------------------------------------------------------*/
3636 /* genMod - generates code for division                            */
3637 /*-----------------------------------------------------------------*/
3638 static void genMod (iCode *ic)
3639 {
3640     operand *left = IC_LEFT(ic);
3641     operand *right = IC_RIGHT(ic);
3642     operand *result= IC_RESULT(ic);  
3643
3644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3645     /* assign the amsops */
3646     pic16_aopOp (left,ic,FALSE);
3647     pic16_aopOp (right,ic,FALSE);
3648     pic16_aopOp (result,ic,TRUE);
3649
3650     /* special cases first */
3651     /* both are bits */
3652     if (AOP_TYPE(left) == AOP_CRY &&
3653         AOP_TYPE(right)== AOP_CRY) {
3654         genModbits(left,right,result);
3655         goto release ;
3656     }
3657
3658     /* if both are of size == 1 */
3659     if (AOP_SIZE(left) == 1 &&
3660         AOP_SIZE(right) == 1 ) {
3661         genModOneByte(left,right,result);
3662         goto release ;
3663     }
3664
3665     /* should have been converted to function call */
3666     assert(0);
3667
3668 release :
3669     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3670     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3671     pic16_freeAsmop(result,NULL,ic,TRUE); 
3672 }
3673
3674 /*-----------------------------------------------------------------*/
3675 /* genIfxJump :- will create a jump depending on the ifx           */
3676 /*-----------------------------------------------------------------*/
3677 /*
3678   note: May need to add parameter to indicate when a variable is in bit space.
3679 */
3680 static void genIfxJump (iCode *ic, char *jval)
3681 {
3682
3683     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3684     /* if true label then we jump if condition
3685     supplied is true */
3686     if ( IC_TRUE(ic) ) {
3687
3688         if(strcmp(jval,"a") == 0)
3689           emitSKPZ;
3690         else if (strcmp(jval,"c") == 0)
3691           emitSKPC;
3692         else {
3693           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3694           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3695         }
3696
3697         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3698         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3699
3700     }
3701     else {
3702         /* false label is present */
3703         if(strcmp(jval,"a") == 0)
3704           emitSKPNZ;
3705         else if (strcmp(jval,"c") == 0)
3706           emitSKPNC;
3707         else {
3708           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3709           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3710         }
3711
3712         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3713         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3714
3715     }
3716
3717
3718     /* mark the icode as generated */
3719     ic->generated = 1;
3720 }
3721
3722 /*-----------------------------------------------------------------*/
3723 /* genSkip                                                         */
3724 /*-----------------------------------------------------------------*/
3725 static void genSkip(iCode *ifx,int status_bit)
3726 {
3727   if(!ifx)
3728     return;
3729
3730   if ( IC_TRUE(ifx) ) {
3731     switch(status_bit) {
3732     case 'z':
3733       emitSKPNZ;
3734       break;
3735
3736     case 'c':
3737       emitSKPNC;
3738       break;
3739
3740     case 'd':
3741       emitSKPDC;
3742       break;
3743
3744     }
3745
3746     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3747     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3748
3749   } else {
3750
3751     switch(status_bit) {
3752
3753     case 'z':
3754       emitSKPZ;
3755       break;
3756
3757     case 'c':
3758       emitSKPC;
3759       break;
3760
3761     case 'd':
3762       emitSKPDC;
3763       break;
3764     }
3765     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3766     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3767
3768   }
3769
3770 }
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genSkipc                                                        */
3774 /*-----------------------------------------------------------------*/
3775 static void genSkipc(resolvedIfx *rifx)
3776 {
3777   if(!rifx)
3778     return;
3779
3780   if(rifx->condition)
3781     emitSKPC;
3782   else
3783     emitSKPNC;
3784
3785   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3786   rifx->generated = 1;
3787 }
3788
3789 /*-----------------------------------------------------------------*/
3790 /* genSkipz2                                                       */
3791 /*-----------------------------------------------------------------*/
3792 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3793 {
3794   if(!rifx)
3795     return;
3796
3797   if( (rifx->condition ^ invert_condition) & 1)
3798     emitSKPZ;
3799   else
3800     emitSKPNZ;
3801
3802   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3803   rifx->generated = 1;
3804 }
3805
3806 /*-----------------------------------------------------------------*/
3807 /* genSkipz                                                        */
3808 /*-----------------------------------------------------------------*/
3809 static void genSkipz(iCode *ifx, int condition)
3810 {
3811   if(!ifx)
3812     return;
3813
3814   if(condition)
3815     emitSKPNZ;
3816   else
3817     emitSKPZ;
3818
3819   if ( IC_TRUE(ifx) )
3820     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3821   else
3822     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3823
3824   if ( IC_TRUE(ifx) )
3825     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3826   else
3827     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3828
3829 }
3830 /*-----------------------------------------------------------------*/
3831 /* genSkipCond                                                     */
3832 /*-----------------------------------------------------------------*/
3833 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3834 {
3835   if(!rifx)
3836     return;
3837
3838   if(rifx->condition)
3839     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3840   else
3841     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3842
3843
3844   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3845   rifx->generated = 1;
3846 }
3847
3848 #if 0
3849 /*-----------------------------------------------------------------*/
3850 /* genChkZeroes :- greater or less than comparison                 */
3851 /*     For each byte in a literal that is zero, inclusive or the   */
3852 /*     the corresponding byte in the operand with W                */
3853 /*     returns true if any of the bytes are zero                   */
3854 /*-----------------------------------------------------------------*/
3855 static int genChkZeroes(operand *op, int lit,  int size)
3856 {
3857
3858   int i;
3859   int flag =1;
3860
3861   while(size--) {
3862     i = (lit >> (size*8)) & 0xff;
3863
3864     if(i==0) {
3865       if(flag) 
3866         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3867       else
3868         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3869       flag = 0;
3870     }
3871   }
3872
3873   return (flag==0);
3874 }
3875 #endif
3876
3877 /*-----------------------------------------------------------------*/
3878 /* genCmp :- greater or less than comparison                       */
3879 /*-----------------------------------------------------------------*/
3880 static void genCmp (operand *left,operand *right,
3881                     operand *result, iCode *ifx, int sign)
3882 {
3883   int size; //, offset = 0 ;
3884   unsigned long lit = 0L,i = 0;
3885   resolvedIfx rFalseIfx;
3886   //  resolvedIfx rTrueIfx;
3887   symbol *truelbl;
3888   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3889 /*
3890   if(ifx) {
3891     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3892     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3893   }
3894 */
3895
3896   resolveIfx(&rFalseIfx,ifx);
3897   truelbl  = newiTempLabel(NULL);
3898   size = max(AOP_SIZE(left),AOP_SIZE(right));
3899
3900   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3901
3902 #define _swapp
3903
3904   /* if literal is on the right then swap with left */
3905   if ((AOP_TYPE(right) == AOP_LIT)) {
3906     operand *tmp = right ;
3907     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3908     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3909 #ifdef _swapp
3910
3911     lit = (lit - 1) & mask;
3912     right = left;
3913     left = tmp;
3914     rFalseIfx.condition ^= 1;
3915 #endif
3916
3917   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3918     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3919   }
3920
3921
3922   //if(IC_TRUE(ifx) == NULL)
3923   /* if left & right are bit variables */
3924   if (AOP_TYPE(left) == AOP_CRY &&
3925       AOP_TYPE(right) == AOP_CRY ) {
3926     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3927     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3928   } else {
3929     /* subtract right from left if at the
3930        end the carry flag is set then we know that
3931        left is greater than right */
3932
3933     //    {
3934
3935     symbol *lbl  = newiTempLabel(NULL);
3936
3937 #ifndef _swapp
3938     if(AOP_TYPE(right) == AOP_LIT) {
3939
3940       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3941
3942       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3943
3944       /* special cases */
3945
3946       if(lit == 0) {
3947
3948         if(sign != 0) 
3949           genSkipCond(&rFalseIfx,left,size-1,7);
3950         else 
3951           /* no need to compare to 0...*/
3952           /* NOTE: this is a de-generate compare that most certainly 
3953            *       creates some dead code. */
3954           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
3955
3956         if(ifx) ifx->generated = 1;
3957         return;
3958
3959       }
3960       size--;
3961
3962       if(size == 0) {
3963         //i = (lit >> (size*8)) & 0xff;
3964         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3965         
3966         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
3967
3968         i = ((0-lit) & 0xff);
3969         if(sign) {
3970           if( i == 0x81) { 
3971             /* lit is 0x7f, all signed chars are less than
3972              * this except for 0x7f itself */
3973             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
3974             genSkipz2(&rFalseIfx,0);
3975           } else {
3976             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
3977             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
3978             genSkipc(&rFalseIfx);
3979           }
3980
3981         } else {
3982           if(lit == 1) {
3983             genSkipz2(&rFalseIfx,1);
3984           } else {
3985             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
3986             genSkipc(&rFalseIfx);
3987           }
3988         }
3989
3990         if(ifx) ifx->generated = 1;
3991         return;
3992       }
3993
3994       /* chars are out of the way. now do ints and longs */
3995
3996
3997       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
3998         
3999       /* special cases */
4000
4001       if(sign) {
4002
4003         if(lit == 0) {
4004           genSkipCond(&rFalseIfx,left,size,7);
4005           if(ifx) ifx->generated = 1;
4006           return;
4007         }
4008
4009         if(lit <0x100) {
4010           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4011
4012           //rFalseIfx.condition ^= 1;
4013           //genSkipCond(&rFalseIfx,left,size,7);
4014           //rFalseIfx.condition ^= 1;
4015
4016           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4017           if(rFalseIfx.condition)
4018             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4019           else
4020             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4021
4022           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4023           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4024           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4025
4026           while(size > 1)
4027             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4028
4029           if(rFalseIfx.condition) {
4030             emitSKPZ;
4031             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4032
4033           } else {
4034             emitSKPNZ;
4035           }
4036
4037           genSkipc(&rFalseIfx);
4038           pic16_emitpLabel(truelbl->key);
4039           if(ifx) ifx->generated = 1;
4040           return;
4041
4042         }
4043
4044         if(size == 1) {
4045
4046           if( (lit & 0xff) == 0) {
4047             /* lower byte is zero */
4048             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4049             i = ((lit >> 8) & 0xff) ^0x80;
4050             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4051             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4052             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4053             genSkipc(&rFalseIfx);
4054
4055
4056             if(ifx) ifx->generated = 1;
4057             return;
4058
4059           }
4060         } else {
4061           /* Special cases for signed longs */
4062           if( (lit & 0xffffff) == 0) {
4063             /* lower byte is zero */
4064             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4065             i = ((lit >> 8*3) & 0xff) ^0x80;
4066             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4067             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4068             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4069             genSkipc(&rFalseIfx);
4070
4071
4072             if(ifx) ifx->generated = 1;
4073             return;
4074
4075           }
4076
4077         }
4078
4079
4080         if(lit & (0x80 << (size*8))) {
4081           /* lit is negative */
4082           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4083
4084           //genSkipCond(&rFalseIfx,left,size,7);
4085
4086           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4087
4088           if(rFalseIfx.condition)
4089             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4090           else
4091             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4092
4093
4094         } else {
4095           /* lit is positive */
4096           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4097           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4098           if(rFalseIfx.condition)
4099             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4100           else
4101             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4102
4103         }
4104
4105         /*
4106           This works, but is only good for ints.
4107           It also requires a "known zero" register.
4108           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4109           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4110           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4111           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4112           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4113           genSkipc(&rFalseIfx);
4114
4115           pic16_emitpLabel(truelbl->key);
4116           if(ifx) ifx->generated = 1;
4117           return;
4118         **/
4119           
4120         /* There are no more special cases, so perform a general compare */
4121   
4122         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4123         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4124
4125         while(size--) {
4126
4127           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4128           emitSKPNZ;
4129           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4130         }
4131         //rFalseIfx.condition ^= 1;
4132         genSkipc(&rFalseIfx);
4133
4134         pic16_emitpLabel(truelbl->key);
4135
4136         if(ifx) ifx->generated = 1;
4137         return;
4138
4139
4140       }
4141
4142
4143       /* sign is out of the way. So now do an unsigned compare */
4144       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4145
4146
4147       /* General case - compare to an unsigned literal on the right.*/
4148
4149       i = (lit >> (size*8)) & 0xff;
4150       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4151       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4152       while(size--) {
4153         i = (lit >> (size*8)) & 0xff;
4154
4155         if(i) {
4156           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4157           emitSKPNZ;
4158           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4159         } else {
4160           /* this byte of the lit is zero, 
4161            *if it's not the last then OR in the variable */
4162           if(size)
4163             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4164         }
4165       }
4166
4167
4168       pic16_emitpLabel(lbl->key);
4169       //if(emitFinalCheck)
4170       genSkipc(&rFalseIfx);
4171       if(sign)
4172         pic16_emitpLabel(truelbl->key);
4173
4174       if(ifx) ifx->generated = 1;
4175       return;
4176
4177
4178     }
4179 #endif  // _swapp
4180
4181     if(AOP_TYPE(left) == AOP_LIT) {
4182       //symbol *lbl = newiTempLabel(NULL);
4183
4184       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4185
4186
4187       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4188
4189       /* Special cases */
4190       if((lit == 0) && (sign == 0)){
4191
4192         size--;
4193         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4194         while(size) 
4195           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4196
4197         genSkipz2(&rFalseIfx,0);
4198         if(ifx) ifx->generated = 1;
4199         return;
4200       }
4201
4202       if(size==1) {
4203         /* Special cases */
4204         lit &= 0xff;
4205         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4206           /* degenerate compare can never be true */
4207           if(rFalseIfx.condition == 0)
4208             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4209
4210           if(ifx) ifx->generated = 1;
4211           return;
4212         }
4213
4214         if(sign) {
4215           /* signed comparisons to a literal byte */
4216
4217           int lp1 = (lit+1) & 0xff;
4218
4219           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4220           switch (lp1) {
4221           case 0:
4222             rFalseIfx.condition ^= 1;
4223             genSkipCond(&rFalseIfx,right,0,7);
4224             break;
4225           case 0x7f:
4226             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4227             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4228             genSkipz2(&rFalseIfx,1);
4229             break;
4230           default:
4231             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4232             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4233             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4234             rFalseIfx.condition ^= 1;
4235             genSkipc(&rFalseIfx);
4236             break;
4237           }
4238         } else {
4239           /* unsigned comparisons to a literal byte */
4240
4241           switch(lit & 0xff ) {
4242           case 0:
4243             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4244             genSkipz2(&rFalseIfx,0);
4245             break;
4246           case 0x7f:
4247             rFalseIfx.condition ^= 1;
4248             genSkipCond(&rFalseIfx,right,0,7);
4249             break;
4250
4251           default:
4252             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4253             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4254             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4255             rFalseIfx.condition ^= 1;
4256             if (AOP_TYPE(result) == AOP_CRY)
4257               genSkipc(&rFalseIfx);
4258             else {
4259               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4260               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4261             }         
4262             break;
4263           }
4264         }
4265
4266         if(ifx) ifx->generated = 1;
4267         //goto check_carry;
4268         return;
4269
4270       } else {
4271
4272         /* Size is greater than 1 */
4273
4274         if(sign) {
4275           int lp1 = lit+1;
4276
4277           size--;
4278
4279           if(lp1 == 0) {
4280             /* this means lit = 0xffffffff, or -1 */
4281
4282
4283             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4284             rFalseIfx.condition ^= 1;
4285             genSkipCond(&rFalseIfx,right,size,7);
4286             if(ifx) ifx->generated = 1;
4287             return;
4288           }
4289
4290           if(lit == 0) {
4291             int s = size;
4292
4293             if(rFalseIfx.condition) {
4294               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4295               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4296             }
4297
4298             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4299             while(size--)
4300               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4301
4302
4303             emitSKPZ;
4304             if(rFalseIfx.condition) {
4305               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4306               pic16_emitpLabel(truelbl->key);
4307             }else {
4308               rFalseIfx.condition ^= 1;
4309               genSkipCond(&rFalseIfx,right,s,7);
4310             }
4311
4312             if(ifx) ifx->generated = 1;
4313             return;
4314           }
4315
4316           if((size == 1) &&  (0 == (lp1&0xff))) {
4317             /* lower byte of signed word is zero */
4318             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4319             i = ((lp1 >> 8) & 0xff) ^0x80;
4320             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4321             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4322             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4323             rFalseIfx.condition ^= 1;
4324             genSkipc(&rFalseIfx);
4325
4326
4327             if(ifx) ifx->generated = 1;
4328             return;
4329           }
4330
4331           if(lit & (0x80 << (size*8))) {
4332             /* Lit is less than zero */
4333             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4334             //rFalseIfx.condition ^= 1;
4335             //genSkipCond(&rFalseIfx,left,size,7);
4336             //rFalseIfx.condition ^= 1;
4337             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4338             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4339
4340             if(rFalseIfx.condition)
4341               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4342             else
4343               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4344
4345
4346           } else {
4347             /* Lit is greater than or equal to zero */
4348             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4349             //rFalseIfx.condition ^= 1;
4350             //genSkipCond(&rFalseIfx,right,size,7);
4351             //rFalseIfx.condition ^= 1;
4352
4353             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4354             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4355
4356             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4357             if(rFalseIfx.condition)
4358               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4359             else
4360               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4361
4362           }
4363
4364
4365           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4366           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4367
4368           while(size--) {
4369
4370             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4371             emitSKPNZ;
4372             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4373           }
4374           rFalseIfx.condition ^= 1;
4375           //rFalseIfx.condition = 1;
4376           genSkipc(&rFalseIfx);
4377
4378           pic16_emitpLabel(truelbl->key);
4379
4380           if(ifx) ifx->generated = 1;
4381           return;
4382           // end of if (sign)
4383         } else {
4384
4385           /* compare word or long to an unsigned literal on the right.*/
4386
4387
4388           size--;
4389           if(lit < 0xff) {
4390             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4391             switch (lit) {
4392             case 0:
4393               break; /* handled above */
4394 /*
4395             case 0xff:
4396               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4397               while(size--)
4398                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4399               genSkipz2(&rFalseIfx,0);
4400               break;
4401 */
4402             default:
4403               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4404               while(--size)
4405                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4406
4407               emitSKPZ;
4408               if(rFalseIfx.condition)
4409                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4410               else
4411                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4412
4413
4414               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4415               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4416
4417               rFalseIfx.condition ^= 1;
4418               genSkipc(&rFalseIfx);
4419             }
4420
4421             pic16_emitpLabel(truelbl->key);
4422
4423             if(ifx) ifx->generated = 1;
4424             return;
4425           }
4426
4427
4428           lit++;
4429           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4430           i = (lit >> (size*8)) & 0xff;
4431
4432           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4433           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4434
4435           while(size--) {
4436             i = (lit >> (size*8)) & 0xff;
4437
4438             if(i) {
4439               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4440               emitSKPNZ;
4441               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4442             } else {
4443               /* this byte of the lit is zero, 
4444                *if it's not the last then OR in the variable */
4445               if(size)
4446                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4447             }
4448           }
4449
4450
4451           pic16_emitpLabel(lbl->key);
4452
4453           rFalseIfx.condition ^= 1;
4454           genSkipc(&rFalseIfx);
4455         }
4456
4457         if(sign)
4458           pic16_emitpLabel(truelbl->key);
4459         if(ifx) ifx->generated = 1;
4460         return;
4461       }
4462     }
4463     /* Compare two variables */
4464
4465     DEBUGpic16_emitcode(";sign","%d",sign);
4466
4467     size--;
4468     if(sign) {
4469       /* Sigh. thus sucks... */
4470       if(size) {
4471         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4472         pic16_emitpcode(POC_MOVWF, popRegFromIdx(pic16_Gstack_base_addr));
4473         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4474         pic16_emitpcode(POC_XORWF, popRegFromIdx(pic16_Gstack_base_addr));
4475         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4476         pic16_emitpcode(POC_SUBFW, popRegFromIdx(pic16_Gstack_base_addr));
4477       } else {
4478         /* Signed char comparison */
4479         /* Special thanks to Nikolai Golovchenko for this snippet */
4480         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4481         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4482         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4483         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4484         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4485         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4486
4487         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4488         genSkipc(&rFalseIfx);
4489           
4490         if(ifx) ifx->generated = 1;
4491         return;
4492       }
4493
4494     } else {
4495
4496       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4497       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4498     }
4499
4500
4501     /* The rest of the bytes of a multi-byte compare */
4502     while (size) {
4503
4504       emitSKPZ;
4505       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4506       size--;
4507
4508       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4509       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4510
4511
4512     }
4513
4514     pic16_emitpLabel(lbl->key);
4515
4516     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4517     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4518         (AOP_TYPE(result) == AOP_REG)) {
4519       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4520       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4521     } else {
4522       genSkipc(&rFalseIfx);
4523     }         
4524     //genSkipc(&rFalseIfx);
4525     if(ifx) ifx->generated = 1;
4526
4527     return;
4528
4529   }
4530
4531   // check_carry:
4532   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4534     pic16_outBitC(result);
4535   } else {
4536     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4537     /* if the result is used in the next
4538        ifx conditional branch then generate
4539        code a little differently */
4540     if (ifx )
4541       genIfxJump (ifx,"c");
4542     else
4543       pic16_outBitC(result);
4544     /* leave the result in acc */
4545   }
4546
4547 }
4548
4549 /*-----------------------------------------------------------------*/
4550 /* genCmpGt :- greater than comparison                             */
4551 /*-----------------------------------------------------------------*/
4552 static void genCmpGt (iCode *ic, iCode *ifx)
4553 {
4554     operand *left, *right, *result;
4555     sym_link *letype , *retype;
4556     int sign ;
4557
4558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4559     left = IC_LEFT(ic);
4560     right= IC_RIGHT(ic);
4561     result = IC_RESULT(ic);
4562
4563     letype = getSpec(operandType(left));
4564     retype =getSpec(operandType(right));
4565     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4566     /* assign the amsops */
4567     pic16_aopOp (left,ic,FALSE);
4568     pic16_aopOp (right,ic,FALSE);
4569     pic16_aopOp (result,ic,TRUE);
4570
4571     genCmp(right, left, result, ifx, sign);
4572
4573     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4574     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4575     pic16_freeAsmop(result,NULL,ic,TRUE); 
4576 }
4577
4578 /*-----------------------------------------------------------------*/
4579 /* genCmpLt - less than comparisons                                */
4580 /*-----------------------------------------------------------------*/
4581 static void genCmpLt (iCode *ic, iCode *ifx)
4582 {
4583     operand *left, *right, *result;
4584     sym_link *letype , *retype;
4585     int sign ;
4586
4587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4588     left = IC_LEFT(ic);
4589     right= IC_RIGHT(ic);
4590     result = IC_RESULT(ic);
4591
4592     letype = getSpec(operandType(left));
4593     retype =getSpec(operandType(right));
4594     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4595
4596     /* assign the amsops */
4597     pic16_aopOp (left,ic,FALSE);
4598     pic16_aopOp (right,ic,FALSE);
4599     pic16_aopOp (result,ic,TRUE);
4600
4601     genCmp(left, right, result, ifx, sign);
4602
4603     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4604     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4605     pic16_freeAsmop(result,NULL,ic,TRUE); 
4606 }
4607
4608 /*-----------------------------------------------------------------*/
4609 /* genc16bit2lit - compare a 16 bit value to a literal             */
4610 /*-----------------------------------------------------------------*/
4611 static void genc16bit2lit(operand *op, int lit, int offset)
4612 {
4613   int i;
4614
4615   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4616   if( (lit&0xff) == 0) 
4617     i=1;
4618   else
4619     i=0;
4620
4621   switch( BYTEofLONG(lit,i)) { 
4622   case 0:
4623     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4624     break;
4625   case 1:
4626     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4627     break;
4628   case 0xff:
4629     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4630     break;
4631   default:
4632     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4633     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4634   }
4635
4636   i ^= 1;
4637
4638   switch( BYTEofLONG(lit,i)) { 
4639   case 0:
4640     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4641     break;
4642   case 1:
4643     emitSKPNZ;
4644     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4645     break;
4646   case 0xff:
4647     emitSKPNZ;
4648     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4649     break;
4650   default:
4651     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4652     emitSKPNZ;
4653     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4654
4655   }
4656
4657 }
4658
4659 /*-----------------------------------------------------------------*/
4660 /* gencjneshort - compare and jump if not equal                    */
4661 /*-----------------------------------------------------------------*/
4662 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4663 {
4664   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4665   int offset = 0;
4666   int res_offset = 0;  /* the result may be a different size then left or right */
4667   int res_size = AOP_SIZE(result);
4668   resolvedIfx rIfx;
4669   symbol *lbl;
4670
4671   unsigned long lit = 0L;
4672   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4673   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4674   if(result)
4675     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4676   resolveIfx(&rIfx,ifx);
4677   lbl =  newiTempLabel(NULL);
4678
4679
4680   /* if the left side is a literal or 
4681      if the right is in a pointer register and left 
4682      is not */
4683   if ((AOP_TYPE(left) == AOP_LIT) || 
4684       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4685     operand *t = right;
4686     right = left;
4687     left = t;
4688   }
4689   if(AOP_TYPE(right) == AOP_LIT)
4690     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4691
4692   /* if the right side is a literal then anything goes */
4693   if (AOP_TYPE(right) == AOP_LIT &&
4694       AOP_TYPE(left) != AOP_DIR ) {
4695     switch(size) {
4696     case 2:
4697       genc16bit2lit(left, lit, 0);
4698       emitSKPNZ;
4699       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4700       break;
4701     default:
4702       while (size--) {
4703         if(lit & 0xff) {
4704           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4705           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4706         } else {
4707           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4708         }
4709
4710         emitSKPNZ;
4711         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4712         offset++;
4713         if(res_offset < res_size-1)
4714           res_offset++;
4715         lit >>= 8;
4716       }
4717       break;
4718     }
4719   }
4720
4721   /* if the right side is in a register or in direct space or
4722      if the left is a pointer register & right is not */    
4723   else if (AOP_TYPE(right) == AOP_REG ||
4724            AOP_TYPE(right) == AOP_DIR || 
4725            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4726            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4727     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4728     int lbl_key = lbl->key;
4729
4730     if(result) {
4731       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4732       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4733     }else {
4734       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4735       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4736               __FUNCTION__,__LINE__);
4737       return;
4738     }
4739
4740 /*     switch(size) { */
4741 /*     case 2: */
4742 /*       genc16bit2lit(left, lit, 0); */
4743 /*       emitSKPNZ; */
4744 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4745 /*       break; */
4746 /*     default: */
4747     while (size--) {
4748       int emit_skip=1;
4749       if((AOP_TYPE(left) == AOP_DIR) && 
4750          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4751
4752         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4753         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4754
4755       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4756             
4757         switch (lit & 0xff) {
4758         case 0:
4759           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4760           break;
4761         case 1:
4762           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4763           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4764           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4765           emit_skip=0;
4766           break;
4767         case 0xff:
4768           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4769           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4770           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4771           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4772           emit_skip=0;
4773           break;
4774         default:
4775           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4776           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4777         }
4778         lit >>= 8;
4779
4780       } else {
4781         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4782       }
4783       if(emit_skip) {
4784         if(AOP_TYPE(result) == AOP_CRY) {
4785           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4786           if(rIfx.condition)
4787             emitSKPNZ;
4788           else
4789             emitSKPZ;
4790           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4791         } else {
4792           /* fix me. probably need to check result size too */
4793           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4794           if(rIfx.condition)
4795             emitSKPZ;
4796           else
4797             emitSKPNZ;
4798           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4799           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4800         }
4801         if(ifx)
4802           ifx->generated=1;
4803       }
4804       emit_skip++;
4805       offset++;
4806       if(res_offset < res_size-1)
4807         res_offset++;
4808     }
4809 /*       break; */
4810 /*     } */
4811   } else if(AOP_TYPE(right) == AOP_REG &&
4812             AOP_TYPE(left) != AOP_DIR){
4813
4814     while(size--) {
4815       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4816       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4817       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4818       if(rIfx.condition)
4819         emitSKPNZ;
4820       else
4821         emitSKPZ;
4822       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4823       offset++;
4824       if(res_offset < res_size-1)
4825         res_offset++;
4826     }
4827       
4828   }else{
4829     /* right is a pointer reg need both a & b */
4830     while(size--) {
4831       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4832       if(strcmp(l,"b"))
4833         pic16_emitcode("mov","b,%s",l);
4834       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4835       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4836       offset++;
4837     }
4838   }
4839
4840   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4841   if(!rIfx.condition)
4842     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4843
4844   pic16_emitpLabel(lbl->key);
4845
4846   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4847
4848   if(ifx)
4849     ifx->generated = 1;
4850 }
4851
4852 #if 0
4853 /*-----------------------------------------------------------------*/
4854 /* gencjne - compare and jump if not equal                         */
4855 /*-----------------------------------------------------------------*/
4856 static void gencjne(operand *left, operand *right, iCode *ifx)
4857 {
4858     symbol *tlbl  = newiTempLabel(NULL);
4859
4860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4861     gencjneshort(left, right, lbl);
4862
4863     pic16_emitcode("mov","a,%s",one);
4864     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4865     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4866     pic16_emitcode("clr","a");
4867     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4868
4869     pic16_emitpLabel(lbl->key);
4870     pic16_emitpLabel(tlbl->key);
4871
4872 }
4873 #endif
4874
4875 /*-----------------------------------------------------------------*/
4876 /* genCmpEq - generates code for equal to                          */
4877 /*-----------------------------------------------------------------*/
4878 static void genCmpEq (iCode *ic, iCode *ifx)
4879 {
4880     operand *left, *right, *result;
4881     unsigned long lit = 0L;
4882     int size,offset=0;
4883
4884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4885
4886     if(ifx)
4887       DEBUGpic16_emitcode ("; ifx is non-null","");
4888     else
4889       DEBUGpic16_emitcode ("; ifx is null","");
4890
4891     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4892     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4893     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4894
4895     size = max(AOP_SIZE(left),AOP_SIZE(right));
4896
4897     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4898
4899     /* if literal, literal on the right or 
4900     if the right is in a pointer register and left 
4901     is not */
4902     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4903         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4904       operand *tmp = right ;
4905       right = left;
4906       left = tmp;
4907     }
4908
4909
4910     if(ifx && !AOP_SIZE(result)){
4911         symbol *tlbl;
4912         /* if they are both bit variables */
4913         if (AOP_TYPE(left) == AOP_CRY &&
4914             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4915             if(AOP_TYPE(right) == AOP_LIT){
4916                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4917                 if(lit == 0L){
4918                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4919                     pic16_emitcode("cpl","c");
4920                 } else if(lit == 1L) {
4921                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4922                 } else {
4923                     pic16_emitcode("clr","c");
4924                 }
4925                 /* AOP_TYPE(right) == AOP_CRY */
4926             } else {
4927                 symbol *lbl = newiTempLabel(NULL);
4928                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4929                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4930                 pic16_emitcode("cpl","c");
4931                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4932             }
4933             /* if true label then we jump if condition
4934             supplied is true */
4935             tlbl = newiTempLabel(NULL);
4936             if ( IC_TRUE(ifx) ) {
4937                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4938                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4939             } else {
4940                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4941                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4942             }
4943             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4944
4945             {
4946               /* left and right are both bit variables, result is carry */
4947               resolvedIfx rIfx;
4948               
4949               resolveIfx(&rIfx,ifx);
4950
4951               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4952               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4953               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4954               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4955               genSkipz2(&rIfx,0);
4956             }
4957         } else {
4958
4959           /* They're not both bit variables. Is the right a literal? */
4960           if(AOP_TYPE(right) == AOP_LIT) {
4961             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4962             
4963             switch(size) {
4964
4965             case 1:
4966               switch(lit & 0xff) {
4967               case 1:
4968                 if ( IC_TRUE(ifx) ) {
4969                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4970                   emitSKPNZ;
4971                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4972                 } else {
4973                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4974                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4975                 }
4976                 break;
4977               case 0xff:
4978                 if ( IC_TRUE(ifx) ) {
4979                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4980                   emitSKPNZ;
4981                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4982                 } else {
4983                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4984                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4985                 }
4986                 break;
4987               default:
4988                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4989                 if(lit)
4990                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4991                 genSkip(ifx,'z');
4992               }
4993
4994
4995               /* end of size == 1 */
4996               break;
4997               
4998             case 2:
4999               genc16bit2lit(left,lit,offset);
5000               genSkip(ifx,'z');
5001               break;
5002               /* end of size == 2 */
5003
5004             default:
5005               /* size is 4 */
5006               if(lit==0) {
5007                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5008                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5009                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5010                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5011
5012               } else {
5013
5014                 /* search for patterns that can be optimized */
5015
5016                 genc16bit2lit(left,lit,0);
5017                 lit >>= 16;
5018                 if(lit) {
5019                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
5020                   //genSkip(ifx,'z');
5021                   genc16bit2lit(left,lit,2);
5022                 } else {
5023                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5024                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5025
5026                 }
5027                 
5028               }
5029
5030               genSkip(ifx,'z');
5031             }
5032           
5033             ifx->generated = 1;
5034             goto release ;
5035             
5036
5037           } else if(AOP_TYPE(right) == AOP_CRY ) {
5038             /* we know the left is not a bit, but that the right is */
5039             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5040             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5041                       pic16_popGet(AOP(right),offset));
5042             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5043
5044             /* if the two are equal, then W will be 0 and the Z bit is set
5045              * we could test Z now, or go ahead and check the high order bytes if
5046              * the variable we're comparing is larger than a byte. */
5047
5048             while(--size)
5049               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5050
5051             if ( IC_TRUE(ifx) ) {
5052               emitSKPNZ;
5053               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5054               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5055             } else {
5056               emitSKPZ;
5057               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5058               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5059             }
5060
5061           } else {
5062             /* They're both variables that are larger than bits */
5063             int s = size;
5064
5065             tlbl = newiTempLabel(NULL);
5066
5067             while(size--) {
5068               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5069               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5070
5071               if ( IC_TRUE(ifx) ) {
5072                 if(size) {
5073                   emitSKPZ;
5074                 
5075                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5076
5077                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5078                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5079                 } else {
5080                   emitSKPNZ;
5081
5082                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5083
5084
5085                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5086                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5087                 }
5088               } else {
5089                 emitSKPZ;
5090
5091                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5092
5093                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5094                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5095               }
5096               offset++;
5097             }
5098             if(s>1 && IC_TRUE(ifx)) {
5099               pic16_emitpLabel(tlbl->key);
5100               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5101             }
5102           }
5103         }
5104         /* mark the icode as generated */
5105         ifx->generated = 1;
5106         goto release ;
5107     }
5108
5109     /* if they are both bit variables */
5110     if (AOP_TYPE(left) == AOP_CRY &&
5111         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5112         if(AOP_TYPE(right) == AOP_LIT){
5113             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5114             if(lit == 0L){
5115                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5116                 pic16_emitcode("cpl","c");
5117             } else if(lit == 1L) {
5118                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5119             } else {
5120                 pic16_emitcode("clr","c");
5121             }
5122             /* AOP_TYPE(right) == AOP_CRY */
5123         } else {
5124             symbol *lbl = newiTempLabel(NULL);
5125             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5126             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5127             pic16_emitcode("cpl","c");
5128             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5129         }
5130         /* c = 1 if egal */
5131         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5132             pic16_outBitC(result);
5133             goto release ;
5134         }
5135         if (ifx) {
5136             genIfxJump (ifx,"c");
5137             goto release ;
5138         }
5139         /* if the result is used in an arithmetic operation
5140         then put the result in place */
5141         pic16_outBitC(result);
5142     } else {
5143       
5144       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5145       gencjne(left,right,result,ifx);
5146 /*
5147       if(ifx) 
5148         gencjne(left,right,newiTempLabel(NULL));
5149       else {
5150         if(IC_TRUE(ifx)->key)
5151           gencjne(left,right,IC_TRUE(ifx)->key);
5152         else
5153           gencjne(left,right,IC_FALSE(ifx)->key);
5154         ifx->generated = 1;
5155         goto release ;
5156       }
5157       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5158         pic16_aopPut(AOP(result),"a",0);
5159         goto release ;
5160       }
5161
5162       if (ifx) {
5163         genIfxJump (ifx,"a");
5164         goto release ;
5165       }
5166 */
5167       /* if the result is used in an arithmetic operation
5168          then put the result in place */
5169 /*
5170       if (AOP_TYPE(result) != AOP_CRY) 
5171         pic16_outAcc(result);
5172 */
5173       /* leave the result in acc */
5174     }
5175
5176 release:
5177     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5178     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5179     pic16_freeAsmop(result,NULL,ic,TRUE);
5180 }
5181
5182 /*-----------------------------------------------------------------*/
5183 /* ifxForOp - returns the icode containing the ifx for operand     */
5184 /*-----------------------------------------------------------------*/
5185 static iCode *ifxForOp ( operand *op, iCode *ic )
5186 {
5187     /* if true symbol then needs to be assigned */
5188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5189     if (IS_TRUE_SYMOP(op))
5190         return NULL ;
5191
5192     /* if this has register type condition and
5193     the next instruction is ifx with the same operand
5194     and live to of the operand is upto the ifx only then */
5195     if (ic->next &&
5196         ic->next->op == IFX &&
5197         IC_COND(ic->next)->key == op->key &&
5198         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5199         return ic->next;
5200
5201     if (ic->next &&
5202         ic->next->op == IFX &&
5203         IC_COND(ic->next)->key == op->key) {
5204       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5205       return ic->next;
5206     }
5207
5208     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5209     if (ic->next &&
5210         ic->next->op == IFX)
5211       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5212
5213     if (ic->next &&
5214         ic->next->op == IFX &&
5215         IC_COND(ic->next)->key == op->key) {
5216       DEBUGpic16_emitcode ("; "," key is okay");
5217       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5218                            OP_SYMBOL(op)->liveTo,
5219                            ic->next->seq);
5220     }
5221
5222
5223     return NULL;
5224 }
5225 /*-----------------------------------------------------------------*/
5226 /* genAndOp - for && operation                                     */
5227 /*-----------------------------------------------------------------*/
5228 static void genAndOp (iCode *ic)
5229 {
5230     operand *left,*right, *result;
5231 /*     symbol *tlbl; */
5232
5233     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5234     /* note here that && operations that are in an
5235     if statement are taken away by backPatchLabels
5236     only those used in arthmetic operations remain */
5237     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5238     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5239     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5240
5241     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5242
5243     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5244     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5245     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5246
5247     /* if both are bit variables */
5248 /*     if (AOP_TYPE(left) == AOP_CRY && */
5249 /*         AOP_TYPE(right) == AOP_CRY ) { */
5250 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5251 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5252 /*         pic16_outBitC(result); */
5253 /*     } else { */
5254 /*         tlbl = newiTempLabel(NULL); */
5255 /*         pic16_toBoolean(left);     */
5256 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5257 /*         pic16_toBoolean(right); */
5258 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5259 /*         pic16_outBitAcc(result); */
5260 /*     } */
5261
5262     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5263     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5264     pic16_freeAsmop(result,NULL,ic,TRUE);
5265 }
5266
5267
5268 /*-----------------------------------------------------------------*/
5269 /* genOrOp - for || operation                                      */
5270 /*-----------------------------------------------------------------*/
5271 /*
5272   tsd pic port -
5273   modified this code, but it doesn't appear to ever get called
5274 */
5275
5276 static void genOrOp (iCode *ic)
5277 {
5278     operand *left,*right, *result;
5279     symbol *tlbl;
5280
5281     /* note here that || operations that are in an
5282     if statement are taken away by backPatchLabels
5283     only those used in arthmetic operations remain */
5284     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5285     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5286     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5287     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5288
5289     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5290
5291     /* if both are bit variables */
5292     if (AOP_TYPE(left) == AOP_CRY &&
5293         AOP_TYPE(right) == AOP_CRY ) {
5294       pic16_emitcode("clrc","");
5295       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5296                AOP(left)->aopu.aop_dir,
5297                AOP(left)->aopu.aop_dir);
5298       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5299                AOP(right)->aopu.aop_dir,
5300                AOP(right)->aopu.aop_dir);
5301       pic16_emitcode("setc","");
5302
5303     } else {
5304         tlbl = newiTempLabel(NULL);
5305         pic16_toBoolean(left);
5306         emitSKPZ;
5307         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5308         pic16_toBoolean(right);
5309         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5310
5311         pic16_outBitAcc(result);
5312     }
5313
5314     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5315     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5316     pic16_freeAsmop(result,NULL,ic,TRUE);            
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* isLiteralBit - test if lit == 2^n                               */
5321 /*-----------------------------------------------------------------*/
5322 static int isLiteralBit(unsigned long lit)
5323 {
5324     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5325     0x100L,0x200L,0x400L,0x800L,
5326     0x1000L,0x2000L,0x4000L,0x8000L,
5327     0x10000L,0x20000L,0x40000L,0x80000L,
5328     0x100000L,0x200000L,0x400000L,0x800000L,
5329     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5330     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5331     int idx;
5332     
5333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5334     for(idx = 0; idx < 32; idx++)
5335         if(lit == pw[idx])
5336             return idx+1;
5337     return 0;
5338 }
5339
5340 /*-----------------------------------------------------------------*/
5341 /* continueIfTrue -                                                */
5342 /*-----------------------------------------------------------------*/
5343 static void continueIfTrue (iCode *ic)
5344 {
5345     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5346     if(IC_TRUE(ic))
5347         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5348     ic->generated = 1;
5349 }
5350
5351 /*-----------------------------------------------------------------*/
5352 /* jmpIfTrue -                                                     */
5353 /*-----------------------------------------------------------------*/
5354 static void jumpIfTrue (iCode *ic)
5355 {
5356     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5357     if(!IC_TRUE(ic))
5358         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5359     ic->generated = 1;
5360 }
5361
5362 /*-----------------------------------------------------------------*/
5363 /* jmpTrueOrFalse -                                                */
5364 /*-----------------------------------------------------------------*/
5365 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5366 {
5367     // ugly but optimized by peephole
5368     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5369     if(IC_TRUE(ic)){
5370         symbol *nlbl = newiTempLabel(NULL);
5371         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5372         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5373         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5374         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5375     }
5376     else{
5377         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5378         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5379     }
5380     ic->generated = 1;
5381 }
5382
5383 /*-----------------------------------------------------------------*/
5384 /* genAnd  - code for and                                          */
5385 /*-----------------------------------------------------------------*/
5386 static void genAnd (iCode *ic, iCode *ifx)
5387 {
5388   operand *left, *right, *result;
5389   int size, offset=0;  
5390   unsigned long lit = 0L;
5391   int bytelit = 0;
5392   resolvedIfx rIfx;
5393
5394
5395   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5396   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5397   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5398   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5399
5400   resolveIfx(&rIfx,ifx);
5401
5402   /* if left is a literal & right is not then exchange them */
5403   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5404       AOP_NEEDSACC(left)) {
5405     operand *tmp = right ;
5406     right = left;
5407     left = tmp;
5408   }
5409
5410   /* if result = right then exchange them */
5411   if(pic16_sameRegs(AOP(result),AOP(right))){
5412     operand *tmp = right ;
5413     right = left;
5414     left = tmp;
5415   }
5416
5417   /* if right is bit then exchange them */
5418   if (AOP_TYPE(right) == AOP_CRY &&
5419       AOP_TYPE(left) != AOP_CRY){
5420     operand *tmp = right ;
5421     right = left;
5422     left = tmp;
5423   }
5424   if(AOP_TYPE(right) == AOP_LIT)
5425     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5426
5427   size = AOP_SIZE(result);
5428
5429   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5430
5431   // if(bit & yy)
5432   // result = bit & yy;
5433   if (AOP_TYPE(left) == AOP_CRY){
5434     // c = bit & literal;
5435     if(AOP_TYPE(right) == AOP_LIT){
5436       if(lit & 1) {
5437         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5438           // no change
5439           goto release;
5440         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5441       } else {
5442         // bit(result) = 0;
5443         if(size && (AOP_TYPE(result) == AOP_CRY)){
5444           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5445           goto release;
5446         }
5447         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5448           jumpIfTrue(ifx);
5449           goto release;
5450         }
5451         pic16_emitcode("clr","c");
5452       }
5453     } else {
5454       if (AOP_TYPE(right) == AOP_CRY){
5455         // c = bit & bit;
5456         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5457         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5458       } else {
5459         // c = bit & val;
5460         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5461         // c = lsb
5462         pic16_emitcode("rrc","a");
5463         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5464       }
5465     }
5466     // bit = c
5467     // val = c
5468     if(size)
5469       pic16_outBitC(result);
5470     // if(bit & ...)
5471     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5472       genIfxJump(ifx, "c");           
5473     goto release ;
5474   }
5475
5476   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5477   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5478   if((AOP_TYPE(right) == AOP_LIT) &&
5479      (AOP_TYPE(result) == AOP_CRY) &&
5480      (AOP_TYPE(left) != AOP_CRY)){
5481     int posbit = isLiteralBit(lit);
5482     /* left &  2^n */
5483     if(posbit){
5484       posbit--;
5485       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5486       // bit = left & 2^n
5487       if(size)
5488         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5489       // if(left &  2^n)
5490       else{
5491         if(ifx){
5492 /*
5493           if(IC_TRUE(ifx)) {
5494             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5495             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5496           } else {
5497             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5498             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5499           }
5500 */
5501           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5502                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5503           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5504           
5505           ifx->generated = 1;
5506         }
5507         goto release;
5508       }
5509     } else {
5510       symbol *tlbl = newiTempLabel(NULL);
5511       int sizel = AOP_SIZE(left);
5512       if(size)
5513         pic16_emitcode("setb","c");
5514       while(sizel--){
5515         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5516           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5517           // byte ==  2^n ?
5518           if((posbit = isLiteralBit(bytelit)) != 0)
5519             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5520           else{
5521             if(bytelit != 0x0FFL)
5522               pic16_emitcode("anl","a,%s",
5523                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5524             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5525           }
5526         }
5527         offset++;
5528       }
5529       // bit = left & literal
5530       if(size){
5531         pic16_emitcode("clr","c");
5532         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5533       }
5534       // if(left & literal)
5535       else{
5536         if(ifx)
5537           jmpTrueOrFalse(ifx, tlbl);
5538         goto release ;
5539       }
5540     }
5541     pic16_outBitC(result);
5542     goto release ;
5543   }
5544
5545   /* if left is same as result */
5546   if(pic16_sameRegs(AOP(result),AOP(left))){
5547     int know_W = -1;
5548     for(;size--; offset++,lit>>=8) {
5549       if(AOP_TYPE(right) == AOP_LIT){
5550         switch(lit & 0xff) {
5551         case 0x00:
5552           /*  and'ing with 0 has clears the result */
5553 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5554           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5555           break;
5556         case 0xff:
5557           /* and'ing with 0xff is a nop when the result and left are the same */
5558           break;
5559
5560         default:
5561           {
5562             int p = my_powof2( (~lit) & 0xff );
5563             if(p>=0) {
5564               /* only one bit is set in the literal, so use a bcf instruction */
5565 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5566               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5567
5568             } else {
5569               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5570               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5571               if(know_W != (lit&0xff))
5572                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5573               know_W = lit &0xff;
5574               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5575             }
5576           }    
5577         }
5578       } else {
5579         if (AOP_TYPE(left) == AOP_ACC) {
5580           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5581         } else {                    
5582           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5583           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5584
5585         }
5586       }
5587     }
5588
5589   } else {
5590     // left & result in different registers
5591     if(AOP_TYPE(result) == AOP_CRY){
5592       // result = bit
5593       // if(size), result in bit
5594       // if(!size && ifx), conditional oper: if(left & right)
5595       symbol *tlbl = newiTempLabel(NULL);
5596       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5597       if(size)
5598         pic16_emitcode("setb","c");
5599       while(sizer--){
5600         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5601         pic16_emitcode("anl","a,%s",
5602                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5603         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5604         offset++;
5605       }
5606       if(size){
5607         CLRC;
5608         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5609         pic16_outBitC(result);
5610       } else if(ifx)
5611         jmpTrueOrFalse(ifx, tlbl);
5612     } else {
5613       for(;(size--);offset++) {
5614         // normal case
5615         // result = left & right
5616         if(AOP_TYPE(right) == AOP_LIT){
5617           int t = (lit >> (offset*8)) & 0x0FFL;
5618           switch(t) { 
5619           case 0x00:
5620             pic16_emitcode("clrf","%s",
5621                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5622             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5623             break;
5624           case 0xff:
5625             pic16_emitcode("movf","%s,w",
5626                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5627             pic16_emitcode("movwf","%s",
5628                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5629             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5630             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5631             break;
5632           default:
5633             pic16_emitcode("movlw","0x%x",t);
5634             pic16_emitcode("andwf","%s,w",
5635                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5636             pic16_emitcode("movwf","%s",
5637                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5638               
5639             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5640             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5641             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5642           }
5643           continue;
5644         }
5645
5646         if (AOP_TYPE(left) == AOP_ACC) {
5647           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5648           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5649         } else {
5650           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5651           pic16_emitcode("andwf","%s,w",
5652                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5653           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5654           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5655         }
5656         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5657         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5658       }
5659     }
5660   }
5661
5662   release :
5663     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5664   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5665   pic16_freeAsmop(result,NULL,ic,TRUE);     
5666 }
5667
5668 /*-----------------------------------------------------------------*/
5669 /* genOr  - code for or                                            */
5670 /*-----------------------------------------------------------------*/
5671 static void genOr (iCode *ic, iCode *ifx)
5672 {
5673     operand *left, *right, *result;
5674     int size, offset=0;
5675     unsigned long lit = 0L;
5676
5677     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5678
5679     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5680     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5681     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5682
5683     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5684
5685     /* if left is a literal & right is not then exchange them */
5686     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5687         AOP_NEEDSACC(left)) {
5688         operand *tmp = right ;
5689         right = left;
5690         left = tmp;
5691     }
5692
5693     /* if result = right then exchange them */
5694     if(pic16_sameRegs(AOP(result),AOP(right))){
5695         operand *tmp = right ;
5696         right = left;
5697         left = tmp;
5698     }
5699
5700     /* if right is bit then exchange them */
5701     if (AOP_TYPE(right) == AOP_CRY &&
5702         AOP_TYPE(left) != AOP_CRY){
5703         operand *tmp = right ;
5704         right = left;
5705         left = tmp;
5706     }
5707
5708     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5709
5710     if(AOP_TYPE(right) == AOP_LIT)
5711         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5712
5713     size = AOP_SIZE(result);
5714
5715     // if(bit | yy)
5716     // xx = bit | yy;
5717     if (AOP_TYPE(left) == AOP_CRY){
5718         if(AOP_TYPE(right) == AOP_LIT){
5719             // c = bit & literal;
5720             if(lit){
5721                 // lit != 0 => result = 1
5722                 if(AOP_TYPE(result) == AOP_CRY){
5723                   if(size)
5724                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5725                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5726                   //     AOP(result)->aopu.aop_dir,
5727                   //     AOP(result)->aopu.aop_dir);
5728                     else if(ifx)
5729                         continueIfTrue(ifx);
5730                     goto release;
5731                 }
5732             } else {
5733                 // lit == 0 => result = left
5734                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5735                     goto release;
5736                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5737             }
5738         } else {
5739             if (AOP_TYPE(right) == AOP_CRY){
5740               if(pic16_sameRegs(AOP(result),AOP(left))){
5741                 // c = bit | bit;
5742                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5743                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5744                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5745
5746                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5747                          AOP(result)->aopu.aop_dir,
5748                          AOP(result)->aopu.aop_dir);
5749                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5750                          AOP(right)->aopu.aop_dir,
5751                          AOP(right)->aopu.aop_dir);
5752                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5753                          AOP(result)->aopu.aop_dir,
5754                          AOP(result)->aopu.aop_dir);
5755               } else {
5756                 if( AOP_TYPE(result) == AOP_ACC) {
5757                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5758                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5759                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5760                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5761
5762                 } else {
5763
5764                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5765                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5766                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5767                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5768
5769                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5770                                  AOP(result)->aopu.aop_dir,
5771                                  AOP(result)->aopu.aop_dir);
5772                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5773                                  AOP(right)->aopu.aop_dir,
5774                                  AOP(right)->aopu.aop_dir);
5775                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5776                                  AOP(left)->aopu.aop_dir,
5777                                  AOP(left)->aopu.aop_dir);
5778                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5779                                  AOP(result)->aopu.aop_dir,
5780                                  AOP(result)->aopu.aop_dir);
5781                 }
5782               }
5783             } else {
5784                 // c = bit | val;
5785                 symbol *tlbl = newiTempLabel(NULL);
5786                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5787
5788
5789                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5790                 if( AOP_TYPE(right) == AOP_ACC) {
5791                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5792                   emitSKPNZ;
5793                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5794                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5795                 }
5796
5797
5798
5799                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5800                     pic16_emitcode(";XXX setb","c");
5801                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5802                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5803                 pic16_toBoolean(right);
5804                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5805                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5806                     jmpTrueOrFalse(ifx, tlbl);
5807                     goto release;
5808                 } else {
5809                     CLRC;
5810                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5811                 }
5812             }
5813         }
5814         // bit = c
5815         // val = c
5816         if(size)
5817             pic16_outBitC(result);
5818         // if(bit | ...)
5819         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5820             genIfxJump(ifx, "c");           
5821         goto release ;
5822     }
5823
5824     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5825     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5826     if((AOP_TYPE(right) == AOP_LIT) &&
5827        (AOP_TYPE(result) == AOP_CRY) &&
5828        (AOP_TYPE(left) != AOP_CRY)){
5829         if(lit){
5830           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5831             // result = 1
5832             if(size)
5833                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5834             else 
5835                 continueIfTrue(ifx);
5836             goto release;
5837         } else {
5838           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5839             // lit = 0, result = boolean(left)
5840             if(size)
5841                 pic16_emitcode(";XXX setb","c");
5842             pic16_toBoolean(right);
5843             if(size){
5844                 symbol *tlbl = newiTempLabel(NULL);
5845                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5846                 CLRC;
5847                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5848             } else {
5849                 genIfxJump (ifx,"a");
5850                 goto release;
5851             }
5852         }
5853         pic16_outBitC(result);
5854         goto release ;
5855     }
5856
5857     /* if left is same as result */
5858     if(pic16_sameRegs(AOP(result),AOP(left))){
5859       int know_W = -1;
5860       for(;size--; offset++,lit>>=8) {
5861         if(AOP_TYPE(right) == AOP_LIT){
5862           if((lit & 0xff) == 0)
5863             /*  or'ing with 0 has no effect */
5864             continue;
5865           else {
5866             int p = my_powof2(lit & 0xff);
5867             if(p>=0) {
5868               /* only one bit is set in the literal, so use a bsf instruction */
5869               pic16_emitpcode(POC_BSF,
5870                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5871             } else {
5872               if(know_W != (lit & 0xff))
5873                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5874               know_W = lit & 0xff;
5875               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5876             }
5877                     
5878           }
5879         } else {
5880           if (AOP_TYPE(left) == AOP_ACC) {
5881             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5882             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5883           } else {                  
5884             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5885             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5886
5887             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5888             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5889
5890           }
5891         }
5892       }
5893     } else {
5894         // left & result in different registers
5895         if(AOP_TYPE(result) == AOP_CRY){
5896             // result = bit
5897             // if(size), result in bit
5898             // if(!size && ifx), conditional oper: if(left | right)
5899             symbol *tlbl = newiTempLabel(NULL);
5900             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5901             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5902
5903
5904             if(size)
5905                 pic16_emitcode(";XXX setb","c");
5906             while(sizer--){
5907                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5908                 pic16_emitcode(";XXX orl","a,%s",
5909                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5910                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5911                 offset++;
5912             }
5913             if(size){
5914                 CLRC;
5915                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5916                 pic16_outBitC(result);
5917             } else if(ifx)
5918                 jmpTrueOrFalse(ifx, tlbl);
5919         } else for(;(size--);offset++){
5920           // normal case
5921           // result = left & right
5922           if(AOP_TYPE(right) == AOP_LIT){
5923             int t = (lit >> (offset*8)) & 0x0FFL;
5924             switch(t) { 
5925             case 0x00:
5926               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5927               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5928
5929               pic16_emitcode("movf","%s,w",
5930                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5931               pic16_emitcode("movwf","%s",
5932                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5933               break;
5934             default:
5935               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5936               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5937               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5938
5939               pic16_emitcode("movlw","0x%x",t);
5940               pic16_emitcode("iorwf","%s,w",
5941                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5942               pic16_emitcode("movwf","%s",
5943                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5944               
5945             }
5946             continue;
5947           }
5948
5949           // faster than result <- left, anl result,right
5950           // and better if result is SFR
5951           if (AOP_TYPE(left) == AOP_ACC) {
5952             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5953             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5954           } else {
5955             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5956             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5957
5958             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5959             pic16_emitcode("iorwf","%s,w",
5960                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5961           }
5962           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5963           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5964         }
5965     }
5966
5967 release :
5968     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5969     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5970     pic16_freeAsmop(result,NULL,ic,TRUE);     
5971 }
5972
5973 /*-----------------------------------------------------------------*/
5974 /* genXor - code for xclusive or                                   */
5975 /*-----------------------------------------------------------------*/
5976 static void genXor (iCode *ic, iCode *ifx)
5977 {
5978   operand *left, *right, *result;
5979   int size, offset=0;
5980   unsigned long lit = 0L;
5981
5982   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5983
5984   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5985   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5986   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5987
5988   /* if left is a literal & right is not ||
5989      if left needs acc & right does not */
5990   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5991       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5992     operand *tmp = right ;
5993     right = left;
5994     left = tmp;
5995   }
5996
5997   /* if result = right then exchange them */
5998   if(pic16_sameRegs(AOP(result),AOP(right))){
5999     operand *tmp = right ;
6000     right = left;
6001     left = tmp;
6002   }
6003
6004   /* if right is bit then exchange them */
6005   if (AOP_TYPE(right) == AOP_CRY &&
6006       AOP_TYPE(left) != AOP_CRY){
6007     operand *tmp = right ;
6008     right = left;
6009     left = tmp;
6010   }
6011   if(AOP_TYPE(right) == AOP_LIT)
6012     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6013
6014   size = AOP_SIZE(result);
6015
6016   // if(bit ^ yy)
6017   // xx = bit ^ yy;
6018   if (AOP_TYPE(left) == AOP_CRY){
6019     if(AOP_TYPE(right) == AOP_LIT){
6020       // c = bit & literal;
6021       if(lit>>1){
6022         // lit>>1  != 0 => result = 1
6023         if(AOP_TYPE(result) == AOP_CRY){
6024           if(size)
6025             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6026             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6027           else if(ifx)
6028             continueIfTrue(ifx);
6029           goto release;
6030         }
6031         pic16_emitcode("setb","c");
6032       } else{
6033         // lit == (0 or 1)
6034         if(lit == 0){
6035           // lit == 0, result = left
6036           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6037             goto release;
6038           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6039         } else{
6040           // lit == 1, result = not(left)
6041           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6042             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6043             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6044             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6045             goto release;
6046           } else {
6047             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6048             pic16_emitcode("cpl","c");
6049           }
6050         }
6051       }
6052
6053     } else {
6054       // right != literal
6055       symbol *tlbl = newiTempLabel(NULL);
6056       if (AOP_TYPE(right) == AOP_CRY){
6057         // c = bit ^ bit;
6058         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6059       }
6060       else{
6061         int sizer = AOP_SIZE(right);
6062         // c = bit ^ val
6063         // if val>>1 != 0, result = 1
6064         pic16_emitcode("setb","c");
6065         while(sizer){
6066           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6067           if(sizer == 1)
6068             // test the msb of the lsb
6069             pic16_emitcode("anl","a,#0xfe");
6070           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6071           sizer--;
6072         }
6073         // val = (0,1)
6074         pic16_emitcode("rrc","a");
6075       }
6076       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6077       pic16_emitcode("cpl","c");
6078       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6079     }
6080     // bit = c
6081     // val = c
6082     if(size)
6083       pic16_outBitC(result);
6084     // if(bit | ...)
6085     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6086       genIfxJump(ifx, "c");           
6087     goto release ;
6088   }
6089
6090   if(pic16_sameRegs(AOP(result),AOP(left))){
6091     /* if left is same as result */
6092     for(;size--; offset++) {
6093       if(AOP_TYPE(right) == AOP_LIT){
6094         int t  = (lit >> (offset*8)) & 0x0FFL;
6095         if(t == 0x00L)
6096           continue;
6097         else
6098           if (IS_AOP_PREG(left)) {
6099             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6100             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6101             pic16_aopPut(AOP(result),"a",offset);
6102           } else {
6103             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6104             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6105             pic16_emitcode("xrl","%s,%s",
6106                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6107                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6108           }
6109       } else {
6110         if (AOP_TYPE(left) == AOP_ACC)
6111           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6112         else {
6113           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6114           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6115 /*
6116           if (IS_AOP_PREG(left)) {
6117             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6118             pic16_aopPut(AOP(result),"a",offset);
6119           } else
6120             pic16_emitcode("xrl","%s,a",
6121                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6122 */
6123         }
6124       }
6125     }
6126   } else {
6127     // left & result in different registers
6128     if(AOP_TYPE(result) == AOP_CRY){
6129       // result = bit
6130       // if(size), result in bit
6131       // if(!size && ifx), conditional oper: if(left ^ right)
6132       symbol *tlbl = newiTempLabel(NULL);
6133       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6134       if(size)
6135         pic16_emitcode("setb","c");
6136       while(sizer--){
6137         if((AOP_TYPE(right) == AOP_LIT) &&
6138            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6139           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6140         } else {
6141           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6142           pic16_emitcode("xrl","a,%s",
6143                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6144         }
6145         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6146         offset++;
6147       }
6148       if(size){
6149         CLRC;
6150         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6151         pic16_outBitC(result);
6152       } else if(ifx)
6153         jmpTrueOrFalse(ifx, tlbl);
6154     } else for(;(size--);offset++){
6155       // normal case
6156       // result = left & right
6157       if(AOP_TYPE(right) == AOP_LIT){
6158         int t = (lit >> (offset*8)) & 0x0FFL;
6159         switch(t) { 
6160         case 0x00:
6161           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6162           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6163           pic16_emitcode("movf","%s,w",
6164                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6165           pic16_emitcode("movwf","%s",
6166                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6167           break;
6168         case 0xff:
6169           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6170           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6171           pic16_emitcode("comf","%s,w",
6172                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6173           pic16_emitcode("movwf","%s",
6174                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6175           break;
6176         default:
6177           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6178           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6179           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6180           pic16_emitcode("movlw","0x%x",t);
6181           pic16_emitcode("xorwf","%s,w",
6182                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6183           pic16_emitcode("movwf","%s",
6184                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6185
6186         }
6187         continue;
6188       }
6189
6190       // faster than result <- left, anl result,right
6191       // and better if result is SFR
6192       if (AOP_TYPE(left) == AOP_ACC) {
6193         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6194         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6195       } else {
6196         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6197         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6198         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6199         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6200       }
6201       if ( AOP_TYPE(result) != AOP_ACC){
6202         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6203         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6204       }
6205     }
6206   }
6207
6208   release :
6209     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6211   pic16_freeAsmop(result,NULL,ic,TRUE);     
6212 }
6213
6214 /*-----------------------------------------------------------------*/
6215 /* genInline - write the inline code out                           */
6216 /*-----------------------------------------------------------------*/
6217 static void genInline (iCode *ic)
6218 {
6219     char *buffer, *bp, *bp1;
6220     
6221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6222
6223     _G.inLine += (!options.asmpeep);
6224
6225     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6226     strcpy(buffer,IC_INLINE(ic));
6227
6228     /* emit each line as a code */
6229     while (*bp) {
6230         if (*bp == '\n') {
6231             *bp++ = '\0';
6232
6233             if(*bp1)
6234               pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6235             bp1 = bp;
6236         } else {
6237             if (*bp == ':') {
6238                 bp++;
6239                 *bp = '\0';
6240                 bp++;
6241                 pic16_emitcode(bp1,"");
6242                 bp1 = bp;
6243             } else
6244                 bp++;
6245         }
6246     }
6247     if ((bp1 != bp) && *bp1)
6248       pic16_addpCode2pBlock(pb,pic16_AssembleLine(bp1));
6249
6250     Safe_free(buffer);
6251
6252     _G.inLine -= (!options.asmpeep);
6253 }
6254
6255 /*-----------------------------------------------------------------*/
6256 /* genRRC - rotate right with carry                                */
6257 /*-----------------------------------------------------------------*/
6258 static void genRRC (iCode *ic)
6259 {
6260   operand *left , *result ;
6261   int size, offset = 0, same;
6262
6263   /* rotate right with carry */
6264   left = IC_LEFT(ic);
6265   result=IC_RESULT(ic);
6266   pic16_aopOp (left,ic,FALSE);
6267   pic16_aopOp (result,ic,FALSE);
6268
6269   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6270
6271   same = pic16_sameRegs(AOP(result),AOP(left));
6272
6273   size = AOP_SIZE(result);    
6274
6275   /* get the lsb and put it into the carry */
6276   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6277
6278   offset = 0 ;
6279
6280   while(size--) {
6281
6282     if(same) {
6283       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6284     } else {
6285       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6286       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6287     }
6288
6289     offset++;
6290   }
6291
6292   pic16_freeAsmop(left,NULL,ic,TRUE);
6293   pic16_freeAsmop(result,NULL,ic,TRUE);
6294 }
6295
6296 /*-----------------------------------------------------------------*/
6297 /* genRLC - generate code for rotate left with carry               */
6298 /*-----------------------------------------------------------------*/
6299 static void genRLC (iCode *ic)
6300 {    
6301   operand *left , *result ;
6302   int size, offset = 0;
6303   int same;
6304
6305   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6306   /* rotate right with carry */
6307   left = IC_LEFT(ic);
6308   result=IC_RESULT(ic);
6309   pic16_aopOp (left,ic,FALSE);
6310   pic16_aopOp (result,ic,FALSE);
6311
6312   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6313
6314   same = pic16_sameRegs(AOP(result),AOP(left));
6315
6316   /* move it to the result */
6317   size = AOP_SIZE(result);    
6318
6319   /* get the msb and put it into the carry */
6320   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6321
6322   offset = 0 ;
6323
6324   while(size--) {
6325
6326     if(same) {
6327       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6328     } else {
6329       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6330       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6331     }
6332
6333     offset++;
6334   }
6335
6336
6337   pic16_freeAsmop(left,NULL,ic,TRUE);
6338   pic16_freeAsmop(result,NULL,ic,TRUE);
6339 }
6340
6341 /*-----------------------------------------------------------------*/
6342 /* genGetHbit - generates code get highest order bit               */
6343 /*-----------------------------------------------------------------*/
6344 static void genGetHbit (iCode *ic)
6345 {
6346     operand *left, *result;
6347     left = IC_LEFT(ic);
6348     result=IC_RESULT(ic);
6349     pic16_aopOp (left,ic,FALSE);
6350     pic16_aopOp (result,ic,FALSE);
6351
6352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6353     /* get the highest order byte into a */
6354     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6355     if(AOP_TYPE(result) == AOP_CRY){
6356         pic16_emitcode("rlc","a");
6357         pic16_outBitC(result);
6358     }
6359     else{
6360         pic16_emitcode("rl","a");
6361         pic16_emitcode("anl","a,#0x01");
6362         pic16_outAcc(result);
6363     }
6364
6365
6366     pic16_freeAsmop(left,NULL,ic,TRUE);
6367     pic16_freeAsmop(result,NULL,ic,TRUE);
6368 }
6369
6370 /*-----------------------------------------------------------------*/
6371 /* AccRol - rotate left accumulator by known count                 */
6372 /*-----------------------------------------------------------------*/
6373 static void AccRol (int shCount)
6374 {
6375     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6376     shCount &= 0x0007;              // shCount : 0..7
6377     switch(shCount){
6378         case 0 :
6379             break;
6380         case 1 :
6381             pic16_emitcode("rl","a");
6382             break;
6383         case 2 :
6384             pic16_emitcode("rl","a");
6385             pic16_emitcode("rl","a");
6386             break;
6387         case 3 :
6388             pic16_emitcode("swap","a");
6389             pic16_emitcode("rr","a");
6390             break;
6391         case 4 :
6392             pic16_emitcode("swap","a");
6393             break;
6394         case 5 :
6395             pic16_emitcode("swap","a");
6396             pic16_emitcode("rl","a");
6397             break;
6398         case 6 :
6399             pic16_emitcode("rr","a");
6400             pic16_emitcode("rr","a");
6401             break;
6402         case 7 :
6403             pic16_emitcode("rr","a");
6404             break;
6405     }
6406 }
6407
6408 /*-----------------------------------------------------------------*/
6409 /* AccLsh - left shift accumulator by known count                  */
6410 /*-----------------------------------------------------------------*/
6411 static void AccLsh (int shCount)
6412 {
6413     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6414     if(shCount != 0){
6415         if(shCount == 1)
6416             pic16_emitcode("add","a,acc");
6417         else 
6418             if(shCount == 2) {
6419             pic16_emitcode("add","a,acc");
6420             pic16_emitcode("add","a,acc");
6421         } else {
6422             /* rotate left accumulator */
6423             AccRol(shCount);
6424             /* and kill the lower order bits */
6425             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6426         }
6427     }
6428 }
6429
6430 /*-----------------------------------------------------------------*/
6431 /* AccRsh - right shift accumulator by known count                 */
6432 /*-----------------------------------------------------------------*/
6433 static void AccRsh (int shCount)
6434 {
6435     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6436     if(shCount != 0){
6437         if(shCount == 1){
6438             CLRC;
6439             pic16_emitcode("rrc","a");
6440         } else {
6441             /* rotate right accumulator */
6442             AccRol(8 - shCount);
6443             /* and kill the higher order bits */
6444             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6445         }
6446     }
6447 }
6448
6449 #if 0
6450 /*-----------------------------------------------------------------*/
6451 /* AccSRsh - signed right shift accumulator by known count                 */
6452 /*-----------------------------------------------------------------*/
6453 static void AccSRsh (int shCount)
6454 {
6455     symbol *tlbl ;
6456     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6457     if(shCount != 0){
6458         if(shCount == 1){
6459             pic16_emitcode("mov","c,acc.7");
6460             pic16_emitcode("rrc","a");
6461         } else if(shCount == 2){
6462             pic16_emitcode("mov","c,acc.7");
6463             pic16_emitcode("rrc","a");
6464             pic16_emitcode("mov","c,acc.7");
6465             pic16_emitcode("rrc","a");
6466         } else {
6467             tlbl = newiTempLabel(NULL);
6468             /* rotate right accumulator */
6469             AccRol(8 - shCount);
6470             /* and kill the higher order bits */
6471             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6472             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6473             pic16_emitcode("orl","a,#0x%02x",
6474                      (unsigned char)~SRMask[shCount]);
6475             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6476         }
6477     }
6478 }
6479 #endif
6480 /*-----------------------------------------------------------------*/
6481 /* shiftR1Left2Result - shift right one byte from left to result   */
6482 /*-----------------------------------------------------------------*/
6483 static void shiftR1Left2ResultSigned (operand *left, int offl,
6484                                 operand *result, int offr,
6485                                 int shCount)
6486 {
6487   int same;
6488
6489   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6490
6491   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6492
6493   switch(shCount) {
6494   case 1:
6495     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6496     if(same) 
6497       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6498     else {
6499       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6500       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6501     }
6502
6503     break;
6504   case 2:
6505
6506     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6507     if(same) 
6508       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6509     else {
6510       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6511       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6512     }
6513     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6514     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6515
6516     break;
6517
6518   case 3:
6519     if(same)
6520       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6521     else {
6522       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6523       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6524     }
6525
6526     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6527     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6528     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6529
6530     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6531     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6532
6533     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6534     break;
6535
6536   case 4:
6537     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6538     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6539     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6540     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6541     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6542     break;
6543   case 5:
6544     if(same) {
6545       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6546     } else {
6547       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6548       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6549     }
6550     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6551     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6552     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6553     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6554     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6555     break;
6556
6557   case 6:
6558     if(same) {
6559       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6560       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6561       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6562       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6563       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6564       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6565     } else {
6566       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6567       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6568       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6569       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6570       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6571     }
6572     break;
6573
6574   case 7:
6575     if(same) {
6576       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6577       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6578       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6579       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6580     } else {
6581       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6582       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6583       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6584     }
6585
6586   default:
6587     break;
6588   }
6589 }
6590
6591 /*-----------------------------------------------------------------*/
6592 /* shiftR1Left2Result - shift right one byte from left to result   */
6593 /*-----------------------------------------------------------------*/
6594 static void shiftR1Left2Result (operand *left, int offl,
6595                                 operand *result, int offr,
6596                                 int shCount, int sign)
6597 {
6598   int same;
6599
6600   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6601
6602   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6603
6604   /* Copy the msb into the carry if signed. */
6605   if(sign) {
6606     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6607     return;
6608   }
6609
6610
6611
6612   switch(shCount) {
6613   case 1:
6614     emitCLRC;
6615     if(same) 
6616       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6617     else {
6618       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6619       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6620     }
6621     break;
6622   case 2:
6623     emitCLRC;
6624     if(same) {
6625       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6626     } else {
6627       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6628       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6629     }
6630     emitCLRC;
6631     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6632
6633     break;
6634   case 3:
6635     if(same)
6636       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6637     else {
6638       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6639       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6640     }
6641
6642     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6643     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6644     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6645     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6646     break;
6647       
6648   case 4:
6649     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6650     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6651     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6652     break;
6653
6654   case 5:
6655     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6656     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6657     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6658     emitCLRC;
6659     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6660
6661     break;
6662   case 6:
6663
6664     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6665     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6666     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6667     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6668     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6669     break;
6670
6671   case 7:
6672
6673     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6674     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6675     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6676
6677     break;
6678
6679   default:
6680     break;
6681   }
6682 }
6683
6684 /*-----------------------------------------------------------------*/
6685 /* shiftL1Left2Result - shift left one byte from left to result    */
6686 /*-----------------------------------------------------------------*/
6687 static void shiftL1Left2Result (operand *left, int offl,
6688                                 operand *result, int offr, int shCount)
6689 {
6690   int same;
6691
6692   //    char *l;
6693   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6694
6695   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6696   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6697     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6698     //    MOVA(l);
6699     /* shift left accumulator */
6700     //AccLsh(shCount); // don't comment out just yet...
6701   //    pic16_aopPut(AOP(result),"a",offr);
6702
6703   switch(shCount) {
6704   case 1:
6705     /* Shift left 1 bit position */
6706     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6707     if(same) {
6708       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6709     } else {
6710       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6711       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6712     }
6713     break;
6714   case 2:
6715     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6716     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6717     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6718     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6719     break;
6720   case 3:
6721     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6722     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6723     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6724     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6725     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6726     break;
6727   case 4:
6728     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6729     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6730     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6731     break;
6732   case 5:
6733     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6734     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6735     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6736     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6737     break;
6738   case 6:
6739     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6740     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6741     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6742     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6743     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6744     break;
6745   case 7:
6746     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6747     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6748     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6749     break;
6750
6751   default:
6752     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6753   }
6754
6755 }
6756
6757 /*-----------------------------------------------------------------*/
6758 /* movLeft2Result - move byte from left to result                  */
6759 /*-----------------------------------------------------------------*/
6760 static void movLeft2Result (operand *left, int offl,
6761                             operand *result, int offr)
6762 {
6763   char *l;
6764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6765   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6766     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6767
6768     if (*l == '@' && (IS_AOP_PREG(result))) {
6769       pic16_emitcode("mov","a,%s",l);
6770       pic16_aopPut(AOP(result),"a",offr);
6771     } else {
6772       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6773       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6774     }
6775   }
6776 }
6777
6778 /*-----------------------------------------------------------------*/
6779 /* shiftL2Left2Result - shift left two bytes from left to result   */
6780 /*-----------------------------------------------------------------*/
6781 static void shiftL2Left2Result (operand *left, int offl,
6782                                 operand *result, int offr, int shCount)
6783 {
6784
6785
6786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6787
6788   if(pic16_sameRegs(AOP(result), AOP(left))) {
6789     switch(shCount) {
6790     case 0:
6791       break;
6792     case 1:
6793     case 2:
6794     case 3:
6795
6796       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6797       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6798       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6799
6800       while(--shCount) {
6801         emitCLRC;
6802         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6803         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6804       }
6805
6806       break;
6807     case 4:
6808     case 5:
6809       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6810       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6811       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6812       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6813       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6814       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6815       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6816       if(shCount >=5) {
6817         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6818         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6819       }
6820       break;
6821     case 6:
6822       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6823       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6824       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6825       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6826       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6827       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6828       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6829       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6830       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6831       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6832       break;
6833     case 7:
6834       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6835       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6836       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6837       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6838       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6839     }
6840
6841   } else {
6842     switch(shCount) {
6843     case 0:
6844       break;
6845     case 1:
6846     case 2:
6847     case 3:
6848       /* note, use a mov/add for the shift since the mov has a
6849          chance of getting optimized out */
6850       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6851       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6852       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6853       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6854       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6855
6856       while(--shCount) {
6857         emitCLRC;
6858         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6859         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6860       }
6861       break;
6862
6863     case 4:
6864     case 5:
6865       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6866       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6867       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6868       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6869       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6870       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6871       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6872       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6873
6874
6875       if(shCount == 5) {
6876         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6877         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6878       }
6879       break;
6880     case 6:
6881       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6882       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6883       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6884       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6885
6886       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6887       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6888       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6889       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6890       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6891       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6892       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6893       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6894       break;
6895     case 7:
6896       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6897       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6898       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6899       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6900       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6901     }
6902   }
6903
6904 }
6905 /*-----------------------------------------------------------------*/
6906 /* shiftR2Left2Result - shift right two bytes from left to result  */
6907 /*-----------------------------------------------------------------*/
6908 static void shiftR2Left2Result (operand *left, int offl,
6909                                 operand *result, int offr,
6910                                 int shCount, int sign)
6911 {
6912   int same=0;
6913
6914   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6915   same = pic16_sameRegs(AOP(result), AOP(left));
6916
6917   if(same && ((offl + MSB16) == offr)){
6918     same=1;
6919     /* don't crash result[offr] */
6920     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
6921     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6922   }
6923 /* else {
6924     movLeft2Result(left,offl, result, offr);
6925     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6926   }
6927 */
6928   /* a:x >> shCount (x = lsb(result))*/
6929 /*
6930   if(sign)
6931     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6932   else {
6933     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6934 */
6935   switch(shCount) {
6936   case 0:
6937     break;
6938   case 1:
6939   case 2:
6940   case 3:
6941     if(sign)
6942       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6943     else
6944       emitCLRC;
6945
6946     if(same) {
6947       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6948       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6949     } else {
6950       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6951       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6952       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6953       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6954     }
6955
6956     while(--shCount) {
6957       if(sign)
6958         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
6959       else
6960         emitCLRC;
6961       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
6962       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
6963     }
6964     break;
6965   case 4:
6966   case 5:
6967     if(same) {
6968
6969       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
6970       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
6971       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6972
6973       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6974       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
6975       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6976       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6977     } else {
6978       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6979       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6980       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6981
6982       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6983       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6984       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6985       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
6986       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6987     }
6988
6989     if(shCount >=5) {
6990       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
6991       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6992     }
6993
6994     if(sign) {
6995       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
6996       pic16_emitpcode(POC_BTFSC, 
6997                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6998       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6999     }
7000
7001     break;
7002
7003   case 6:
7004     if(same) {
7005
7006       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7007       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7008
7009       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7010       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7011       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7012       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7013       if(sign) {
7014         pic16_emitpcode(POC_BTFSC, 
7015                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7016         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7017       }
7018       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7019       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7020       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7021       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7022     } else {
7023       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7024       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7025       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7026       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7027       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7028       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7029       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7030       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7031       if(sign) {
7032         pic16_emitpcode(POC_BTFSC, 
7033                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7034         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7035       }
7036       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7037       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7038
7039         
7040     }
7041
7042     break;
7043   case 7:
7044     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7045     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7046     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7047     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7048     if(sign) {
7049       emitSKPNC;
7050       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7051     } else 
7052       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7053   }
7054 }
7055
7056
7057 /*-----------------------------------------------------------------*/
7058 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7059 /*-----------------------------------------------------------------*/
7060 static void shiftLLeftOrResult (operand *left, int offl,
7061                                 operand *result, int offr, int shCount)
7062 {
7063     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7064     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7065     /* shift left accumulator */
7066     AccLsh(shCount);
7067     /* or with result */
7068     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
7069     /* back to result */
7070     pic16_aopPut(AOP(result),"a",offr);
7071 }
7072
7073 /*-----------------------------------------------------------------*/
7074 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7075 /*-----------------------------------------------------------------*/
7076 static void shiftRLeftOrResult (operand *left, int offl,
7077                                 operand *result, int offr, int shCount)
7078 {
7079     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7080     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7081     /* shift right accumulator */
7082     AccRsh(shCount);
7083     /* or with result */
7084     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
7085     /* back to result */
7086     pic16_aopPut(AOP(result),"a",offr);
7087 }
7088
7089 /*-----------------------------------------------------------------*/
7090 /* genlshOne - left shift a one byte quantity by known count       */
7091 /*-----------------------------------------------------------------*/
7092 static void genlshOne (operand *result, operand *left, int shCount)
7093 {       
7094     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7095     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7096 }
7097
7098 /*-----------------------------------------------------------------*/
7099 /* genlshTwo - left shift two bytes by known amount != 0           */
7100 /*-----------------------------------------------------------------*/
7101 static void genlshTwo (operand *result,operand *left, int shCount)
7102 {
7103     int size;
7104     
7105     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7106     size = pic16_getDataSize(result);
7107
7108     /* if shCount >= 8 */
7109     if (shCount >= 8) {
7110         shCount -= 8 ;
7111
7112         if (size > 1){
7113             if (shCount)
7114                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7115             else 
7116                 movLeft2Result(left, LSB, result, MSB16);
7117         }
7118         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7119     }
7120
7121     /*  1 <= shCount <= 7 */
7122     else {  
7123         if(size == 1)
7124             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7125         else 
7126             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7127     }
7128 }
7129
7130 /*-----------------------------------------------------------------*/
7131 /* shiftLLong - shift left one long from left to result            */
7132 /* offl = LSB or MSB16                                             */
7133 /*-----------------------------------------------------------------*/
7134 static void shiftLLong (operand *left, operand *result, int offr )
7135 {
7136     char *l;
7137     int size = AOP_SIZE(result);
7138
7139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7140     if(size >= LSB+offr){
7141         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7142         MOVA(l);
7143         pic16_emitcode("add","a,acc");
7144         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7145             size >= MSB16+offr && offr != LSB )
7146             pic16_emitcode("xch","a,%s",
7147                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7148         else        
7149             pic16_aopPut(AOP(result),"a",LSB+offr);
7150     }
7151
7152     if(size >= MSB16+offr){
7153         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7154             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7155             MOVA(l);
7156         }
7157         pic16_emitcode("rlc","a");
7158         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7159             size >= MSB24+offr && offr != LSB)
7160             pic16_emitcode("xch","a,%s",
7161                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7162         else        
7163             pic16_aopPut(AOP(result),"a",MSB16+offr);
7164     }
7165
7166     if(size >= MSB24+offr){
7167         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7168             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7169             MOVA(l);
7170         }
7171         pic16_emitcode("rlc","a");
7172         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7173             size >= MSB32+offr && offr != LSB )
7174             pic16_emitcode("xch","a,%s",
7175                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7176         else        
7177             pic16_aopPut(AOP(result),"a",MSB24+offr);
7178     }
7179
7180     if(size > MSB32+offr){
7181         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7182             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7183             MOVA(l);    
7184         }
7185         pic16_emitcode("rlc","a");
7186         pic16_aopPut(AOP(result),"a",MSB32+offr);
7187     }
7188     if(offr != LSB)
7189         pic16_aopPut(AOP(result),zero,LSB);       
7190 }
7191
7192 /*-----------------------------------------------------------------*/
7193 /* genlshFour - shift four byte by a known amount != 0             */
7194 /*-----------------------------------------------------------------*/
7195 static void genlshFour (operand *result, operand *left, int shCount)
7196 {
7197     int size;
7198
7199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7200     size = AOP_SIZE(result);
7201
7202     /* if shifting more that 3 bytes */
7203     if (shCount >= 24 ) {
7204         shCount -= 24;
7205         if (shCount)
7206             /* lowest order of left goes to the highest
7207             order of the destination */
7208             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7209         else
7210             movLeft2Result(left, LSB, result, MSB32);
7211         pic16_aopPut(AOP(result),zero,LSB);
7212         pic16_aopPut(AOP(result),zero,MSB16);
7213         pic16_aopPut(AOP(result),zero,MSB32);
7214         return;
7215     }
7216
7217     /* more than two bytes */
7218     else if ( shCount >= 16 ) {
7219         /* lower order two bytes goes to higher order two bytes */
7220         shCount -= 16;
7221         /* if some more remaining */
7222         if (shCount)
7223             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7224         else {
7225             movLeft2Result(left, MSB16, result, MSB32);
7226             movLeft2Result(left, LSB, result, MSB24);
7227         }
7228         pic16_aopPut(AOP(result),zero,MSB16);
7229         pic16_aopPut(AOP(result),zero,LSB);
7230         return;
7231     }    
7232
7233     /* if more than 1 byte */
7234     else if ( shCount >= 8 ) {
7235         /* lower order three bytes goes to higher order  three bytes */
7236         shCount -= 8;
7237         if(size == 2){
7238             if(shCount)
7239                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7240             else
7241                 movLeft2Result(left, LSB, result, MSB16);
7242         }
7243         else{   /* size = 4 */
7244             if(shCount == 0){
7245                 movLeft2Result(left, MSB24, result, MSB32);
7246                 movLeft2Result(left, MSB16, result, MSB24);
7247                 movLeft2Result(left, LSB, result, MSB16);
7248                 pic16_aopPut(AOP(result),zero,LSB);
7249             }
7250             else if(shCount == 1)
7251                 shiftLLong(left, result, MSB16);
7252             else{
7253                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7254                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7255                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7256                 pic16_aopPut(AOP(result),zero,LSB);
7257             }
7258         }
7259     }
7260
7261     /* 1 <= shCount <= 7 */
7262     else if(shCount <= 2){
7263         shiftLLong(left, result, LSB);
7264         if(shCount == 2)
7265             shiftLLong(result, result, LSB);
7266     }
7267     /* 3 <= shCount <= 7, optimize */
7268     else{
7269         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7270         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7271         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7272     }
7273 }
7274
7275 /*-----------------------------------------------------------------*/
7276 /* genLeftShiftLiteral - left shifting by known count              */
7277 /*-----------------------------------------------------------------*/
7278 static void genLeftShiftLiteral (operand *left,
7279                                  operand *right,
7280                                  operand *result,
7281                                  iCode *ic)
7282 {    
7283     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7284     int size;
7285
7286     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7287     pic16_freeAsmop(right,NULL,ic,TRUE);
7288
7289     pic16_aopOp(left,ic,FALSE);
7290     pic16_aopOp(result,ic,FALSE);
7291
7292     size = getSize(operandType(result));
7293
7294 #if VIEW_SIZE
7295     pic16_emitcode("; shift left ","result %d, left %d",size,
7296              AOP_SIZE(left));
7297 #endif
7298
7299     /* I suppose that the left size >= result size */
7300     if(shCount == 0){
7301         while(size--){
7302             movLeft2Result(left, size, result, size);
7303         }
7304     }
7305
7306     else if(shCount >= (size * 8))
7307         while(size--)
7308             pic16_aopPut(AOP(result),zero,size);
7309     else{
7310         switch (size) {
7311             case 1:
7312                 genlshOne (result,left,shCount);
7313                 break;
7314
7315             case 2:
7316             case 3:
7317                 genlshTwo (result,left,shCount);
7318                 break;
7319
7320             case 4:
7321                 genlshFour (result,left,shCount);
7322                 break;
7323         }
7324     }
7325     pic16_freeAsmop(left,NULL,ic,TRUE);
7326     pic16_freeAsmop(result,NULL,ic,TRUE);
7327 }
7328
7329 /*-----------------------------------------------------------------*
7330  * genMultiAsm - repeat assembly instruction for size of register.
7331  * if endian == 1, then the high byte (i.e base address + size of 
7332  * register) is used first else the low byte is used first;
7333  *-----------------------------------------------------------------*/
7334 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7335 {
7336
7337   int offset = 0;
7338
7339   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7340
7341   if(!reg)
7342     return;
7343
7344   if(!endian) {
7345     endian = 1;
7346   } else {
7347     endian = -1;
7348     offset = size-1;
7349   }
7350
7351   while(size--) {
7352     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7353     offset += endian;
7354   }
7355
7356 }
7357 /*-----------------------------------------------------------------*/
7358 /* genLeftShift - generates code for left shifting                 */
7359 /*-----------------------------------------------------------------*/
7360 static void genLeftShift (iCode *ic)
7361 {
7362   operand *left,*right, *result;
7363   int size, offset;
7364   char *l;
7365   symbol *tlbl , *tlbl1;
7366   pCodeOp *pctemp;
7367
7368   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7369
7370   right = IC_RIGHT(ic);
7371   left  = IC_LEFT(ic);
7372   result = IC_RESULT(ic);
7373
7374   pic16_aopOp(right,ic,FALSE);
7375
7376   /* if the shift count is known then do it 
7377      as efficiently as possible */
7378   if (AOP_TYPE(right) == AOP_LIT) {
7379     genLeftShiftLiteral (left,right,result,ic);
7380     return ;
7381   }
7382
7383   /* shift count is unknown then we have to form 
7384      a loop get the loop count in B : Note: we take
7385      only the lower order byte since shifting
7386      more that 32 bits make no sense anyway, ( the
7387      largest size of an object can be only 32 bits ) */  
7388
7389     
7390   pic16_aopOp(left,ic,FALSE);
7391   pic16_aopOp(result,ic,FALSE);
7392
7393   /* now move the left to the result if they are not the
7394      same */
7395   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7396       AOP_SIZE(result) > 1) {
7397
7398     size = AOP_SIZE(result);
7399     offset=0;
7400     while (size--) {
7401       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7402       if (*l == '@' && (IS_AOP_PREG(result))) {
7403
7404         pic16_emitcode("mov","a,%s",l);
7405         pic16_aopPut(AOP(result),"a",offset);
7406       } else {
7407         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7408         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7409         //pic16_aopPut(AOP(result),l,offset);
7410       }
7411       offset++;
7412     }
7413   }
7414
7415   size = AOP_SIZE(result);
7416
7417   /* if it is only one byte then */
7418   if (size == 1) {
7419     if(optimized_for_speed) {
7420       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7421       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7422       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7423       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7424       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7425       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7426       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7427       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7428       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7429       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7430       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7431       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7432     } else {
7433
7434       tlbl = newiTempLabel(NULL);
7435       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7436         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7437         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7438       }
7439
7440       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7441       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7442       pic16_emitpLabel(tlbl->key);
7443       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7444       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7445       emitSKPC;
7446       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7447     }
7448     goto release ;
7449   }
7450     
7451   if (pic16_sameRegs(AOP(left),AOP(result))) {
7452
7453     tlbl = newiTempLabel(NULL);
7454     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7455     genMultiAsm(POC_RRCF, result, size,1);
7456     pic16_emitpLabel(tlbl->key);
7457     genMultiAsm(POC_RLCF, result, size,0);
7458     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7459     emitSKPC;
7460     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7461     goto release;
7462   }
7463
7464   //tlbl = newiTempLabel(NULL);
7465   //offset = 0 ;   
7466   //tlbl1 = newiTempLabel(NULL);
7467
7468   //reAdjustPreg(AOP(result));    
7469     
7470   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7471   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7472   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7473   //MOVA(l);
7474   //pic16_emitcode("add","a,acc");         
7475   //pic16_aopPut(AOP(result),"a",offset++);
7476   //while (--size) {
7477   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7478   //  MOVA(l);
7479   //  pic16_emitcode("rlc","a");         
7480   //  pic16_aopPut(AOP(result),"a",offset++);
7481   //}
7482   //reAdjustPreg(AOP(result));
7483
7484   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7485   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7486
7487
7488   tlbl = newiTempLabel(NULL);
7489   tlbl1= newiTempLabel(NULL);
7490
7491   size = AOP_SIZE(result);
7492   offset = 1;
7493
7494   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7495
7496   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7497
7498   /* offset should be 0, 1 or 3 */
7499   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7500   emitSKPNZ;
7501   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7502
7503   pic16_emitpcode(POC_MOVWF, pctemp);
7504
7505
7506   pic16_emitpLabel(tlbl->key);
7507
7508   emitCLRC;
7509   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7510   while(--size)
7511     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7512
7513   pic16_emitpcode(POC_DECFSZ,  pctemp);
7514   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7515   pic16_emitpLabel(tlbl1->key);
7516
7517   pic16_popReleaseTempReg(pctemp);
7518
7519
7520  release:
7521   pic16_freeAsmop (right,NULL,ic,TRUE);
7522   pic16_freeAsmop(left,NULL,ic,TRUE);
7523   pic16_freeAsmop(result,NULL,ic,TRUE);
7524 }
7525
7526 /*-----------------------------------------------------------------*/
7527 /* genrshOne - right shift a one byte quantity by known count      */
7528 /*-----------------------------------------------------------------*/
7529 static void genrshOne (operand *result, operand *left,
7530                        int shCount, int sign)
7531 {
7532     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7533     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7534 }
7535
7536 /*-----------------------------------------------------------------*/
7537 /* genrshTwo - right shift two bytes by known amount != 0          */
7538 /*-----------------------------------------------------------------*/
7539 static void genrshTwo (operand *result,operand *left,
7540                        int shCount, int sign)
7541 {
7542   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7543   /* if shCount >= 8 */
7544   if (shCount >= 8) {
7545     shCount -= 8 ;
7546     if (shCount)
7547       shiftR1Left2Result(left, MSB16, result, LSB,
7548                          shCount, sign);
7549     else
7550       movLeft2Result(left, MSB16, result, LSB);
7551
7552     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7553
7554     if(sign) {
7555       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7556       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7557     }
7558   }
7559
7560   /*  1 <= shCount <= 7 */
7561   else
7562     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7563 }
7564
7565 /*-----------------------------------------------------------------*/
7566 /* shiftRLong - shift right one long from left to result           */
7567 /* offl = LSB or MSB16                                             */
7568 /*-----------------------------------------------------------------*/
7569 static void shiftRLong (operand *left, int offl,
7570                         operand *result, int sign)
7571 {
7572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7573     if(!sign)
7574         pic16_emitcode("clr","c");
7575     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7576     if(sign)
7577         pic16_emitcode("mov","c,acc.7");
7578     pic16_emitcode("rrc","a");
7579     pic16_aopPut(AOP(result),"a",MSB32-offl);
7580     if(offl == MSB16)
7581         /* add sign of "a" */
7582         pic16_addSign(result, MSB32, sign);
7583
7584     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7585     pic16_emitcode("rrc","a");
7586     pic16_aopPut(AOP(result),"a",MSB24-offl);
7587
7588     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7589     pic16_emitcode("rrc","a");
7590     pic16_aopPut(AOP(result),"a",MSB16-offl);
7591
7592     if(offl == LSB){
7593         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7594         pic16_emitcode("rrc","a");
7595         pic16_aopPut(AOP(result),"a",LSB);
7596     }
7597 }
7598
7599 /*-----------------------------------------------------------------*/
7600 /* genrshFour - shift four byte by a known amount != 0             */
7601 /*-----------------------------------------------------------------*/
7602 static void genrshFour (operand *result, operand *left,
7603                         int shCount, int sign)
7604 {
7605   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7606   /* if shifting more that 3 bytes */
7607   if(shCount >= 24 ) {
7608     shCount -= 24;
7609     if(shCount)
7610       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7611     else
7612       movLeft2Result(left, MSB32, result, LSB);
7613
7614     pic16_addSign(result, MSB16, sign);
7615   }
7616   else if(shCount >= 16){
7617     shCount -= 16;
7618     if(shCount)
7619       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7620     else{
7621       movLeft2Result(left, MSB24, result, LSB);
7622       movLeft2Result(left, MSB32, result, MSB16);
7623     }
7624     pic16_addSign(result, MSB24, sign);
7625   }
7626   else if(shCount >= 8){
7627     shCount -= 8;
7628     if(shCount == 1)
7629       shiftRLong(left, MSB16, result, sign);
7630     else if(shCount == 0){
7631       movLeft2Result(left, MSB16, result, LSB);
7632       movLeft2Result(left, MSB24, result, MSB16);
7633       movLeft2Result(left, MSB32, result, MSB24);
7634       pic16_addSign(result, MSB32, sign);
7635     }
7636     else{
7637       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7638       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7639       /* the last shift is signed */
7640       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7641       pic16_addSign(result, MSB32, sign);
7642     }
7643   }
7644   else{   /* 1 <= shCount <= 7 */
7645     if(shCount <= 2){
7646       shiftRLong(left, LSB, result, sign);
7647       if(shCount == 2)
7648         shiftRLong(result, LSB, result, sign);
7649     }
7650     else{
7651       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7652       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7653       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7654     }
7655   }
7656 }
7657
7658 /*-----------------------------------------------------------------*/
7659 /* genRightShiftLiteral - right shifting by known count            */
7660 /*-----------------------------------------------------------------*/
7661 static void genRightShiftLiteral (operand *left,
7662                                   operand *right,
7663                                   operand *result,
7664                                   iCode *ic,
7665                                   int sign)
7666 {    
7667   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7668   int lsize,res_size;
7669
7670   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7671   pic16_freeAsmop(right,NULL,ic,TRUE);
7672
7673   pic16_aopOp(left,ic,FALSE);
7674   pic16_aopOp(result,ic,FALSE);
7675
7676 #if VIEW_SIZE
7677   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7678                  AOP_SIZE(left));
7679 #endif
7680
7681   lsize = pic16_getDataSize(left);
7682   res_size = pic16_getDataSize(result);
7683   /* test the LEFT size !!! */
7684
7685   /* I suppose that the left size >= result size */
7686   if(shCount == 0){
7687     while(res_size--)
7688       movLeft2Result(left, lsize, result, res_size);
7689   }
7690
7691   else if(shCount >= (lsize * 8)){
7692
7693     if(res_size == 1) {
7694       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7695       if(sign) {
7696         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7697         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7698       }
7699     } else {
7700
7701       if(sign) {
7702         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7703         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7704         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7705         while(res_size--)
7706           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7707
7708       } else {
7709
7710         while(res_size--)
7711           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7712       }
7713     }
7714   } else {
7715
7716     switch (res_size) {
7717     case 1:
7718       genrshOne (result,left,shCount,sign);
7719       break;
7720
7721     case 2:
7722       genrshTwo (result,left,shCount,sign);
7723       break;
7724
7725     case 4:
7726       genrshFour (result,left,shCount,sign);
7727       break;
7728     default :
7729       break;
7730     }
7731
7732   }
7733
7734   pic16_freeAsmop(left,NULL,ic,TRUE);
7735   pic16_freeAsmop(result,NULL,ic,TRUE);
7736 }
7737
7738 /*-----------------------------------------------------------------*/
7739 /* genSignedRightShift - right shift of signed number              */
7740 /*-----------------------------------------------------------------*/
7741 static void genSignedRightShift (iCode *ic)
7742 {
7743   operand *right, *left, *result;
7744   int size, offset;
7745   //  char *l;
7746   symbol *tlbl, *tlbl1 ;
7747   pCodeOp *pctemp;
7748
7749   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7750
7751   /* we do it the hard way put the shift count in b
7752      and loop thru preserving the sign */
7753   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7754
7755   right = IC_RIGHT(ic);
7756   left  = IC_LEFT(ic);
7757   result = IC_RESULT(ic);
7758
7759   pic16_aopOp(right,ic,FALSE);  
7760   pic16_aopOp(left,ic,FALSE);
7761   pic16_aopOp(result,ic,FALSE);
7762
7763
7764   if ( AOP_TYPE(right) == AOP_LIT) {
7765     genRightShiftLiteral (left,right,result,ic,1);
7766     return ;
7767   }
7768   /* shift count is unknown then we have to form 
7769      a loop get the loop count in B : Note: we take
7770      only the lower order byte since shifting
7771      more that 32 bits make no sense anyway, ( the
7772      largest size of an object can be only 32 bits ) */  
7773
7774   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7775   //pic16_emitcode("inc","b");
7776   //pic16_freeAsmop (right,NULL,ic,TRUE);
7777   //pic16_aopOp(left,ic,FALSE);
7778   //pic16_aopOp(result,ic,FALSE);
7779
7780   /* now move the left to the result if they are not the
7781      same */
7782   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7783       AOP_SIZE(result) > 1) {
7784
7785     size = AOP_SIZE(result);
7786     offset=0;
7787     while (size--) { 
7788       /*
7789         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7790         if (*l == '@' && IS_AOP_PREG(result)) {
7791
7792         pic16_emitcode("mov","a,%s",l);
7793         pic16_aopPut(AOP(result),"a",offset);
7794         } else
7795         pic16_aopPut(AOP(result),l,offset);
7796       */
7797       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7798       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7799
7800       offset++;
7801     }
7802   }
7803
7804   /* mov the highest order bit to OVR */    
7805   tlbl = newiTempLabel(NULL);
7806   tlbl1= newiTempLabel(NULL);
7807
7808   size = AOP_SIZE(result);
7809   offset = size - 1;
7810
7811   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7812
7813   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7814
7815   /* offset should be 0, 1 or 3 */
7816   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7817   emitSKPNZ;
7818   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7819
7820   pic16_emitpcode(POC_MOVWF, pctemp);
7821
7822
7823   pic16_emitpLabel(tlbl->key);
7824
7825   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7826   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7827
7828   while(--size) {
7829     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7830   }
7831
7832   pic16_emitpcode(POC_DECFSZ,  pctemp);
7833   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7834   pic16_emitpLabel(tlbl1->key);
7835
7836   pic16_popReleaseTempReg(pctemp);
7837 #if 0
7838   size = AOP_SIZE(result);
7839   offset = size - 1;
7840   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7841   pic16_emitcode("rlc","a");
7842   pic16_emitcode("mov","ov,c");
7843   /* if it is only one byte then */
7844   if (size == 1) {
7845     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7846     MOVA(l);
7847     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7848     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7849     pic16_emitcode("mov","c,ov");
7850     pic16_emitcode("rrc","a");
7851     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7852     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7853     pic16_aopPut(AOP(result),"a",0);
7854     goto release ;
7855   }
7856
7857   reAdjustPreg(AOP(result));
7858   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7859   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7860   pic16_emitcode("mov","c,ov");
7861   while (size--) {
7862     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7863     MOVA(l);
7864     pic16_emitcode("rrc","a");         
7865     pic16_aopPut(AOP(result),"a",offset--);
7866   }
7867   reAdjustPreg(AOP(result));
7868   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7869   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7870
7871  release:
7872 #endif
7873
7874   pic16_freeAsmop(left,NULL,ic,TRUE);
7875   pic16_freeAsmop(result,NULL,ic,TRUE);
7876   pic16_freeAsmop(right,NULL,ic,TRUE);
7877 }
7878
7879 /*-----------------------------------------------------------------*/
7880 /* genRightShift - generate code for right shifting                */
7881 /*-----------------------------------------------------------------*/
7882 static void genRightShift (iCode *ic)
7883 {
7884     operand *right, *left, *result;
7885     sym_link *retype ;
7886     int size, offset;
7887     char *l;
7888     symbol *tlbl, *tlbl1 ;
7889
7890     /* if signed then we do it the hard way preserve the
7891     sign bit moving it inwards */
7892     retype = getSpec(operandType(IC_RESULT(ic)));
7893     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7894
7895     if (!SPEC_USIGN(retype)) {
7896         genSignedRightShift (ic);
7897         return ;
7898     }
7899
7900     /* signed & unsigned types are treated the same : i.e. the
7901     signed is NOT propagated inwards : quoting from the
7902     ANSI - standard : "for E1 >> E2, is equivalent to division
7903     by 2**E2 if unsigned or if it has a non-negative value,
7904     otherwise the result is implementation defined ", MY definition
7905     is that the sign does not get propagated */
7906
7907     right = IC_RIGHT(ic);
7908     left  = IC_LEFT(ic);
7909     result = IC_RESULT(ic);
7910
7911     pic16_aopOp(right,ic,FALSE);
7912
7913     /* if the shift count is known then do it 
7914     as efficiently as possible */
7915     if (AOP_TYPE(right) == AOP_LIT) {
7916         genRightShiftLiteral (left,right,result,ic, 0);
7917         return ;
7918     }
7919
7920     /* shift count is unknown then we have to form 
7921     a loop get the loop count in B : Note: we take
7922     only the lower order byte since shifting
7923     more that 32 bits make no sense anyway, ( the
7924     largest size of an object can be only 32 bits ) */  
7925
7926     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7927     pic16_emitcode("inc","b");
7928     pic16_aopOp(left,ic,FALSE);
7929     pic16_aopOp(result,ic,FALSE);
7930
7931     /* now move the left to the result if they are not the
7932     same */
7933     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7934         AOP_SIZE(result) > 1) {
7935
7936         size = AOP_SIZE(result);
7937         offset=0;
7938         while (size--) {
7939             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7940             if (*l == '@' && IS_AOP_PREG(result)) {
7941
7942                 pic16_emitcode("mov","a,%s",l);
7943                 pic16_aopPut(AOP(result),"a",offset);
7944             } else
7945                 pic16_aopPut(AOP(result),l,offset);
7946             offset++;
7947         }
7948     }
7949
7950     tlbl = newiTempLabel(NULL);
7951     tlbl1= newiTempLabel(NULL);
7952     size = AOP_SIZE(result);
7953     offset = size - 1;
7954
7955     /* if it is only one byte then */
7956     if (size == 1) {
7957
7958       tlbl = newiTempLabel(NULL);
7959       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7960         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7961         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7962       }
7963
7964       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7965       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7966       pic16_emitpLabel(tlbl->key);
7967       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7968       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7969       emitSKPC;
7970       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7971
7972       goto release ;
7973     }
7974
7975     reAdjustPreg(AOP(result));
7976     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7977     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7978     CLRC;
7979     while (size--) {
7980         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7981         MOVA(l);
7982         pic16_emitcode("rrc","a");         
7983         pic16_aopPut(AOP(result),"a",offset--);
7984     }
7985     reAdjustPreg(AOP(result));
7986
7987     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7988     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7989
7990 release:
7991     pic16_freeAsmop(left,NULL,ic,TRUE);
7992     pic16_freeAsmop (right,NULL,ic,TRUE);
7993     pic16_freeAsmop(result,NULL,ic,TRUE);
7994 }
7995
7996 /*-----------------------------------------------------------------*/
7997 /* genUnpackBits - generates code for unpacking bits               */
7998 /*-----------------------------------------------------------------*/
7999 static void genUnpackBits (operand *result, char *rname, int ptype)
8000 {    
8001     int shCnt ;
8002     int rlen = 0 ;
8003     sym_link *etype;
8004     int offset = 0 ;
8005
8006     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8007     etype = getSpec(operandType(result));
8008
8009     /* read the first byte  */
8010     switch (ptype) {
8011
8012     case POINTER:
8013     case IPOINTER:
8014         pic16_emitcode("mov","a,@%s",rname);
8015         break;
8016         
8017     case PPOINTER:
8018         pic16_emitcode("movx","a,@%s",rname);
8019         break;
8020         
8021     case FPOINTER:
8022         pic16_emitcode("movx","a,@dptr");
8023         break;
8024
8025     case CPOINTER:
8026         pic16_emitcode("clr","a");
8027         pic16_emitcode("movc","a","@a+dptr");
8028         break;
8029
8030     case GPOINTER:
8031         pic16_emitcode("lcall","__gptrget");
8032         break;
8033     }
8034
8035     /* if we have bitdisplacement then it fits   */
8036     /* into this byte completely or if length is */
8037     /* less than a byte                          */
8038     if ((shCnt = SPEC_BSTR(etype)) || 
8039         (SPEC_BLEN(etype) <= 8))  {
8040
8041         /* shift right acc */
8042         AccRsh(shCnt);
8043
8044         pic16_emitcode("anl","a,#0x%02x",
8045                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8046         pic16_aopPut(AOP(result),"a",offset);
8047         return ;
8048     }
8049
8050     /* bit field did not fit in a byte  */
8051     rlen = SPEC_BLEN(etype) - 8;
8052     pic16_aopPut(AOP(result),"a",offset++);
8053
8054     while (1)  {
8055
8056         switch (ptype) {
8057         case POINTER:
8058         case IPOINTER:
8059             pic16_emitcode("inc","%s",rname);
8060             pic16_emitcode("mov","a,@%s",rname);
8061             break;
8062             
8063         case PPOINTER:
8064             pic16_emitcode("inc","%s",rname);
8065             pic16_emitcode("movx","a,@%s",rname);
8066             break;
8067
8068         case FPOINTER:
8069             pic16_emitcode("inc","dptr");
8070             pic16_emitcode("movx","a,@dptr");
8071             break;
8072             
8073         case CPOINTER:
8074             pic16_emitcode("clr","a");
8075             pic16_emitcode("inc","dptr");
8076             pic16_emitcode("movc","a","@a+dptr");
8077             break;
8078             
8079         case GPOINTER:
8080             pic16_emitcode("inc","dptr");
8081             pic16_emitcode("lcall","__gptrget");
8082             break;
8083         }
8084
8085         rlen -= 8;            
8086         /* if we are done */
8087         if ( rlen <= 0 )
8088             break ;
8089         
8090         pic16_aopPut(AOP(result),"a",offset++);
8091                               
8092     }
8093     
8094     if (rlen) {
8095         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8096         pic16_aopPut(AOP(result),"a",offset);          
8097     }
8098     
8099     return ;
8100 }
8101
8102 #if 0
8103 /*-----------------------------------------------------------------*/
8104 /* genDataPointerGet - generates code when ptr offset is known     */
8105 /*-----------------------------------------------------------------*/
8106 static void genDataPointerGet (operand *left, 
8107                                operand *result, 
8108                                iCode *ic)
8109 {
8110   int size , offset = 0;
8111
8112
8113   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8114
8115
8116   /* optimization - most of the time, left and result are the same
8117    * address, but different types. for the pic code, we could omit
8118    * the following
8119    */
8120
8121   pic16_aopOp(result,ic,TRUE);
8122
8123   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8124
8125   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8126
8127   size = AOP_SIZE(result);
8128
8129   while (size--) {
8130     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8131     offset++;
8132   }
8133
8134   pic16_freeAsmop(left,NULL,ic,TRUE);
8135   pic16_freeAsmop(result,NULL,ic,TRUE);
8136 }
8137 #endif
8138 /*-----------------------------------------------------------------*/
8139 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8140 /*-----------------------------------------------------------------*/
8141 static void genNearPointerGet (operand *left, 
8142                                operand *result, 
8143                                iCode *ic)
8144 {
8145     asmop *aop = NULL;
8146     //regs *preg = NULL ;
8147     char *rname ;
8148     sym_link *rtype, *retype;
8149     sym_link *ltype = operandType(left);    
8150     //char buffer[80];
8151
8152     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8153
8154     rtype = operandType(result);
8155     retype= getSpec(rtype);
8156     
8157     pic16_aopOp(left,ic,FALSE);
8158     
8159     /* if left is rematerialisable and
8160        result is not bit variable type and
8161        the left is pointer to data space i.e
8162        lower 128 bytes of space */
8163     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8164         !IS_BITVAR(retype)         &&
8165         DCL_TYPE(ltype) == POINTER) {
8166       //genDataPointerGet (left,result,ic);
8167         return ;
8168     }
8169     
8170     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8171
8172         /* if the value is already in a pointer register
8173        then don't need anything more */
8174     if (!AOP_INPREG(AOP(left))) {
8175         /* otherwise get a free pointer register */
8176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8177 /*
8178         aop = newAsmop(0);
8179         preg = getFreePtr(ic,&aop,FALSE);
8180         pic16_emitcode("mov","%s,%s",
8181                 preg->name,
8182                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8183         rname = preg->name ;
8184 */
8185     rname ="BAD";
8186     } else
8187         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8188     
8189     pic16_aopOp (result,ic,FALSE);
8190     
8191       /* if bitfield then unpack the bits */
8192     if (IS_BITVAR(retype)) 
8193         genUnpackBits (result,rname,POINTER);
8194     else {
8195         /* we have can just get the values */
8196       int size = AOP_SIZE(result);
8197       int offset = 0 ;  
8198         
8199       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8200
8201       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8202       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8203       while(size--) {
8204         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8205         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8206         if(size)
8207           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8208       }
8209 /*
8210         while (size--) {
8211             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8212
8213                 pic16_emitcode("mov","a,@%s",rname);
8214                 pic16_aopPut(AOP(result),"a",offset);
8215             } else {
8216                 sprintf(buffer,"@%s",rname);
8217                 pic16_aopPut(AOP(result),buffer,offset);
8218             }
8219             offset++ ;
8220             if (size)
8221                 pic16_emitcode("inc","%s",rname);
8222         }
8223 */
8224     }
8225
8226     /* now some housekeeping stuff */
8227     if (aop) {
8228         /* we had to allocate for this iCode */
8229     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8230         pic16_freeAsmop(NULL,aop,ic,TRUE);
8231     } else { 
8232         /* we did not allocate which means left
8233            already in a pointer register, then
8234            if size > 0 && this could be used again
8235            we have to point it back to where it 
8236            belongs */
8237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8238         if (AOP_SIZE(result) > 1 &&
8239             !OP_SYMBOL(left)->remat &&
8240             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8241               ic->depth )) {
8242             int size = AOP_SIZE(result) - 1;
8243             while (size--)
8244                 pic16_emitcode("dec","%s",rname);
8245         }
8246     }
8247
8248     /* done */
8249     pic16_freeAsmop(left,NULL,ic,TRUE);
8250     pic16_freeAsmop(result,NULL,ic,TRUE);
8251      
8252 }
8253
8254 /*-----------------------------------------------------------------*/
8255 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8256 /*-----------------------------------------------------------------*/
8257 static void genPagedPointerGet (operand *left, 
8258                                operand *result, 
8259                                iCode *ic)
8260 {
8261     asmop *aop = NULL;
8262     regs *preg = NULL ;
8263     char *rname ;
8264     sym_link *rtype, *retype;    
8265
8266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8267
8268     rtype = operandType(result);
8269     retype= getSpec(rtype);
8270     
8271     pic16_aopOp(left,ic,FALSE);
8272
8273   /* if the value is already in a pointer register
8274        then don't need anything more */
8275     if (!AOP_INPREG(AOP(left))) {
8276         /* otherwise get a free pointer register */
8277         aop = newAsmop(0);
8278         preg = getFreePtr(ic,&aop,FALSE);
8279         pic16_emitcode("mov","%s,%s",
8280                 preg->name,
8281                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8282         rname = preg->name ;
8283     } else
8284         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8285     
8286     pic16_freeAsmop(left,NULL,ic,TRUE);
8287     pic16_aopOp (result,ic,FALSE);
8288
8289     /* if bitfield then unpack the bits */
8290     if (IS_BITVAR(retype)) 
8291         genUnpackBits (result,rname,PPOINTER);
8292     else {
8293         /* we have can just get the values */
8294         int size = AOP_SIZE(result);
8295         int offset = 0 ;        
8296         
8297         while (size--) {
8298             
8299             pic16_emitcode("movx","a,@%s",rname);
8300             pic16_aopPut(AOP(result),"a",offset);
8301             
8302             offset++ ;
8303             
8304             if (size)
8305                 pic16_emitcode("inc","%s",rname);
8306         }
8307     }
8308
8309     /* now some housekeeping stuff */
8310     if (aop) {
8311         /* we had to allocate for this iCode */
8312         pic16_freeAsmop(NULL,aop,ic,TRUE);
8313     } else { 
8314         /* we did not allocate which means left
8315            already in a pointer register, then
8316            if size > 0 && this could be used again
8317            we have to point it back to where it 
8318            belongs */
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(result,NULL,ic,TRUE);
8331     
8332         
8333 }
8334
8335 /*-----------------------------------------------------------------*/
8336 /* genFarPointerGet - gget value from far space                    */
8337 /*-----------------------------------------------------------------*/
8338 static void genFarPointerGet (operand *left,
8339                               operand *result, iCode *ic)
8340 {
8341     int size, offset ;
8342     sym_link *retype = getSpec(operandType(result));
8343
8344     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8345
8346     pic16_aopOp(left,ic,FALSE);
8347
8348     /* if the operand is already in dptr 
8349     then we do nothing else we move the value to dptr */
8350     if (AOP_TYPE(left) != AOP_STR) {
8351         /* if this is remateriazable */
8352         if (AOP_TYPE(left) == AOP_IMMD)
8353             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8354         else { /* we need to get it byte by byte */
8355             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8356             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8357             if (options.model == MODEL_FLAT24)
8358             {
8359                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8360             }
8361         }
8362     }
8363     /* so dptr know contains the address */
8364     pic16_freeAsmop(left,NULL,ic,TRUE);
8365     pic16_aopOp(result,ic,FALSE);
8366
8367     /* if bit then unpack */
8368     if (IS_BITVAR(retype)) 
8369         genUnpackBits(result,"dptr",FPOINTER);
8370     else {
8371         size = AOP_SIZE(result);
8372         offset = 0 ;
8373
8374         while (size--) {
8375             pic16_emitcode("movx","a,@dptr");
8376             pic16_aopPut(AOP(result),"a",offset++);
8377             if (size)
8378                 pic16_emitcode("inc","dptr");
8379         }
8380     }
8381
8382     pic16_freeAsmop(result,NULL,ic,TRUE);
8383 }
8384 #if 0
8385 /*-----------------------------------------------------------------*/
8386 /* genCodePointerGet - get value from code space                  */
8387 /*-----------------------------------------------------------------*/
8388 static void genCodePointerGet (operand *left,
8389                                 operand *result, iCode *ic)
8390 {
8391     int size, offset ;
8392     sym_link *retype = getSpec(operandType(result));
8393
8394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8395
8396     pic16_aopOp(left,ic,FALSE);
8397
8398     /* if the operand is already in dptr 
8399     then we do nothing else we move the value to dptr */
8400     if (AOP_TYPE(left) != AOP_STR) {
8401         /* if this is remateriazable */
8402         if (AOP_TYPE(left) == AOP_IMMD)
8403             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8404         else { /* we need to get it byte by byte */
8405             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8406             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8407             if (options.model == MODEL_FLAT24)
8408             {
8409                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8410             }
8411         }
8412     }
8413     /* so dptr know contains the address */
8414     pic16_freeAsmop(left,NULL,ic,TRUE);
8415     pic16_aopOp(result,ic,FALSE);
8416
8417     /* if bit then unpack */
8418     if (IS_BITVAR(retype)) 
8419         genUnpackBits(result,"dptr",CPOINTER);
8420     else {
8421         size = AOP_SIZE(result);
8422         offset = 0 ;
8423
8424         while (size--) {
8425             pic16_emitcode("clr","a");
8426             pic16_emitcode("movc","a,@a+dptr");
8427             pic16_aopPut(AOP(result),"a",offset++);
8428             if (size)
8429                 pic16_emitcode("inc","dptr");
8430         }
8431     }
8432
8433     pic16_freeAsmop(result,NULL,ic,TRUE);
8434 }
8435 #endif
8436 /*-----------------------------------------------------------------*/
8437 /* genGenPointerGet - gget value from generic pointer space        */
8438 /*-----------------------------------------------------------------*/
8439 static void genGenPointerGet (operand *left,
8440                               operand *result, iCode *ic)
8441 {
8442   int size, offset ;
8443   sym_link *retype = getSpec(operandType(result));
8444
8445   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8446   pic16_aopOp(left,ic,FALSE);
8447   pic16_aopOp(result,ic,FALSE);
8448
8449
8450   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8451
8452   /* if the operand is already in dptr 
8453      then we do nothing else we move the value to dptr */
8454   //  if (AOP_TYPE(left) != AOP_STR) {
8455     /* if this is remateriazable */
8456     if (AOP_TYPE(left) == AOP_IMMD) {
8457       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8458       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8459     }
8460     else { /* we need to get it byte by byte */
8461
8462       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8463       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8464
8465       size = AOP_SIZE(result);
8466       offset = 0 ;
8467
8468       while(size--) {
8469         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8470         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8471         if(size)
8472           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8473       }
8474       goto release;
8475     }
8476     //}
8477   /* so dptr know contains the address */
8478
8479   /* if bit then unpack */
8480   //if (IS_BITVAR(retype)) 
8481   //  genUnpackBits(result,"dptr",GPOINTER);
8482
8483  release:
8484   pic16_freeAsmop(left,NULL,ic,TRUE);
8485   pic16_freeAsmop(result,NULL,ic,TRUE);
8486
8487 }
8488
8489 /*-----------------------------------------------------------------*/
8490 /* genConstPointerGet - get value from const generic pointer space */
8491 /*-----------------------------------------------------------------*/
8492 static void genConstPointerGet (operand *left,
8493                                 operand *result, iCode *ic)
8494 {
8495   //sym_link *retype = getSpec(operandType(result));
8496   symbol *albl = newiTempLabel(NULL);
8497   symbol *blbl = newiTempLabel(NULL);
8498   PIC_OPCODE poc;
8499
8500   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8501   pic16_aopOp(left,ic,FALSE);
8502   pic16_aopOp(result,ic,FALSE);
8503
8504
8505   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8506
8507   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8508
8509   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8510   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8511   pic16_emitpLabel(albl->key);
8512
8513   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8514     
8515   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8516   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8517   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8518   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8519
8520   pic16_emitpLabel(blbl->key);
8521
8522   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8523
8524
8525   pic16_freeAsmop(left,NULL,ic,TRUE);
8526   pic16_freeAsmop(result,NULL,ic,TRUE);
8527
8528 }
8529 /*-----------------------------------------------------------------*/
8530 /* genPointerGet - generate code for pointer get                   */
8531 /*-----------------------------------------------------------------*/
8532 static void genPointerGet (iCode *ic)
8533 {
8534     operand *left, *result ;
8535     sym_link *type, *etype;
8536     int p_type;
8537
8538     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8539
8540     left = IC_LEFT(ic);
8541     result = IC_RESULT(ic) ;
8542
8543     /* depending on the type of pointer we need to
8544     move it to the correct pointer register */
8545     type = operandType(left);
8546     etype = getSpec(type);
8547
8548 #if 0
8549     if (IS_PTR_CONST(type))
8550 #else
8551     if (IS_CODEPTR(type))
8552 #endif
8553       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8554
8555     /* if left is of type of pointer then it is simple */
8556     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8557         p_type = DCL_TYPE(type);
8558     else {
8559         /* we have to go by the storage class */
8560         p_type = PTR_TYPE(SPEC_OCLS(etype));
8561
8562         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8563
8564         if (SPEC_OCLS(etype)->codesp ) {
8565           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8566           //p_type = CPOINTER ; 
8567         }
8568         else
8569             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8570               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8571                /*p_type = FPOINTER ;*/ 
8572             else
8573                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8574                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8575 /*                  p_type = PPOINTER; */
8576                 else
8577                     if (SPEC_OCLS(etype) == idata )
8578                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8579 /*                      p_type = IPOINTER; */
8580                     else
8581                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8582 /*                      p_type = POINTER ; */
8583     }
8584
8585     /* now that we have the pointer type we assign
8586     the pointer values */
8587     switch (p_type) {
8588
8589     case POINTER:       
8590     case IPOINTER:
8591         genNearPointerGet (left,result,ic);
8592         break;
8593
8594     case PPOINTER:
8595         genPagedPointerGet(left,result,ic);
8596         break;
8597
8598     case FPOINTER:
8599         genFarPointerGet (left,result,ic);
8600         break;
8601
8602     case CPOINTER:
8603         genConstPointerGet (left,result,ic);
8604         //pic16_emitcodePointerGet (left,result,ic);
8605         break;
8606
8607     case GPOINTER:
8608 #if 0
8609       if (IS_PTR_CONST(type))
8610         genConstPointerGet (left,result,ic);
8611       else
8612 #endif
8613         genGenPointerGet (left,result,ic);
8614       break;
8615     }
8616
8617 }
8618
8619 /*-----------------------------------------------------------------*/
8620 /* genPackBits - generates code for packed bit storage             */
8621 /*-----------------------------------------------------------------*/
8622 static void genPackBits (sym_link    *etype ,
8623                          operand *right ,
8624                          char *rname, int p_type)
8625 {
8626     int shCount = 0 ;
8627     int offset = 0  ;
8628     int rLen = 0 ;
8629     int blen, bstr ;   
8630     char *l ;
8631
8632     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8633     blen = SPEC_BLEN(etype);
8634     bstr = SPEC_BSTR(etype);
8635
8636     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8637     MOVA(l);   
8638
8639     /* if the bit lenth is less than or    */
8640     /* it exactly fits a byte then         */
8641     if (SPEC_BLEN(etype) <= 8 )  {
8642         shCount = SPEC_BSTR(etype) ;
8643
8644         /* shift left acc */
8645         AccLsh(shCount);
8646
8647         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8648
8649
8650             switch (p_type) {
8651                 case POINTER:
8652                     pic16_emitcode ("mov","b,a");
8653                     pic16_emitcode("mov","a,@%s",rname);
8654                     break;
8655
8656                 case FPOINTER:
8657                     pic16_emitcode ("mov","b,a");
8658                     pic16_emitcode("movx","a,@dptr");
8659                     break;
8660
8661                 case GPOINTER:
8662                     pic16_emitcode ("push","b");
8663                     pic16_emitcode ("push","acc");
8664                     pic16_emitcode ("lcall","__gptrget");
8665                     pic16_emitcode ("pop","b");
8666                     break;
8667             }
8668
8669             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8670                       ((unsigned char)(0xFF << (blen+bstr)) | 
8671                        (unsigned char)(0xFF >> (8-bstr)) ) );
8672             pic16_emitcode ("orl","a,b");
8673             if (p_type == GPOINTER)
8674                 pic16_emitcode("pop","b");
8675         }
8676     }
8677
8678     switch (p_type) {
8679         case POINTER:
8680             pic16_emitcode("mov","@%s,a",rname);
8681             break;
8682
8683         case FPOINTER:
8684             pic16_emitcode("movx","@dptr,a");
8685             break;
8686
8687         case GPOINTER:
8688             DEBUGpic16_emitcode(";lcall","__gptrput");
8689             break;
8690     }
8691
8692     /* if we r done */
8693     if ( SPEC_BLEN(etype) <= 8 )
8694         return ;
8695
8696     pic16_emitcode("inc","%s",rname);
8697     rLen = SPEC_BLEN(etype) ;     
8698
8699     /* now generate for lengths greater than one byte */
8700     while (1) {
8701
8702         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8703
8704         rLen -= 8 ;
8705         if (rLen <= 0 )
8706             break ;
8707
8708         switch (p_type) {
8709             case POINTER:
8710                 if (*l == '@') {
8711                     MOVA(l);
8712                     pic16_emitcode("mov","@%s,a",rname);
8713                 } else
8714                     pic16_emitcode("mov","@%s,%s",rname,l);
8715                 break;
8716
8717             case FPOINTER:
8718                 MOVA(l);
8719                 pic16_emitcode("movx","@dptr,a");
8720                 break;
8721
8722             case GPOINTER:
8723                 MOVA(l);
8724                 DEBUGpic16_emitcode(";lcall","__gptrput");
8725                 break;  
8726         }   
8727         pic16_emitcode ("inc","%s",rname);
8728     }
8729
8730     MOVA(l);
8731
8732     /* last last was not complete */
8733     if (rLen)   {
8734         /* save the byte & read byte */
8735         switch (p_type) {
8736             case POINTER:
8737                 pic16_emitcode ("mov","b,a");
8738                 pic16_emitcode("mov","a,@%s",rname);
8739                 break;
8740
8741             case FPOINTER:
8742                 pic16_emitcode ("mov","b,a");
8743                 pic16_emitcode("movx","a,@dptr");
8744                 break;
8745
8746             case GPOINTER:
8747                 pic16_emitcode ("push","b");
8748                 pic16_emitcode ("push","acc");
8749                 pic16_emitcode ("lcall","__gptrget");
8750                 pic16_emitcode ("pop","b");
8751                 break;
8752         }
8753
8754         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8755         pic16_emitcode ("orl","a,b");
8756     }
8757
8758     if (p_type == GPOINTER)
8759         pic16_emitcode("pop","b");
8760
8761     switch (p_type) {
8762
8763     case POINTER:
8764         pic16_emitcode("mov","@%s,a",rname);
8765         break;
8766         
8767     case FPOINTER:
8768         pic16_emitcode("movx","@dptr,a");
8769         break;
8770         
8771     case GPOINTER:
8772         DEBUGpic16_emitcode(";lcall","__gptrput");
8773         break;                  
8774     }
8775 }
8776 /*-----------------------------------------------------------------*/
8777 /* genDataPointerSet - remat pointer to data space                 */
8778 /*-----------------------------------------------------------------*/
8779 static void genDataPointerSet(operand *right,
8780                               operand *result,
8781                               iCode *ic)
8782 {
8783     int size, offset = 0 ;
8784     char *l, buffer[256];
8785
8786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8787     pic16_aopOp(right,ic,FALSE);
8788     
8789     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8790     size = AOP_SIZE(right);
8791 /*
8792     if ( AOP_TYPE(result) == AOP_PCODE) {
8793       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8794               AOP(result)->aopu.pcop->name,
8795               PCOI(AOP(result)->aopu.pcop)->offset);
8796     }
8797 */
8798
8799     // tsd, was l+1 - the underline `_' prefix was being stripped
8800     while (size--) {
8801       if (offset) {
8802         sprintf(buffer,"(%s + %d)",l,offset);
8803         fprintf(stderr,"oops  %s\n",buffer);
8804       } else
8805         sprintf(buffer,"%s",l);
8806
8807         if (AOP_TYPE(right) == AOP_LIT) {
8808           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8809           lit = lit >> (8*offset);
8810           if(lit&0xff) {
8811             pic16_emitcode("movlw","%d",lit);
8812             pic16_emitcode("movwf","%s",buffer);
8813
8814             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8815             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8816             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8817
8818           } else {
8819             pic16_emitcode("clrf","%s",buffer);
8820             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
8821             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8822           }
8823         }else {
8824           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8825           pic16_emitcode("movwf","%s",buffer);
8826
8827           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8828           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8829           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8830
8831         }
8832
8833         offset++;
8834     }
8835
8836     pic16_freeAsmop(right,NULL,ic,TRUE);
8837     pic16_freeAsmop(result,NULL,ic,TRUE);
8838 }
8839
8840 /*-----------------------------------------------------------------*/
8841 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8842 /*-----------------------------------------------------------------*/
8843 static void genNearPointerSet (operand *right,
8844                                operand *result, 
8845                                iCode *ic)
8846 {
8847   asmop *aop = NULL;
8848   char *l;
8849   sym_link *retype;
8850   sym_link *ptype = operandType(result);
8851
8852     
8853   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8854   retype= getSpec(operandType(right));
8855
8856   pic16_aopOp(result,ic,FALSE);
8857
8858     
8859   /* if the result is rematerializable &
8860      in data space & not a bit variable */
8861   //if (AOP_TYPE(result) == AOP_IMMD &&
8862   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8863       DCL_TYPE(ptype) == POINTER   &&
8864       !IS_BITVAR(retype)) {
8865     genDataPointerSet (right,result,ic);
8866     pic16_freeAsmop(result,NULL,ic,TRUE);
8867     return;
8868   }
8869
8870   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8871   pic16_aopOp(right,ic,FALSE);
8872   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8873
8874   /* if the value is already in a pointer register
8875      then don't need anything more */
8876   if (!AOP_INPREG(AOP(result))) {
8877     /* otherwise get a free pointer register */
8878     //aop = newAsmop(0);
8879     //preg = getFreePtr(ic,&aop,FALSE);
8880     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8881     //pic16_emitcode("mov","%s,%s",
8882     //         preg->name,
8883     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8884     //rname = preg->name ;
8885     //pic16_emitcode("movwf","fsr0");
8886     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8887     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8888     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8889     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8890     goto release;
8891
8892   }// else
8893   //   rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8894
8895
8896   /* if bitfield then unpack the bits */
8897   if (IS_BITVAR(retype)) {
8898     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8899            "The programmer is obviously confused");
8900     //genPackBits (retype,right,rname,POINTER);
8901     exit(1);
8902   }
8903   else {
8904     /* we have can just get the values */
8905     int size = AOP_SIZE(right);
8906     int offset = 0 ;    
8907
8908     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8909     while (size--) {
8910       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8911       if (*l == '@' ) {
8912         //MOVA(l);
8913         //pic16_emitcode("mov","@%s,a",rname);
8914         pic16_emitcode("movf","indf0,w ;1");
8915       } else {
8916
8917         if (AOP_TYPE(right) == AOP_LIT) {
8918           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8919           if(lit) {
8920             pic16_emitcode("movlw","%s",l);
8921             pic16_emitcode("movwf","indf0 ;2");
8922           } else 
8923             pic16_emitcode("clrf","indf0");
8924         }else {
8925           pic16_emitcode("movf","%s,w",l);
8926           pic16_emitcode("movwf","indf0 ;2");
8927         }
8928         //pic16_emitcode("mov","@%s,%s",rname,l);
8929       }
8930       if (size)
8931         pic16_emitcode("incf","fsr0,f ;3");
8932       //pic16_emitcode("inc","%s",rname);
8933       offset++;
8934     }
8935   }
8936
8937   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8938   /* now some housekeeping stuff */
8939   if (aop) {
8940     /* we had to allocate for this iCode */
8941     pic16_freeAsmop(NULL,aop,ic,TRUE);
8942   } else { 
8943     /* we did not allocate which means left
8944        already in a pointer register, then
8945        if size > 0 && this could be used again
8946        we have to point it back to where it 
8947        belongs */
8948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8949     if (AOP_SIZE(right) > 1 &&
8950         !OP_SYMBOL(result)->remat &&
8951         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8952           ic->depth )) {
8953       int size = AOP_SIZE(right) - 1;
8954       while (size--)
8955         pic16_emitcode("decf","fsr0,f");
8956       //pic16_emitcode("dec","%s",rname);
8957     }
8958   }
8959
8960   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8961   /* done */
8962  release:
8963   pic16_freeAsmop(right,NULL,ic,TRUE);
8964   pic16_freeAsmop(result,NULL,ic,TRUE);
8965 }
8966
8967 /*-----------------------------------------------------------------*/
8968 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
8969 /*-----------------------------------------------------------------*/
8970 static void genPagedPointerSet (operand *right,
8971                                operand *result, 
8972                                iCode *ic)
8973 {
8974     asmop *aop = NULL;
8975     regs *preg = NULL ;
8976     char *rname , *l;
8977     sym_link *retype;
8978        
8979     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8980
8981     retype= getSpec(operandType(right));
8982     
8983     pic16_aopOp(result,ic,FALSE);
8984     
8985     /* if the value is already in a pointer register
8986        then don't need anything more */
8987     if (!AOP_INPREG(AOP(result))) {
8988         /* otherwise get a free pointer register */
8989         aop = newAsmop(0);
8990         preg = getFreePtr(ic,&aop,FALSE);
8991         pic16_emitcode("mov","%s,%s",
8992                 preg->name,
8993                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
8994         rname = preg->name ;
8995     } else
8996         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8997     
8998     pic16_freeAsmop(result,NULL,ic,TRUE);
8999     pic16_aopOp (right,ic,FALSE);
9000
9001     /* if bitfield then unpack the bits */
9002     if (IS_BITVAR(retype)) 
9003         genPackBits (retype,right,rname,PPOINTER);
9004     else {
9005         /* we have can just get the values */
9006         int size = AOP_SIZE(right);
9007         int offset = 0 ;        
9008         
9009         while (size--) {
9010             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9011             
9012             MOVA(l);
9013             pic16_emitcode("movx","@%s,a",rname);
9014
9015             if (size)
9016                 pic16_emitcode("inc","%s",rname);
9017
9018             offset++;
9019         }
9020     }
9021     
9022     /* now some housekeeping stuff */
9023     if (aop) {
9024         /* we had to allocate for this iCode */
9025         pic16_freeAsmop(NULL,aop,ic,TRUE);
9026     } else { 
9027         /* we did not allocate which means left
9028            already in a pointer register, then
9029            if size > 0 && this could be used again
9030            we have to point it back to where it 
9031            belongs */
9032         if (AOP_SIZE(right) > 1 &&
9033             !OP_SYMBOL(result)->remat &&
9034             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9035               ic->depth )) {
9036             int size = AOP_SIZE(right) - 1;
9037             while (size--)
9038                 pic16_emitcode("dec","%s",rname);
9039         }
9040     }
9041
9042     /* done */
9043     pic16_freeAsmop(right,NULL,ic,TRUE);
9044     
9045         
9046 }
9047
9048 /*-----------------------------------------------------------------*/
9049 /* genFarPointerSet - set value from far space                     */
9050 /*-----------------------------------------------------------------*/
9051 static void genFarPointerSet (operand *right,
9052                               operand *result, iCode *ic)
9053 {
9054     int size, offset ;
9055     sym_link *retype = getSpec(operandType(right));
9056
9057     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9058     pic16_aopOp(result,ic,FALSE);
9059
9060     /* if the operand is already in dptr 
9061     then we do nothing else we move the value to dptr */
9062     if (AOP_TYPE(result) != AOP_STR) {
9063         /* if this is remateriazable */
9064         if (AOP_TYPE(result) == AOP_IMMD)
9065             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9066         else { /* we need to get it byte by byte */
9067             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9068             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9069             if (options.model == MODEL_FLAT24)
9070             {
9071                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9072             }
9073         }
9074     }
9075     /* so dptr know contains the address */
9076     pic16_freeAsmop(result,NULL,ic,TRUE);
9077     pic16_aopOp(right,ic,FALSE);
9078
9079     /* if bit then unpack */
9080     if (IS_BITVAR(retype)) 
9081         genPackBits(retype,right,"dptr",FPOINTER);
9082     else {
9083         size = AOP_SIZE(right);
9084         offset = 0 ;
9085
9086         while (size--) {
9087             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9088             MOVA(l);
9089             pic16_emitcode("movx","@dptr,a");
9090             if (size)
9091                 pic16_emitcode("inc","dptr");
9092         }
9093     }
9094
9095     pic16_freeAsmop(right,NULL,ic,TRUE);
9096 }
9097
9098 /*-----------------------------------------------------------------*/
9099 /* genGenPointerSet - set value from generic pointer space         */
9100 /*-----------------------------------------------------------------*/
9101 static void genGenPointerSet (operand *right,
9102                               operand *result, iCode *ic)
9103 {
9104   int size, offset ;
9105   sym_link *retype = getSpec(operandType(right));
9106
9107   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9108
9109   pic16_aopOp(result,ic,FALSE);
9110   pic16_aopOp(right,ic,FALSE);
9111   size = AOP_SIZE(right);
9112
9113   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9114
9115   /* if the operand is already in dptr 
9116      then we do nothing else we move the value to dptr */
9117   if (AOP_TYPE(result) != AOP_STR) {
9118     /* if this is remateriazable */
9119     if (AOP_TYPE(result) == AOP_IMMD) {
9120       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9121       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9122     }
9123     else { /* we need to get it byte by byte */
9124       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9125       size = AOP_SIZE(right);
9126       offset = 0 ;
9127
9128       /* hack hack! see if this the FSR. If so don't load W */
9129       if(AOP_TYPE(right) != AOP_ACC) {
9130
9131 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(result), pic16_popCopyReg(&pic16_pc_fsr0), 0));
9132
9133         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9134         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9135
9136         if(AOP_SIZE(result) > 1) {
9137           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9138           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9139           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9140
9141         }
9142
9143         //if(size==2)
9144         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9145         //if(size==4) {
9146         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9147         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9148         //}
9149
9150         while(size--) {
9151           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9152           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9153           
9154           if(size)
9155             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9156         }
9157
9158
9159         goto release;
9160       } 
9161
9162       if(aopIdx(AOP(result),0) != 4) {
9163
9164         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9165         goto release;
9166       }
9167
9168       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9169       goto release;
9170
9171     }
9172   }
9173   /* so dptr know contains the address */
9174
9175
9176   /* if bit then unpack */
9177   if (IS_BITVAR(retype)) 
9178     genPackBits(retype,right,"dptr",GPOINTER);
9179   else {
9180     size = AOP_SIZE(right);
9181     offset = 0 ;
9182
9183   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9184
9185     while (size--) {
9186
9187       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9188       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9189
9190       if (AOP_TYPE(right) == AOP_LIT) 
9191         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9192       else
9193         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9194
9195       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9196
9197       offset++;
9198     }
9199   }
9200
9201  release:
9202   pic16_freeAsmop(right,NULL,ic,TRUE);
9203   pic16_freeAsmop(result,NULL,ic,TRUE);
9204 }
9205
9206 /*-----------------------------------------------------------------*/
9207 /* genPointerSet - stores the value into a pointer location        */
9208 /*-----------------------------------------------------------------*/
9209 static void genPointerSet (iCode *ic)
9210 {    
9211     operand *right, *result ;
9212     sym_link *type, *etype;
9213     int p_type;
9214
9215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9216
9217     right = IC_RIGHT(ic);
9218     result = IC_RESULT(ic) ;
9219
9220     /* depending on the type of pointer we need to
9221     move it to the correct pointer register */
9222     type = operandType(result);
9223     etype = getSpec(type);
9224     /* if left is of type of pointer then it is simple */
9225     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9226         p_type = DCL_TYPE(type);
9227     }
9228     else {
9229         /* we have to go by the storage class */
9230         p_type = PTR_TYPE(SPEC_OCLS(etype));
9231
9232 /*      if (SPEC_OCLS(etype)->codesp ) { */
9233 /*          p_type = CPOINTER ;  */
9234 /*      } */
9235 /*      else */
9236 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9237 /*              p_type = FPOINTER ; */
9238 /*          else */
9239 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9240 /*                  p_type = PPOINTER ; */
9241 /*              else */
9242 /*                  if (SPEC_OCLS(etype) == idata ) */
9243 /*                      p_type = IPOINTER ; */
9244 /*                  else */
9245 /*                      p_type = POINTER ; */
9246     }
9247
9248     /* now that we have the pointer type we assign
9249     the pointer values */
9250     switch (p_type) {
9251
9252     case POINTER:
9253     case IPOINTER:
9254         genNearPointerSet (right,result,ic);
9255         break;
9256
9257     case PPOINTER:
9258         genPagedPointerSet (right,result,ic);
9259         break;
9260
9261     case FPOINTER:
9262         genFarPointerSet (right,result,ic);
9263         break;
9264
9265     case GPOINTER:
9266         genGenPointerSet (right,result,ic);
9267         break;
9268
9269     default:
9270       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9271               "genPointerSet: illegal pointer type");
9272     }
9273 }
9274
9275 /*-----------------------------------------------------------------*/
9276 /* genIfx - generate code for Ifx statement                        */
9277 /*-----------------------------------------------------------------*/
9278 static void genIfx (iCode *ic, iCode *popIc)
9279 {
9280   operand *cond = IC_COND(ic);
9281   int isbit =0;
9282
9283   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9284
9285   pic16_aopOp(cond,ic,FALSE);
9286
9287   /* get the value into acc */
9288   if (AOP_TYPE(cond) != AOP_CRY)
9289     pic16_toBoolean(cond);
9290   else
9291     isbit = 1;
9292   /* the result is now in the accumulator */
9293   pic16_freeAsmop(cond,NULL,ic,TRUE);
9294
9295   /* if there was something to be popped then do it */
9296   if (popIc)
9297     genIpop(popIc);
9298
9299   /* if the condition is  a bit variable */
9300   if (isbit && IS_ITEMP(cond) && 
9301       SPIL_LOC(cond)) {
9302     genIfxJump(ic,SPIL_LOC(cond)->rname);
9303     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9304   }
9305   else {
9306     if (isbit && !IS_ITEMP(cond))
9307       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9308     else
9309       genIfxJump(ic,"a");
9310   }
9311   ic->generated = 1;
9312
9313 }
9314
9315 /*-----------------------------------------------------------------*/
9316 /* genAddrOf - generates code for address of                       */
9317 /*-----------------------------------------------------------------*/
9318 #if 0
9319 static void genAddrOf (iCode *ic)
9320 {
9321   operand *right, *result, *left;
9322   int size, offset ;
9323
9324   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9325
9326
9327   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9328
9329   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9330   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9331   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9332
9333   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9334
9335   size = AOP_SIZE(IC_RESULT(ic));
9336   offset = 0;
9337
9338
9339   while (size--) {
9340     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9341     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9342     offset++;
9343   }
9344
9345
9346   pic16_freeAsmop(left,NULL,ic,FALSE);
9347   pic16_freeAsmop(result,NULL,ic,TRUE);
9348
9349 }
9350
9351 #else   /* new genAddrOf */
9352
9353 static void genAddrOf (iCode *ic)
9354 {
9355   operand *result, *left;
9356   int size;
9357   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9358   pCodeOp *pcop0, *pcop1;
9359
9360         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9361
9362         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9363         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9364
9365         sym = OP_SYMBOL( left );
9366
9367         size = AOP_SIZE(IC_RESULT(ic));
9368
9369         /* Assume that what we want the address of is in direct addressing space
9370          * since there is no stack on the PIC, yet! -- VR */
9371
9372         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, 0));
9373         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, 0));
9374 #if 0
9375         pcop0 = pic16_newpCodeOp(sym->rname, PO_IMMEDIATE);
9376         PCOI(pcop0)->offset = 0;
9377         PCOI(pcop0)->index = 0;
9378         pcop1 = pic16_newpCodeOp(sym->rname, PO_IMMEDIATE);
9379         PCOI(pcop1)->offset = 1;
9380         PCOI(pcop1)->index = 0;
9381 #endif
9382
9383         if (size == 2) {
9384                 pic16_emitpcode(POC_MOVLW, pcop0);
9385                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9386                 pic16_emitpcode(POC_MOVLW, pcop1);
9387                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9388         } else {
9389                 pic16_emitpcode(POC_MOVLW, pcop0);
9390                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9391         }
9392
9393         pic16_freeAsmop(result,NULL,ic,TRUE);
9394         pic16_freeAsmop(left, NULL, ic, FALSE);
9395 }
9396
9397 #endif  /* new genAddrOf */
9398
9399 #if 0
9400 /*-----------------------------------------------------------------*/
9401 /* genFarFarAssign - assignment when both are in far space         */
9402 /*-----------------------------------------------------------------*/
9403 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9404 {
9405     int size = AOP_SIZE(right);
9406     int offset = 0;
9407     char *l ;
9408     /* first push the right side on to the stack */
9409     while (size--) {
9410         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9411         MOVA(l);
9412         pic16_emitcode ("push","acc");
9413     }
9414     
9415     pic16_freeAsmop(right,NULL,ic,FALSE);
9416     /* now assign DPTR to result */
9417     pic16_aopOp(result,ic,FALSE);
9418     size = AOP_SIZE(result);
9419     while (size--) {
9420         pic16_emitcode ("pop","acc");
9421         pic16_aopPut(AOP(result),"a",--offset);
9422     }
9423     pic16_freeAsmop(result,NULL,ic,FALSE);
9424         
9425 }
9426 #endif
9427
9428 /*-----------------------------------------------------------------*/
9429 /* genAssign - generate code for assignment                        */
9430 /*-----------------------------------------------------------------*/
9431 static void genAssign (iCode *ic)
9432 {
9433   operand *result, *right;
9434   int size, offset,know_W;
9435   unsigned long lit = 0L;
9436
9437   result = IC_RESULT(ic);
9438   right  = IC_RIGHT(ic) ;
9439
9440   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9441   
9442   /* if they are the same */
9443   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9444     return ;
9445
9446   pic16_aopOp(right,ic,FALSE);
9447   pic16_aopOp(result,ic,TRUE);
9448
9449   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9450
9451   /* if they are the same registers */
9452   if (pic16_sameRegs(AOP(right),AOP(result)))
9453     goto release;
9454
9455   /* if the result is a bit */
9456   if (AOP_TYPE(result) == AOP_CRY) {
9457     /* if the right size is a literal then
9458        we know what the value is */
9459     if (AOP_TYPE(right) == AOP_LIT) {
9460           
9461       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9462                   pic16_popGet(AOP(result),0));
9463
9464       if (((int) operandLitValue(right))) 
9465         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9466                        AOP(result)->aopu.aop_dir,
9467                        AOP(result)->aopu.aop_dir);
9468       else
9469         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9470                        AOP(result)->aopu.aop_dir,
9471                        AOP(result)->aopu.aop_dir);
9472       goto release;
9473     }
9474
9475     /* the right is also a bit variable */
9476     if (AOP_TYPE(right) == AOP_CRY) {
9477       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9478       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9479       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9480
9481       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9482                      AOP(result)->aopu.aop_dir,
9483                      AOP(result)->aopu.aop_dir);
9484       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9485                      AOP(right)->aopu.aop_dir,
9486                      AOP(right)->aopu.aop_dir);
9487       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9488                      AOP(result)->aopu.aop_dir,
9489                      AOP(result)->aopu.aop_dir);
9490       goto release ;
9491     }
9492
9493     /* we need to or */
9494     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9495     pic16_toBoolean(right);
9496     emitSKPZ;
9497     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9498     //pic16_aopPut(AOP(result),"a",0);
9499     goto release ;
9500   }
9501
9502   /* bit variables done */
9503   /* general case */
9504   size = AOP_SIZE(result);
9505   offset = 0 ;
9506   if(AOP_TYPE(right) == AOP_LIT)
9507     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9508
9509 /* VR - What is this?! */
9510   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9511   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9512     if(aopIdx(AOP(result),0) == 4) {
9513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9514       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9515       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9516       goto release;
9517     } else
9518       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9519   }
9520
9521   know_W=-1;
9522   while (size--) {
9523   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9524     if(AOP_TYPE(right) == AOP_LIT) {
9525       if(lit&0xff) {
9526         if(know_W != (lit&0xff))
9527           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9528         know_W = lit&0xff;
9529         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9530       } else
9531         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9532
9533       lit >>= 8;
9534
9535     } else if (AOP_TYPE(right) == AOP_CRY) {
9536       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9537       if(offset == 0) {
9538         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9539         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9540       }
9541     } else {
9542   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9543
9544 #if 1
9545         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9546            normally should work, but mind that the W register live range
9547            is not checked, so if the code generator assumes that the W
9548            is already loaded after such a pair, wrong code will be generated.
9549            
9550            Checking the live range is the next step.
9551            This is experimental code yet and has not been fully tested yet.
9552            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9553            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9554            
9555         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9556 #else   
9557         /* This is the old code, which is assumed(?!) that works fine(!?) */
9558
9559         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9560         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9561 #endif
9562     }
9563             
9564     offset++;
9565   }
9566
9567     
9568  release:
9569   pic16_freeAsmop (right,NULL,ic,FALSE);
9570   pic16_freeAsmop (result,NULL,ic,TRUE);
9571 }   
9572
9573 /*-----------------------------------------------------------------*/
9574 /* genJumpTab - generates code for jump table                       */
9575 /*-----------------------------------------------------------------*/
9576 static void genJumpTab (iCode *ic)
9577 {
9578     symbol *jtab;
9579     char *l;
9580
9581     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9582
9583     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9584     /* get the condition into accumulator */
9585     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9586     MOVA(l);
9587     /* multiply by three */
9588     pic16_emitcode("add","a,acc");
9589     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9590
9591     jtab = newiTempLabel(NULL);
9592     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9593     pic16_emitcode("jmp","@a+dptr");
9594     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9595
9596     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9597     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9598     emitSKPNC;
9599     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9600     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9601     pic16_emitpLabel(jtab->key);
9602
9603     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9604
9605     /* now generate the jump labels */
9606     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9607          jtab = setNextItem(IC_JTLABELS(ic))) {
9608         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9609         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9610         
9611     }
9612
9613 }
9614
9615 /*-----------------------------------------------------------------*/
9616 /* genMixedOperation - gen code for operators between mixed types  */
9617 /*-----------------------------------------------------------------*/
9618 /*
9619   TSD - Written for the PIC port - but this unfortunately is buggy.
9620   This routine is good in that it is able to efficiently promote 
9621   types to different (larger) sizes. Unfortunately, the temporary
9622   variables that are optimized out by this routine are sometimes
9623   used in other places. So until I know how to really parse the 
9624   iCode tree, I'm going to not be using this routine :(.
9625 */
9626 static int genMixedOperation (iCode *ic)
9627 {
9628 #if 0
9629   operand *result = IC_RESULT(ic);
9630   sym_link *ctype = operandType(IC_LEFT(ic));
9631   operand *right = IC_RIGHT(ic);
9632   int ret = 0;
9633   int big,small;
9634   int offset;
9635
9636   iCode *nextic;
9637   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9638
9639   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9640
9641   nextic = ic->next;
9642   if(!nextic)
9643     return 0;
9644
9645   nextright = IC_RIGHT(nextic);
9646   nextleft  = IC_LEFT(nextic);
9647   nextresult = IC_RESULT(nextic);
9648
9649   pic16_aopOp(right,ic,FALSE);
9650   pic16_aopOp(result,ic,FALSE);
9651   pic16_aopOp(nextright,  nextic, FALSE);
9652   pic16_aopOp(nextleft,   nextic, FALSE);
9653   pic16_aopOp(nextresult, nextic, FALSE);
9654
9655   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9656
9657     operand *t = right;
9658     right = nextright;
9659     nextright = t; 
9660
9661     pic16_emitcode(";remove right +","");
9662
9663   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9664 /*
9665     operand *t = right;
9666     right = nextleft;
9667     nextleft = t; 
9668 */
9669     pic16_emitcode(";remove left +","");
9670   } else
9671     return 0;
9672
9673   big = AOP_SIZE(nextleft);
9674   small = AOP_SIZE(nextright);
9675
9676   switch(nextic->op) {
9677
9678   case '+':
9679     pic16_emitcode(";optimize a +","");
9680     /* if unsigned or not an integral type */
9681     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9682       pic16_emitcode(";add a bit to something","");
9683     } else {
9684
9685       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9686
9687       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9688         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9689         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9690       } else
9691         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9692
9693       offset = 0;
9694       while(--big) {
9695
9696         offset++;
9697
9698         if(--small) {
9699           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9700             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9701             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9702           }
9703
9704           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9705           emitSKPNC;
9706           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9707                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9708                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9709           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9710           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9711
9712         } else {
9713           pic16_emitcode("rlf","known_zero,w");
9714
9715           /*
9716             if right is signed
9717               btfsc  right,7
9718                addlw ff
9719           */
9720           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9721             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9722             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9723           } else {
9724             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9725           }
9726         }
9727       }
9728       ret = 1;
9729     }
9730   }
9731   ret = 1;
9732
9733 release:
9734   pic16_freeAsmop(right,NULL,ic,TRUE);
9735   pic16_freeAsmop(result,NULL,ic,TRUE);
9736   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9737   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9738   if(ret)
9739     nextic->generated = 1;
9740
9741   return ret;
9742 #else
9743   return 0;
9744 #endif
9745 }
9746 /*-----------------------------------------------------------------*/
9747 /* genCast - gen code for casting                                  */
9748 /*-----------------------------------------------------------------*/
9749 static void genCast (iCode *ic)
9750 {
9751     operand *result = IC_RESULT(ic);
9752     sym_link *ctype = operandType(IC_LEFT(ic));
9753     sym_link *rtype = operandType(IC_RIGHT(ic));
9754     operand *right = IC_RIGHT(ic);
9755     int size, offset ;
9756
9757     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9758     /* if they are equivalent then do nothing */
9759     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9760         return ;
9761
9762     pic16_aopOp(right,ic,FALSE) ;
9763     pic16_aopOp(result,ic,FALSE);
9764
9765     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9766
9767     /* if the result is a bit */
9768     if (AOP_TYPE(result) == AOP_CRY) {
9769         /* if the right size is a literal then
9770         we know what the value is */
9771       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9772         if (AOP_TYPE(right) == AOP_LIT) {
9773
9774           pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9775                       pic16_popGet(AOP(result),0));
9776
9777             if (((int) operandLitValue(right))) 
9778               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9779                        AOP(result)->aopu.aop_dir,
9780                        AOP(result)->aopu.aop_dir);
9781             else
9782               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9783                        AOP(result)->aopu.aop_dir,
9784                        AOP(result)->aopu.aop_dir);
9785
9786             goto release;
9787         }
9788
9789         /* the right is also a bit variable */
9790         if (AOP_TYPE(right) == AOP_CRY) {
9791
9792           emitCLRC;
9793           pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9794
9795           pic16_emitcode("clrc","");
9796           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9797                    AOP(right)->aopu.aop_dir,
9798                    AOP(right)->aopu.aop_dir);
9799             pic16_aopPut(AOP(result),"c",0);
9800             goto release ;
9801         }
9802
9803         /* we need to or */
9804         if (AOP_TYPE(right) == AOP_REG) {
9805           pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9806           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9807           pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9808         }
9809         pic16_toBoolean(right);
9810         pic16_aopPut(AOP(result),"a",0);
9811         goto release ;
9812     }
9813
9814     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9815       int offset = 1;
9816       size = AOP_SIZE(result);
9817
9818       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9819
9820       pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9821       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9822       pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9823
9824       while (size--)
9825         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9826
9827       goto release;
9828     }
9829
9830     /* if they are the same size : or less */
9831     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9832
9833         /* if they are in the same place */
9834       if (pic16_sameRegs(AOP(right),AOP(result)))
9835         goto release;
9836
9837       DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9838 #if 0
9839       if (IS_PTR_CONST(rtype))
9840 #else
9841       if (IS_CODEPTR(rtype))
9842 #endif
9843         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9844 #if 0
9845       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9846 #else
9847       if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9848 #endif
9849         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9850
9851       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9852         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9853         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9854         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9855         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9856         if(AOP_SIZE(result) <2)
9857           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9858
9859       } else {
9860
9861         /* if they in different places then copy */
9862         size = AOP_SIZE(result);
9863         offset = 0 ;
9864         while (size--) {
9865           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9866           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9867
9868           //pic16_aopPut(AOP(result),
9869           // pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9870           // offset);
9871
9872           offset++;
9873         }
9874       }
9875       goto release;
9876     }
9877
9878
9879     /* if the result is of type pointer */
9880     if (IS_PTR(ctype)) {
9881
9882         int p_type;
9883         sym_link *type = operandType(right);
9884         sym_link *etype = getSpec(type);
9885       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9886
9887         /* pointer to generic pointer */
9888         if (IS_GENPTR(ctype)) {
9889             char *l = zero;
9890             
9891             if (IS_PTR(type)) 
9892                 p_type = DCL_TYPE(type);
9893             else {
9894                 /* we have to go by the storage class */
9895                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9896
9897 /*              if (SPEC_OCLS(etype)->codesp )  */
9898 /*                  p_type = CPOINTER ;  */
9899 /*              else */
9900 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9901 /*                      p_type = FPOINTER ; */
9902 /*                  else */
9903 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9904 /*                          p_type = PPOINTER; */
9905 /*                      else */
9906 /*                          if (SPEC_OCLS(etype) == idata ) */
9907 /*                              p_type = IPOINTER ; */
9908 /*                          else */
9909 /*                              p_type = POINTER ; */
9910             }
9911                 
9912             /* the first two bytes are known */
9913       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9914             size = GPTRSIZE - 1; 
9915             offset = 0 ;
9916             while (size--) {
9917               if(offset < AOP_SIZE(right)) {
9918       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9919                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9920                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9921                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9922                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9923                 } else { 
9924                   pic16_aopPut(AOP(result),
9925                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9926                          offset);
9927                 }
9928               } else 
9929                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9930               offset++;
9931             }
9932             /* the last byte depending on type */
9933             switch (p_type) {
9934             case IPOINTER:
9935             case POINTER:
9936                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
9937                 break;
9938             case FPOINTER:
9939               pic16_emitcode(";BUG!? ","%d",__LINE__);
9940                 l = one;
9941                 break;
9942             case CPOINTER:
9943               pic16_emitcode(";BUG!? ","%d",__LINE__);
9944                 l = "#0x02";
9945                 break;                          
9946             case PPOINTER:
9947               pic16_emitcode(";BUG!? ","%d",__LINE__);
9948                 l = "#0x03";
9949                 break;
9950                 
9951             default:
9952                 /* this should never happen */
9953                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9954                        "got unknown pointer type");
9955                 exit(1);
9956             }
9957             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
9958             goto release ;
9959         }
9960         
9961         /* just copy the pointers */
9962         size = AOP_SIZE(result);
9963         offset = 0 ;
9964         while (size--) {
9965             pic16_aopPut(AOP(result),
9966                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9967                    offset);
9968             offset++;
9969         }
9970         goto release ;
9971     }
9972     
9973
9974
9975     /* so we now know that the size of destination is greater
9976     than the size of the source.
9977     Now, if the next iCode is an operator then we might be
9978     able to optimize the operation without performing a cast.
9979     */
9980     if(genMixedOperation(ic))
9981       goto release;
9982
9983     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9984     
9985     /* we move to result for the size of source */
9986     size = AOP_SIZE(right);
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     /* now depending on the sign of the destination */
9995     size = AOP_SIZE(result) - AOP_SIZE(right);
9996     /* if unsigned or not an integral type */
9997     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9998       while (size--)
9999         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10000     } else {
10001       /* we need to extend the sign :{ */
10002
10003       if(size == 1) {
10004         /* Save one instruction of casting char to int */
10005         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10006         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10007         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10008       } else {
10009         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10010
10011         if(offset)
10012           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10013         else
10014           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10015         
10016         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10017
10018         while (size--)
10019           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10020       }
10021     }
10022
10023 release:
10024     pic16_freeAsmop(right,NULL,ic,TRUE);
10025     pic16_freeAsmop(result,NULL,ic,TRUE);
10026
10027 }
10028
10029 /*-----------------------------------------------------------------*/
10030 /* genDjnz - generate decrement & jump if not zero instrucion      */
10031 /*-----------------------------------------------------------------*/
10032 static int genDjnz (iCode *ic, iCode *ifx)
10033 {
10034     symbol *lbl, *lbl1;
10035     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10036
10037     if (!ifx)
10038         return 0;
10039     
10040     /* if the if condition has a false label
10041        then we cannot save */
10042     if (IC_FALSE(ifx))
10043         return 0;
10044
10045     /* if the minus is not of the form 
10046        a = a - 1 */
10047     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10048         !IS_OP_LITERAL(IC_RIGHT(ic)))
10049         return 0;
10050
10051     if (operandLitValue(IC_RIGHT(ic)) != 1)
10052         return 0;
10053
10054     /* if the size of this greater than one then no
10055        saving */
10056     if (getSize(operandType(IC_RESULT(ic))) > 1)
10057         return 0;
10058
10059     /* otherwise we can save BIG */
10060     lbl = newiTempLabel(NULL);
10061     lbl1= newiTempLabel(NULL);
10062
10063     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10064     
10065     if (IS_AOP_PREG(IC_RESULT(ic))) {
10066         pic16_emitcode("dec","%s",
10067                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10068         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10069         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10070     } else {    
10071
10072
10073       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10074       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10075
10076       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10077       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10078
10079     }
10080 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10081 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10082 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10083 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10084
10085     
10086     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10087     ifx->generated = 1;
10088     return 1;
10089 }
10090
10091 /*-----------------------------------------------------------------*/
10092 /* genReceive - generate code for a receive iCode                  */
10093 /*-----------------------------------------------------------------*/
10094 static void genReceive (iCode *ic)
10095 {    
10096         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10097
10098         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10099                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10100                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10101
10102           int size = getSize(operandType(IC_RESULT(ic)));
10103           int offset =  pic16_fReturnSizePic - size;
10104
10105                 while (size--) {
10106                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10107                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10108                         offset++;
10109                 }
10110
10111                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10112
10113                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10114                 size = AOP_SIZE(IC_RESULT(ic));
10115                 offset = 0;
10116                 while (size--) {
10117                         pic16_emitcode ("pop","acc");
10118                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10119                 }
10120         } else {
10121                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10122
10123                 _G.accInUse++;
10124                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10125                 _G.accInUse--;
10126                 assignResultValue(IC_RESULT(ic));       
10127         }
10128
10129         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10130 }
10131
10132 /*-----------------------------------------------------------------*/
10133 /* genDummyRead - generate code for dummy read of volatiles        */
10134 /*-----------------------------------------------------------------*/
10135 static void
10136 genDummyRead (iCode * ic)
10137 {
10138   pic16_emitcode ("; genDummyRead","");
10139   pic16_emitcode ("; not implemented","");
10140
10141   ic = ic;
10142 }
10143
10144 /*-----------------------------------------------------------------*/
10145 /* genpic16Code - generate code for pic16 based controllers        */
10146 /*-----------------------------------------------------------------*/
10147 /*
10148  * At this point, ralloc.c has gone through the iCode and attempted
10149  * to optimize in a way suitable for a PIC. Now we've got to generate
10150  * PIC instructions that correspond to the iCode.
10151  *
10152  * Once the instructions are generated, we'll pass through both the
10153  * peep hole optimizer and the pCode optimizer.
10154  *-----------------------------------------------------------------*/
10155
10156 void genpic16Code (iCode *lic)
10157 {
10158     iCode *ic;
10159     int cln = 0;
10160
10161     lineHead = lineCurr = NULL;
10162
10163     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10164     pic16_addpBlock(pb);
10165
10166 #if 0
10167     /* if debug information required */
10168     if (options.debug && currFunc) {
10169       if (currFunc) {
10170         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10171         _G.debugLine = 1;
10172         if (IS_STATIC(currFunc->etype)) {
10173           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10174           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10175         } else {
10176           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10177           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10178         }
10179         _G.debugLine = 0;
10180       }
10181     }
10182 #endif
10183
10184 //    dumpiCode(lic);
10185
10186     for (ic = lic ; ic ; ic = ic->next ) {
10187
10188 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10189 //      DEBUGpic16_emitcode("; VR", "");
10190       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10191         if ( cln != ic->lineno ) {
10192             if ( options.debug ) {
10193                 _G.debugLine = 1;
10194                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10195                          FileBaseName(ic->filename),ic->lineno,
10196                          ic->level,ic->block);
10197                 _G.debugLine = 0;
10198             }
10199             pic16_addpCode2pBlock(pb,
10200                             pic16_newpCodeCSource(ic->lineno, 
10201                                             ic->filename, 
10202                                             printCLine(ic->filename, ic->lineno)));
10203
10204             cln = ic->lineno ;
10205         }
10206         /* if the result is marked as
10207            spilt and rematerializable or code for
10208            this has already been generated then
10209            do nothing */
10210         if (resultRemat(ic) || ic->generated ) 
10211             continue ;
10212         
10213         /* depending on the operation */
10214         switch (ic->op) {
10215         case '!' :
10216             pic16_genNot(ic);
10217             break;
10218             
10219         case '~' :
10220             pic16_genCpl(ic);
10221             break;
10222             
10223         case UNARYMINUS:
10224             genUminus (ic);
10225             break;
10226             
10227         case IPUSH:
10228             genIpush (ic);
10229             break;
10230             
10231         case IPOP:
10232             /* IPOP happens only when trying to restore a 
10233                spilt live range, if there is an ifx statement
10234                following this pop then the if statement might
10235                be using some of the registers being popped which
10236                would destroy the contents of the register so
10237                we need to check for this condition and handle it */
10238             if (ic->next            && 
10239                 ic->next->op == IFX &&
10240                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10241                 genIfx (ic->next,ic);
10242             else
10243                 genIpop (ic);
10244             break; 
10245             
10246         case CALL:
10247             genCall (ic);
10248             break;
10249             
10250         case PCALL:
10251             genPcall (ic);
10252             break;
10253             
10254         case FUNCTION:
10255             genFunction (ic);
10256             break;
10257             
10258         case ENDFUNCTION:
10259             genEndFunction (ic);
10260             break;
10261             
10262         case RETURN:
10263             genRet (ic);
10264             break;
10265             
10266         case LABEL:
10267             genLabel (ic);
10268             break;
10269             
10270         case GOTO:
10271             genGoto (ic);
10272             break;
10273             
10274         case '+' :
10275             pic16_genPlus (ic) ;
10276             break;
10277             
10278         case '-' :
10279             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10280                 pic16_genMinus (ic);
10281             break;
10282             
10283         case '*' :
10284             genMult (ic);
10285             break;
10286             
10287         case '/' :
10288             genDiv (ic) ;
10289             break;
10290             
10291         case '%' :
10292             genMod (ic);
10293             break;
10294             
10295         case '>' :
10296             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10297             break;
10298             
10299         case '<' :
10300             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10301             break;
10302             
10303         case LE_OP:
10304         case GE_OP:
10305         case NE_OP:
10306             
10307             /* note these two are xlated by algebraic equivalence
10308                during parsing SDCC.y */
10309             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10310                    "got '>=' or '<=' shouldn't have come here");
10311             break;      
10312             
10313         case EQ_OP:
10314             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10315             break;          
10316             
10317         case AND_OP:
10318             genAndOp (ic);
10319             break;
10320             
10321         case OR_OP:
10322             genOrOp (ic);
10323             break;
10324             
10325         case '^' :
10326             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10327             break;
10328             
10329         case '|' :
10330                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10331             break;
10332             
10333         case BITWISEAND:
10334             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10335             break;
10336             
10337         case INLINEASM:
10338             genInline (ic);
10339             break;
10340             
10341         case RRC:
10342             genRRC (ic);
10343             break;
10344             
10345         case RLC:
10346             genRLC (ic);
10347             break;
10348             
10349         case GETHBIT:
10350             genGetHbit (ic);
10351             break;
10352             
10353         case LEFT_OP:
10354             genLeftShift (ic);
10355             break;
10356             
10357         case RIGHT_OP:
10358             genRightShift (ic);
10359             break;
10360             
10361         case GET_VALUE_AT_ADDRESS:
10362             genPointerGet(ic);
10363             break;
10364             
10365         case '=' :
10366             if (POINTER_SET(ic))
10367                 genPointerSet(ic);
10368             else
10369                 genAssign(ic);
10370             break;
10371             
10372         case IFX:
10373             genIfx (ic,NULL);
10374             break;
10375             
10376         case ADDRESS_OF:
10377             genAddrOf (ic);
10378             break;
10379             
10380         case JUMPTABLE:
10381             genJumpTab (ic);
10382             break;
10383             
10384         case CAST:
10385             genCast (ic);
10386             break;
10387             
10388         case RECEIVE:
10389             genReceive(ic);
10390             break;
10391             
10392         case SEND:
10393               DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\tSEND",ic->op, ic->op);
10394
10395             addSet(&_G.sendSet,ic);
10396             break;
10397
10398         case DUMMY_READ_VOLATILE:
10399           genDummyRead (ic);
10400           break;
10401
10402         default :
10403             ic = ic;
10404         }
10405     }
10406
10407
10408     /* now we are ready to call the
10409        peep hole optimizer */
10410     if (!options.nopeep) {
10411       peepHole (&lineHead);
10412     }
10413     /* now do the actual printing */
10414     printLine (lineHead,codeOutFile);
10415
10416 #ifdef PCODE_DEBUG
10417     DFPRINTF((stderr,"printing pBlock\n\n"));
10418     pic16_printpBlock(stdout,pb);
10419 #endif
10420
10421     return;
10422 }
10423