]> git.gag.com Git - fw/sdcc/blob - src/pic16/gen.c
1f13393251bf1166da7bbd6cfa9dc64f711c2d96
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
81
82 /* this is the down and dirty file with all kinds of 
83    kludgy & hacky stuff. This is what it is all about
84    CODE GENERATION for a specific MCU . some of the
85    routines may be reusable, will have to see */
86
87 static char *zero = "#0x00";
88 static char *one  = "#0x01";
89 static char *spname = "sp";
90
91 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
92 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
93 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
94 static char **fReturn = fReturnpic16;
95
96 static char *accUse[] = {"a","b"};
97
98 //static short rbank = -1;
99
100 static struct {
101     short r0Pushed;
102     short r1Pushed;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108 } _G;
109
110 /* Resolved ifx structure. This structure stores information
111    about an iCode ifx that makes it easier to generate code.
112 */
113 typedef struct resolvedIfx {
114   symbol *lbl;     /* pointer to a label */
115   int condition;   /* true or false ifx */
116   int generated;   /* set true when the code associated with the ifx
117                     * is generated */
118 } resolvedIfx;
119
120 extern int pic16_ptrRegReq ;
121 extern int pic16_nRegs;
122 extern FILE *codeOutFile;
123 static void saverbank (int, iCode *,bool);
124
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
127
128 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
129 0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
131 0x07, 0x03, 0x01, 0x00};
132
133 static  pBlock *pb;
134
135 /*-----------------------------------------------------------------*/
136 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
137 /*                 exponent of 2 is returned, otherwise -1 is      */
138 /*                 returned.                                       */
139 /* note that this is similar to the function `powof2' in SDCCsymt  */
140 /* if(n == 2^y)                                                    */
141 /*   return y;                                                     */
142 /* return -1;                                                      */
143 /*-----------------------------------------------------------------*/
144 static int my_powof2 (unsigned long num)
145 {
146   if(num) {
147     if( (num & (num-1)) == 0) {
148       int nshifts = -1;
149       while(num) {
150         num>>=1;
151         nshifts++;
152       }
153       return nshifts;
154     }
155   }
156
157   return -1;
158 }
159
160 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
161 {
162
163   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
164                        line_no,
165                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
166                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
167                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
168                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
170                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                        ((result) ? AOP_SIZE(result) : 0));
172
173 }
174
175 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177
178   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                        line_no,
180                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
181                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
183                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
184                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
185                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186
187 }
188
189 void pic16_emitcomment (char *fmt, ...)
190 {
191     va_list ap;
192     char lb[INITIAL_INLINEASM];  
193     char *lbp = lb;
194
195     if(!pic16_debug_verbose)
196       return;
197
198     va_start(ap,fmt);   
199
200     lb[0] = ';';
201     vsprintf(lb+1,fmt,ap);
202
203     while (isspace(*lbp)) lbp++;
204
205     if (lbp && *lbp) 
206         lineCurr = (lineCurr ?
207                     connectLine(lineCurr,newLineNode(lb)) :
208                     (lineHead = newLineNode(lb)));
209     lineCurr->isInline = _G.inLine;
210     lineCurr->isDebug  = _G.debugLine;
211
212     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
213     va_end(ap);
214
215 //      fprintf(stderr, "%s\n", lb);
216 }
217
218 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
219 {
220     va_list ap;
221     char lb[INITIAL_INLINEASM];  
222     char *lbp = lb;
223
224     if(!pic16_debug_verbose)
225       return;
226
227     va_start(ap,fmt);   
228
229     if (inst && *inst) {
230         if (fmt && *fmt)
231             sprintf(lb,"%s\t",inst);
232         else
233             sprintf(lb,"%s",inst);
234         vsprintf(lb+(strlen(lb)),fmt,ap);
235     }  else
236         vsprintf(lb,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
248     va_end(ap);
249
250 //      fprintf(stderr, "%s\n", lb);
251 }
252
253 void pic16_emitpLabel(int key)
254 {
255   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
256 }
257
258 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
259 {
260
261   if(pcop)
262     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
263   else
264     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
265     
266 //    fprintf(stderr, "%s\n", pcop->name);
267 }
268
269 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
270 {
271
272   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
273
274 }
275
276
277 #if 1
278 #define pic16_emitcode  DEBUGpic16_emitcode
279 #else
280 /*-----------------------------------------------------------------*/
281 /* pic16_emitcode - writes the code into a file : for now it is simple    */
282 /*-----------------------------------------------------------------*/
283 void pic16_emitcode (char *inst,char *fmt, ...)
284 {
285     va_list ap;
286     char lb[INITIAL_INLINEASM];  
287     char *lbp = lb;
288
289     va_start(ap,fmt);   
290
291     if (inst && *inst) {
292         if (fmt && *fmt)
293             sprintf(lb,"%s\t",inst);
294         else
295             sprintf(lb,"%s",inst);
296         vsprintf(lb+(strlen(lb)),fmt,ap);
297     }  else
298         vsprintf(lb,fmt,ap);
299
300     while (isspace(*lbp)) lbp++;
301
302     if (lbp && *lbp) 
303         lineCurr = (lineCurr ?
304                     connectLine(lineCurr,newLineNode(lb)) :
305                     (lineHead = newLineNode(lb)));
306     lineCurr->isInline = _G.inLine;
307     lineCurr->isDebug  = _G.debugLine;
308
309 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
310
311 //    if(pic16_debug_verbose)
312 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
313
314     va_end(ap);
315 }
316 #endif
317
318
319 /*-----------------------------------------------------------------*/
320 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
321 /*-----------------------------------------------------------------*/
322 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
323 {
324     bool r0iu = FALSE , r1iu = FALSE;
325     bool r0ou = FALSE , r1ou = FALSE;
326
327         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
328
329     /* the logic: if r0 & r1 used in the instruction
330     then we are in trouble otherwise */
331
332     /* first check if r0 & r1 are used by this
333     instruction, in which case we are in trouble */
334     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
335         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
336     {
337         goto endOfWorld;      
338     }
339
340     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
341     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
342
343     /* if no usage of r0 then return it */
344     if (!r0iu && !r0ou) {
345         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
346         (*aopp)->type = AOP_R0;
347         
348         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
349     }
350
351     /* if no usage of r1 then return it */
352     if (!r1iu && !r1ou) {
353         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
354         (*aopp)->type = AOP_R1;
355
356         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
357     }    
358
359     /* now we know they both have usage */
360     /* if r0 not used in this instruction */
361     if (!r0iu) {
362         /* push it if not already pushed */
363         if (!_G.r0Pushed) {
364           //pic16_emitcode ("push","%s",
365           //          pic16_regWithIdx(R0_IDX)->dname);
366             _G.r0Pushed++ ;
367         }
368         
369         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370         (*aopp)->type = AOP_R0;
371
372         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
373     }
374
375     /* if r1 not used then */
376
377     if (!r1iu) {
378         /* push it if not already pushed */
379         if (!_G.r1Pushed) {
380           //pic16_emitcode ("push","%s",
381           //          pic16_regWithIdx(R1_IDX)->dname);
382             _G.r1Pushed++ ;
383         }
384         
385         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
386         (*aopp)->type = AOP_R1;
387         return pic16_regWithIdx(R1_IDX);
388     }
389
390 endOfWorld :
391     /* I said end of world but not quite end of world yet */
392     /* if this is a result then we can push it on the stack*/
393     if (result) {
394         (*aopp)->type = AOP_STK;    
395         return NULL;
396     }
397
398     /* other wise this is true end of the world */
399     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
400            "getFreePtr should never reach here");
401     exit(0);
402 }
403
404 /*-----------------------------------------------------------------*/
405 /* newAsmop - creates a new asmOp                                  */
406 /*-----------------------------------------------------------------*/
407 static asmop *newAsmop (short type)
408 {
409     asmop *aop;
410
411     aop = Safe_calloc(1,sizeof(asmop));
412     aop->type = type;
413     return aop;
414 }
415
416 static void genSetDPTR(int n)
417 {
418     if (!n)
419     {
420         pic16_emitcode(";", "Select standard DPTR");
421         pic16_emitcode("mov", "dps, #0x00");
422     }
423     else
424     {
425         pic16_emitcode(";", "Select alternate DPTR");
426         pic16_emitcode("mov", "dps, #0x01");
427     }
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* resolveIfx - converts an iCode ifx into a form more useful for  */
432 /*              generating code                                    */
433 /*-----------------------------------------------------------------*/
434 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
435 {
436   if(!resIfx) 
437     return;
438
439   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
440
441   resIfx->condition = 1;    /* assume that the ifx is true */
442   resIfx->generated = 0;    /* indicate that the ifx has not been used */
443
444   if(!ifx) {
445     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
446 /*
447     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
448                         __FUNCTION__,__LINE__,resIfx->lbl->key);
449 */
450   } else {
451     if(IC_TRUE(ifx)) {
452       resIfx->lbl = IC_TRUE(ifx);
453     } else {
454       resIfx->lbl = IC_FALSE(ifx);
455       resIfx->condition = 0;
456     }
457 /*
458     if(IC_TRUE(ifx)) 
459       DEBUGpic16_emitcode("; ***","ifx true is non-null");
460     if(IC_FALSE(ifx)) 
461       DEBUGpic16_emitcode("; ***","ifx false is non-null");
462 */
463   }
464
465   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
466
467 }
468 /*-----------------------------------------------------------------*/
469 /* pointerCode - returns the code for a pointer type               */
470 /*-----------------------------------------------------------------*/
471 static int pointerCode (sym_link *etype)
472 {
473
474     return PTR_TYPE(SPEC_OCLS(etype));
475
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* aopForSym - for a true symbol                                   */
480 /*-----------------------------------------------------------------*/
481 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
482 {
483     asmop *aop;
484     memmap *space= SPEC_OCLS(sym->etype);
485
486     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
487     /* if already has one */
488     if (sym->aop) {
489             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
490         return sym->aop;
491     }
492
493     /* assign depending on the storage class */
494     /* if it is on the stack or indirectly addressable */
495     /* space we need to assign either r0 or r1 to it   */    
496     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
497         sym->aop = aop = newAsmop(0);
498         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
499         aop->size = getSize(sym->type);
500
501         /* now assign the address of the variable to 
502         the pointer register */
503         if (aop->type != AOP_STK) {
504
505             if (sym->onStack) {
506                     if ( _G.accInUse )
507                         pic16_emitcode("push","acc");
508
509                     pic16_emitcode("mov","a,_bp");
510                     pic16_emitcode("add","a,#0x%02x",
511                              ((sym->stack < 0) ?
512                               ((char)(sym->stack - _G.nRegsSaved )) :
513                               ((char)sym->stack)) & 0xff);
514                     pic16_emitcode("mov","%s,a",
515                              aop->aopu.aop_ptr->name);
516
517                     if ( _G.accInUse )
518                         pic16_emitcode("pop","acc");
519             } else
520                 pic16_emitcode("mov","%s,#%s",
521                          aop->aopu.aop_ptr->name,
522                          sym->rname);
523             aop->paged = space->paged;
524         } else
525             aop->aopu.aop_stk = sym->stack;
526         return aop;
527     }
528     
529     if (sym->onStack && options.stack10bit)
530     {
531         /* It's on the 10 bit stack, which is located in
532          * far data space.
533          */
534          
535       //DEBUGpic16_emitcode(";","%d",__LINE__);
536
537         if ( _G.accInUse )
538                 pic16_emitcode("push","acc");
539
540         pic16_emitcode("mov","a,_bp");
541         pic16_emitcode("add","a,#0x%02x",
542                  ((sym->stack < 0) ?
543                    ((char)(sym->stack - _G.nRegsSaved )) :
544                    ((char)sym->stack)) & 0xff);
545         
546         genSetDPTR(1);
547         pic16_emitcode ("mov","dpx1,#0x40");
548         pic16_emitcode ("mov","dph1,#0x00");
549         pic16_emitcode ("mov","dpl1, a");
550         genSetDPTR(0);
551         
552         if ( _G.accInUse )
553             pic16_emitcode("pop","acc");
554             
555         sym->aop = aop = newAsmop(AOP_DPTR2);
556         aop->size = getSize(sym->type); 
557         return aop;
558     }
559
560     //DEBUGpic16_emitcode(";","%d",__LINE__);
561     /* if in bit space */
562     if (IN_BITSPACE(space)) {
563         sym->aop = aop = newAsmop (AOP_CRY);
564         aop->aopu.aop_dir = sym->rname ;
565         aop->size = getSize(sym->type);
566         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
567         return aop;
568     }
569     /* if it is in direct space */
570     if (IN_DIRSPACE(space)) {
571         sym->aop = aop = newAsmop (AOP_DIR);
572         aop->aopu.aop_dir = sym->rname ;
573         aop->size = getSize(sym->type);
574         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
575         return aop;
576     }
577
578     /* special case for a function */
579     if (IS_FUNC(sym->type)) {   
580         sym->aop = aop = newAsmop(AOP_IMMD);    
581         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
582         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
583         strcpy(aop->aopu.aop_immd,sym->rname);
584         aop->size = FPTRSIZE; 
585         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
586         return aop;
587     }
588
589
590     /* only remaining is far space */
591     /* in which case DPTR gets the address */
592     sym->aop = aop = newAsmop(AOP_PCODE);
593
594     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
595     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
596     PCOI(aop->aopu.pcop)->index = 0;
597
598     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
599                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
600
601     pic16_allocDirReg (IC_LEFT(ic));
602
603     aop->size = FPTRSIZE; 
604 /*
605     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
606     sym->aop = aop = newAsmop(AOP_DPTR);
607     pic16_emitcode ("mov","dptr,#%s", sym->rname);
608     aop->size = getSize(sym->type);
609
610     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
611 */
612
613     /* if it is in code space */
614     if (IN_CODESPACE(space))
615         aop->code = 1;
616
617     return aop;     
618 }
619
620 /*-----------------------------------------------------------------*/
621 /* aopForRemat - rematerialzes an object                           */
622 /*-----------------------------------------------------------------*/
623 static asmop *aopForRemat (operand *op) // x symbol *sym)
624 {
625   symbol *sym = OP_SYMBOL(op);
626   iCode *ic = NULL;
627   asmop *aop = newAsmop(AOP_PCODE);
628   int val = 0;
629   int offset = 0;
630
631   ic = sym->rematiCode;
632
633   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
634   if(IS_OP_POINTER(op)) {
635     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
636   }
637   for (;;) {
638     if (ic->op == '+') {
639       val += (int) operandLitValue(IC_RIGHT(ic));
640     } else if (ic->op == '-') {
641       val -= (int) operandLitValue(IC_RIGHT(ic));
642     } else
643       break;
644         
645     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
646   }
647
648   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
649   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
650 #if 0
651   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
652 #else
653   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
654 #endif
655   PCOI(aop->aopu.pcop)->index = val;
656
657   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
658                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
659 #if 0
660                       val, IS_PTR_CONST(operandType(op)));
661 #else
662                       val, IS_CODEPTR(operandType(op)));
663 #endif
664
665   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
666
667   pic16_allocDirReg (IC_LEFT(ic));
668
669   return aop;        
670 }
671
672 static int aopIdx (asmop *aop, int offset)
673 {
674   if(!aop)
675     return -1;
676
677   if(aop->type !=  AOP_REG)
678     return -2;
679         
680   return aop->aopu.aop_reg[offset]->rIdx;
681
682 }
683 /*-----------------------------------------------------------------*/
684 /* regsInCommon - two operands have some registers in common       */
685 /*-----------------------------------------------------------------*/
686 static bool regsInCommon (operand *op1, operand *op2)
687 {
688     symbol *sym1, *sym2;
689     int i;
690
691     /* if they have registers in common */
692     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
693         return FALSE ;
694
695     sym1 = OP_SYMBOL(op1);
696     sym2 = OP_SYMBOL(op2);
697
698     if (sym1->nRegs == 0 || sym2->nRegs == 0)
699         return FALSE ;
700
701     for (i = 0 ; i < sym1->nRegs ; i++) {
702         int j;
703         if (!sym1->regs[i])
704             continue ;
705
706         for (j = 0 ; j < sym2->nRegs ;j++ ) {
707             if (!sym2->regs[j])
708                 continue ;
709
710             if (sym2->regs[j] == sym1->regs[i])
711                 return TRUE ;
712         }
713     }
714
715     return FALSE ;
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* operandsEqu - equivalent                                        */
720 /*-----------------------------------------------------------------*/
721 static bool operandsEqu ( operand *op1, operand *op2)
722 {
723     symbol *sym1, *sym2;
724
725     /* if they not symbols */
726     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
727         return FALSE;
728
729     sym1 = OP_SYMBOL(op1);
730     sym2 = OP_SYMBOL(op2);
731
732     /* if both are itemps & one is spilt
733        and the other is not then false */
734     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
735         sym1->isspilt != sym2->isspilt )
736         return FALSE ;
737
738     /* if they are the same */
739     if (sym1 == sym2)
740         return TRUE ;
741
742     if (strcmp(sym1->rname,sym2->rname) == 0)
743         return TRUE;
744
745
746     /* if left is a tmp & right is not */
747     if (IS_ITEMP(op1)  && 
748         !IS_ITEMP(op2) &&
749         sym1->isspilt  &&
750         (sym1->usl.spillLoc == sym2))
751         return TRUE;
752
753     if (IS_ITEMP(op2)  && 
754         !IS_ITEMP(op1) &&
755         sym2->isspilt  &&
756         sym1->level > 0 &&
757         (sym2->usl.spillLoc == sym1))
758         return TRUE ;
759
760     return FALSE ;
761 }
762
763 /*-----------------------------------------------------------------*/
764 /* pic16_sameRegs - two asmops have the same registers                   */
765 /*-----------------------------------------------------------------*/
766 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
767 {
768     int i;
769
770     if (aop1 == aop2)
771         return TRUE ;
772
773     if (aop1->type != AOP_REG ||
774         aop2->type != AOP_REG )
775         return FALSE ;
776
777     if (aop1->size != aop2->size )
778         return FALSE ;
779
780     for (i = 0 ; i < aop1->size ; i++ )
781         if (aop1->aopu.aop_reg[i] !=
782             aop2->aopu.aop_reg[i] )
783             return FALSE ;
784
785     return TRUE ;
786 }
787
788 /*-----------------------------------------------------------------*/
789 /* pic16_aopOp - allocates an asmop for an operand  :                    */
790 /*-----------------------------------------------------------------*/
791 void pic16_aopOp (operand *op, iCode *ic, bool result)
792 {
793     asmop *aop;
794     symbol *sym;
795     int i;
796
797     if (!op)
798         return ;
799
800 //      DEBUGpic16_emitcode(";","%d",__LINE__);
801
802     /* if this a literal */
803     if (IS_OP_LITERAL(op)) {
804         op->aop = aop = newAsmop(AOP_LIT);
805         aop->aopu.aop_lit = op->operand.valOperand;
806         aop->size = getSize(operandType(op));
807         return;
808     }
809
810     {
811       sym_link *type = operandType(op);
812 #if 0
813       if(IS_PTR_CONST(type))
814 #else
815       if(IS_CODEPTR(type))
816 #endif
817         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
818     }
819
820     /* if already has a asmop then continue */
821     if (op->aop)
822         return ;
823
824     /* if the underlying symbol has a aop */
825     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
826       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
827         op->aop = OP_SYMBOL(op)->aop;
828         return;
829     }
830
831     /* if this is a true symbol */
832     if (IS_TRUE_SYMOP(op)) {    
833         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
834       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
835       return ;
836     }
837
838     /* this is a temporary : this has
839     only four choices :
840     a) register
841     b) spillocation
842     c) rematerialize 
843     d) conditional   
844     e) can be a return use only */
845
846     sym = OP_SYMBOL(op);
847
848         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
849     /* if the type is a conditional */
850     if (sym->regType == REG_CND) {
851         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
852         aop->size = 0;
853         return;
854     }
855
856     /* if it is spilt then two situations
857     a) is rematerialize 
858     b) has a spill location */
859     if (sym->isspilt || sym->nRegs == 0) {
860
861       DEBUGpic16_emitcode(";","%d",__LINE__);
862         /* rematerialize it NOW */
863         if (sym->remat) {
864
865             sym->aop = op->aop = aop =
866                                       aopForRemat (op);
867             aop->size = getSize(sym->type);
868             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
869             return;
870         }
871
872         if (sym->accuse) {
873             int i;
874             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
875             aop->size = getSize(sym->type);
876             for ( i = 0 ; i < 2 ; i++ )
877                 aop->aopu.aop_str[i] = accUse[i];
878             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
879             return;  
880         }
881
882         if (sym->ruonly ) {
883           /*
884           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
885           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
886           //pic16_allocDirReg (IC_LEFT(ic));
887           aop->size = getSize(sym->type);
888           */
889
890           unsigned i;
891
892           aop = op->aop = sym->aop = newAsmop(AOP_STR);
893           aop->size = getSize(sym->type);
894           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
895             aop->aopu.aop_str[i] = fReturn[i];
896
897           DEBUGpic16_emitcode(";","%d",__LINE__);
898           return;
899         }
900
901         /* else spill location  */
902         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
903             /* force a new aop if sizes differ */
904             sym->usl.spillLoc->aop = NULL;
905         }
906         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
907                             __FUNCTION__,__LINE__,
908                             sym->usl.spillLoc->rname,
909                             sym->rname, sym->usl.spillLoc->offset);
910
911         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
912         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
913         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
914                                           getSize(sym->type), 
915                                           sym->usl.spillLoc->offset);
916         aop->size = getSize(sym->type);
917
918         return;
919     }
920
921     {
922       sym_link *type = operandType(op);
923 #if 0
924       if(IS_PTR_CONST(type)) 
925 #else
926       if(IS_CODEPTR(type)) 
927 #endif
928         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
929     }
930
931     /* must be in a register */
932     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
933     sym->aop = op->aop = aop = newAsmop(AOP_REG);
934     aop->size = sym->nRegs;
935     for ( i = 0 ; i < sym->nRegs ;i++)
936         aop->aopu.aop_reg[i] = sym->regs[i];
937 }
938
939 /*-----------------------------------------------------------------*/
940 /* pic16_freeAsmop - free up the asmop given to an operand               */
941 /*----------------------------------------------------------------*/
942 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
943 {   
944     asmop *aop ;
945
946     if (!op)
947         aop = aaop;
948     else 
949         aop = op->aop;
950
951     if (!aop)
952         return ;
953
954     if (aop->freed)
955         goto dealloc; 
956
957     aop->freed = 1;
958
959     /* depending on the asmop type only three cases need work AOP_RO
960        , AOP_R1 && AOP_STK */
961 #if 0
962     switch (aop->type) {
963         case AOP_R0 :
964             if (_G.r0Pushed ) {
965                 if (pop) {
966                     pic16_emitcode ("pop","ar0");     
967                     _G.r0Pushed--;
968                 }
969             }
970             bitVectUnSetBit(ic->rUsed,R0_IDX);
971             break;
972
973         case AOP_R1 :
974             if (_G.r1Pushed ) {
975                 if (pop) {
976                     pic16_emitcode ("pop","ar1");
977                     _G.r1Pushed--;
978                 }
979             }
980             bitVectUnSetBit(ic->rUsed,R1_IDX);          
981             break;
982
983         case AOP_STK :
984         {
985             int sz = aop->size;    
986             int stk = aop->aopu.aop_stk + aop->size;
987             bitVectUnSetBit(ic->rUsed,R0_IDX);
988             bitVectUnSetBit(ic->rUsed,R1_IDX);          
989
990             getFreePtr(ic,&aop,FALSE);
991             
992             if (options.stack10bit)
993             {
994                 /* I'm not sure what to do here yet... */
995                 /* #STUB */
996                 fprintf(stderr, 
997                         "*** Warning: probably generating bad code for "
998                         "10 bit stack mode.\n");
999             }
1000             
1001             if (stk) {
1002                 pic16_emitcode ("mov","a,_bp");
1003                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1004                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1005             } else {
1006                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1007             }
1008
1009             while (sz--) {
1010                 pic16_emitcode("pop","acc");
1011                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1012                 if (!sz) break;
1013                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1014             }
1015             op->aop = aop;
1016             pic16_freeAsmop(op,NULL,ic,TRUE);
1017             if (_G.r0Pushed) {
1018                 pic16_emitcode("pop","ar0");
1019                 _G.r0Pushed--;
1020             }
1021
1022             if (_G.r1Pushed) {
1023                 pic16_emitcode("pop","ar1");
1024                 _G.r1Pushed--;
1025             }       
1026         }
1027     }
1028 #endif
1029
1030 dealloc:
1031     /* all other cases just dealloc */
1032     if (op ) {
1033         op->aop = NULL;
1034         if (IS_SYMOP(op)) {
1035             OP_SYMBOL(op)->aop = NULL;    
1036             /* if the symbol has a spill */
1037             if (SPIL_LOC(op))
1038                 SPIL_LOC(op)->aop = NULL;
1039         }
1040     }
1041 }
1042
1043 /*-----------------------------------------------------------------*/
1044 /* pic16_aopGet - for fetching value of the aop                          */
1045 /*-----------------------------------------------------------------*/
1046 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1047 {
1048     char *s = buffer ;
1049     char *rs;
1050
1051     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1052     /* offset is greater than
1053     size then zero */
1054     if (offset > (aop->size - 1) &&
1055         aop->type != AOP_LIT)
1056         return zero;
1057
1058     /* depending on type */
1059     switch (aop->type) {
1060         
1061     case AOP_R0:
1062     case AOP_R1:
1063         DEBUGpic16_emitcode(";","%d",__LINE__);
1064         /* if we need to increment it */       
1065         while (offset > aop->coff) {        
1066             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1067             aop->coff++;
1068         }
1069         
1070         while (offset < aop->coff) {
1071             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072             aop->coff--;
1073         }
1074         
1075         aop->coff = offset ;
1076         if (aop->paged) {
1077             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1078             return (dname ? "acc" : "a");
1079         }       
1080         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1081         rs = Safe_calloc(1,strlen(s)+1);
1082         strcpy(rs,s);   
1083         return rs;
1084         
1085     case AOP_DPTR:
1086     case AOP_DPTR2:
1087         DEBUGpic16_emitcode(";","%d",__LINE__);
1088     if (aop->type == AOP_DPTR2)
1089     {
1090         genSetDPTR(1);
1091     }
1092     
1093         while (offset > aop->coff) {
1094             pic16_emitcode ("inc","dptr");
1095             aop->coff++;
1096         }
1097         
1098         while (offset < aop->coff) {        
1099             pic16_emitcode("lcall","__decdptr");
1100             aop->coff--;
1101         }
1102         
1103         aop->coff = offset;
1104         if (aop->code) {
1105             pic16_emitcode("clr","a");
1106             pic16_emitcode("movc","a,@a+dptr");
1107         }
1108     else {
1109             pic16_emitcode("movx","a,@dptr");
1110     }
1111             
1112     if (aop->type == AOP_DPTR2)
1113     {
1114         genSetDPTR(0);
1115     }
1116             
1117     return (dname ? "acc" : "a");
1118         
1119         
1120     case AOP_IMMD:
1121         if (bit16) 
1122             sprintf (s,"%s",aop->aopu.aop_immd);
1123         else
1124             if (offset) 
1125                 sprintf(s,"(%s >> %d)",
1126                         aop->aopu.aop_immd,
1127                         offset*8);
1128             else
1129                 sprintf(s,"%s",
1130                         aop->aopu.aop_immd);
1131         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1132         rs = Safe_calloc(1,strlen(s)+1);
1133         strcpy(rs,s);   
1134         return rs;
1135         
1136     case AOP_DIR:
1137       if (offset) {
1138         sprintf(s,"(%s + %d)",
1139                 aop->aopu.aop_dir,
1140                 offset);
1141         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1142       } else
1143             sprintf(s,"%s",aop->aopu.aop_dir);
1144         rs = Safe_calloc(1,strlen(s)+1);
1145         strcpy(rs,s);   
1146         return rs;
1147         
1148     case AOP_REG:
1149       //if (dname) 
1150       //    return aop->aopu.aop_reg[offset]->dname;
1151       //else
1152             return aop->aopu.aop_reg[offset]->name;
1153         
1154     case AOP_CRY:
1155       //pic16_emitcode(";","%d",__LINE__);
1156       return aop->aopu.aop_dir;
1157         
1158     case AOP_ACC:
1159         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1160         return "AOP_accumulator_bug";
1161
1162     case AOP_LIT:
1163         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1164         rs = Safe_calloc(1,strlen(s)+1);
1165         strcpy(rs,s);   
1166         return rs;
1167         
1168     case AOP_STR:
1169         aop->coff = offset ;
1170         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1171             dname)
1172             return "acc";
1173         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1174         
1175         return aop->aopu.aop_str[offset];
1176         
1177     case AOP_PCODE:
1178       {
1179         pCodeOp *pcop = aop->aopu.pcop;
1180         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1181         if(pcop->name) {
1182           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1183           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1184           sprintf(s,"%s", pcop->name);
1185         } else
1186           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1187
1188       }
1189       rs = Safe_calloc(1,strlen(s)+1);
1190       strcpy(rs,s);   
1191       return rs;
1192
1193     }
1194
1195     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1196            "aopget got unsupported aop->type");
1197     exit(0);
1198 }
1199
1200
1201 /*-----------------------------------------------------------------*/
1202 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1203 /*-----------------------------------------------------------------*/
1204 pCodeOp *pic16_popGetTempReg(void)
1205 {
1206
1207   pCodeOp *pcop;
1208
1209   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1210   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1211     PCOR(pcop)->r->wasUsed=1;
1212     PCOR(pcop)->r->isFree=0;
1213   }
1214
1215   return pcop;
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1220 /*-----------------------------------------------------------------*/
1221 void pic16_popReleaseTempReg(pCodeOp *pcop)
1222 {
1223
1224   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1225     PCOR(pcop)->r->isFree = 1;
1226
1227 }
1228 /*-----------------------------------------------------------------*/
1229 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1230 /*-----------------------------------------------------------------*/
1231 pCodeOp *pic16_popGetLabel(unsigned int key)
1232 {
1233
1234   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1235
1236   if(key>max_key)
1237     max_key = key;
1238
1239   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* pic16_popCopyReg - copy a pcode operator                              */
1244 /*-----------------------------------------------------------------*/
1245 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1246 {
1247   pCodeOpReg *pcor;
1248
1249   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1250   pcor->pcop.type = pc->pcop.type;
1251   if(pc->pcop.name) {
1252     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1253       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1254   } else
1255     pcor->pcop.name = NULL;
1256
1257   pcor->r = pc->r;
1258   pcor->rIdx = pc->rIdx;
1259   pcor->r->wasUsed=1;
1260
1261   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1262
1263   return PCOP(pcor);
1264 }
1265
1266 /*-----------------------------------------------------------------*/
1267 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1268 /*-----------------------------------------------------------------*/
1269 pCodeOp *pic16_popGetLit(unsigned int lit)
1270 {
1271   return pic16_newpCodeOpLit(lit);
1272 }
1273
1274 /*-----------------------------------------------------------------*/
1275 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1276 /*-----------------------------------------------------------------*/
1277 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1278 {
1279   return pic16_newpCodeOpLit2(lit, arg2);
1280 }
1281
1282
1283 /*-----------------------------------------------------------------*/
1284 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1285 /*-----------------------------------------------------------------*/
1286 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1287 {
1288
1289   return pic16_newpCodeOpImmd(name, offset,index, 0);
1290 }
1291
1292
1293 /*-----------------------------------------------------------------*/
1294 /* pic16_popGet - asm operator to pcode operator conversion              */
1295 /*-----------------------------------------------------------------*/
1296 pCodeOp *pic16_popGetWithString(char *str)
1297 {
1298   pCodeOp *pcop;
1299
1300
1301   if(!str) {
1302     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1303     exit (1);
1304   }
1305
1306   pcop = pic16_newpCodeOp(str,PO_STR);
1307
1308   return pcop;
1309 }
1310
1311 /*-----------------------------------------------------------------*/
1312 /* pic16_popRegFromString -                                        */
1313 /*-----------------------------------------------------------------*/
1314 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1315 {
1316
1317   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1318   pcop->type = PO_DIR;
1319
1320   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1321 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1322
1323   if(!str)
1324     str = "BAD_STRING";
1325
1326   pcop->name = Safe_calloc(1,strlen(str)+1);
1327   strcpy(pcop->name,str);
1328
1329   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1330
1331   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1332   if(PCOR(pcop)->r == NULL) {
1333 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1334 //              __FUNCTION__, __LINE__, str, size, offset);
1335     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1336
1337         //fprintf(stderr, "allocating new register -> %s\n", str);
1338
1339     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1340   } else {
1341     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1342   }
1343   PCOR(pcop)->instance = offset;
1344
1345   return pcop;
1346 }
1347
1348 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1349 {
1350   pCodeOp *pcop;
1351
1352 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1353
1354         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1355         PCOR(pcop)->rIdx = rIdx;
1356         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1357         PCOR(pcop)->r->isFree = 0;
1358         PCOR(pcop)->r->wasUsed = 1;
1359
1360         pcop->type = PCOR(pcop)->r->pc_type;
1361
1362   return pcop;
1363 }
1364
1365 /*---------------------------------------------------------------------------------*/
1366 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1367 /*                 VR 030601                                                       */
1368 /*---------------------------------------------------------------------------------*/
1369 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1370 {
1371   pCodeOpReg2 *pcop2;
1372   pCodeOp *temp;
1373   
1374         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1375
1376         /* comment the following check, so errors to throw up */
1377 //      if(!pcop2)return NULL;
1378
1379         temp = pic16_popGet(aop_dst, offset);
1380         pcop2->pcop2 = temp;
1381         
1382   return PCOP(pcop2);
1383 }
1384
1385 /*---------------------------------------------------------------------------------*/
1386 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1387 /*                     movff instruction                                           */
1388 /*---------------------------------------------------------------------------------*/
1389 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1390 {
1391   pCodeOpReg2 *pcop2;
1392
1393         if(!noalloc) {
1394                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1395                 pcop2->pcop2 = pic16_popCopyReg(dst);
1396         } else {
1397                 /* the pCodeOp may be already allocated */
1398                 pcop2 = (pCodeOpReg2 *)(src);
1399                 pcop2->pcop2 = (pCodeOp *)(dst);
1400         }
1401
1402   return PCOP(pcop2);
1403 }
1404
1405
1406 /*-----------------------------------------------------------------*/
1407 /* pic16_popGet - asm operator to pcode operator conversion              */
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1410 {
1411   //char *s = buffer ;
1412     //char *rs;
1413
1414     pCodeOp *pcop;
1415
1416     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1417     /* offset is greater than
1418     size then zero */
1419
1420     if (offset > (aop->size - 1) &&
1421         aop->type != AOP_LIT)
1422       return NULL;  //zero;
1423
1424     /* depending on type */
1425     switch (aop->type) {
1426         
1427     case AOP_R0:
1428     case AOP_R1:
1429     case AOP_DPTR:
1430     case AOP_DPTR2:
1431     case AOP_ACC:
1432         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1433         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1434         return NULL;
1435         
1436     case AOP_IMMD:
1437       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1438       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1439
1440     case AOP_DIR:
1441       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1442       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1443         
1444     case AOP_REG:
1445       {
1446         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1447
1448         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1449         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1450         PCOR(pcop)->rIdx = rIdx;
1451         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1452         PCOR(pcop)->r->wasUsed=1;
1453         PCOR(pcop)->r->isFree=0;
1454
1455         PCOR(pcop)->instance = offset;
1456         pcop->type = PCOR(pcop)->r->pc_type;
1457         //rs = aop->aopu.aop_reg[offset]->name;
1458         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1459         return pcop;
1460       }
1461
1462     case AOP_CRY:
1463         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1464
1465       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1466       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1467       //if(PCOR(pcop)->r == NULL)
1468       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1469       return pcop;
1470         
1471     case AOP_LIT:
1472         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1473       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1474
1475     case AOP_STR:
1476       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1477       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1478
1479       /*
1480       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1481       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1482       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1483       pcop->type = PCOR(pcop)->r->pc_type;
1484       pcop->name = PCOR(pcop)->r->name;
1485
1486       return pcop;
1487       */
1488
1489     case AOP_PCODE:
1490       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1491                           __LINE__, 
1492                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1493       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1494       PCOI(pcop)->offset = offset;
1495       return pcop;
1496     }
1497
1498     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1499            "pic16_popGet got unsupported aop->type");
1500     exit(0);
1501 }
1502 /*-----------------------------------------------------------------*/
1503 /* pic16_aopPut - puts a string for a aop                                */
1504 /*-----------------------------------------------------------------*/
1505 void pic16_aopPut (asmop *aop, char *s, int offset)
1506 {
1507     char *d = buffer ;
1508     symbol *lbl ;
1509
1510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1511
1512     if (aop->size && offset > ( aop->size - 1)) {
1513         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1514                "pic16_aopPut got offset > aop->size");
1515         exit(0);
1516     }
1517
1518     /* will assign value to value */
1519     /* depending on where it is ofcourse */
1520     switch (aop->type) {
1521     case AOP_DIR:
1522       if (offset) {
1523         sprintf(d,"(%s + %d)",
1524                 aop->aopu.aop_dir,offset);
1525         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1526
1527       } else
1528             sprintf(d,"%s",aop->aopu.aop_dir);
1529         
1530         if (strcmp(d,s)) {
1531           DEBUGpic16_emitcode(";","%d",__LINE__);
1532           if(strcmp(s,"W"))
1533             pic16_emitcode("movf","%s,w",s);
1534           pic16_emitcode("movwf","%s",d);
1535
1536           if(strcmp(s,"W")) {
1537             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1538             if(offset >= aop->size) {
1539               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1540               break;
1541             } else
1542               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1543           }
1544
1545           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1546
1547
1548         }
1549         break;
1550         
1551     case AOP_REG:
1552       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1553         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1554           /*
1555             if (*s == '@'           ||
1556                 strcmp(s,"r0") == 0 ||
1557                 strcmp(s,"r1") == 0 ||
1558                 strcmp(s,"r2") == 0 ||
1559                 strcmp(s,"r3") == 0 ||
1560                 strcmp(s,"r4") == 0 ||
1561                 strcmp(s,"r5") == 0 ||
1562                 strcmp(s,"r6") == 0 || 
1563                 strcmp(s,"r7") == 0 )
1564                 pic16_emitcode("mov","%s,%s  ; %d",
1565                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1566             else
1567           */
1568
1569           if(strcmp(s,"W")==0 )
1570             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1571
1572           pic16_emitcode("movwf","%s",
1573                    aop->aopu.aop_reg[offset]->name);
1574
1575           if(strcmp(s,zero)==0) {
1576             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1577
1578           } else if(strcmp(s,"W")==0) {
1579             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1580             pcop->type = PO_GPR_REGISTER;
1581
1582             PCOR(pcop)->rIdx = -1;
1583             PCOR(pcop)->r = NULL;
1584
1585             DEBUGpic16_emitcode(";","%d",__LINE__);
1586             pcop->name = Safe_strdup(s);
1587             pic16_emitpcode(POC_MOVFW,pcop);
1588             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1589           } else if(strcmp(s,one)==0) {
1590             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1591             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1592           } else {
1593             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1594           }
1595         }
1596         break;
1597         
1598     case AOP_DPTR:
1599     case AOP_DPTR2:
1600     
1601     if (aop->type == AOP_DPTR2)
1602     {
1603         genSetDPTR(1);
1604     }
1605     
1606         if (aop->code) {
1607             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608                    "pic16_aopPut writting to code space");
1609             exit(0);
1610         }
1611         
1612         while (offset > aop->coff) {
1613             aop->coff++;
1614             pic16_emitcode ("inc","dptr");
1615         }
1616         
1617         while (offset < aop->coff) {
1618             aop->coff-- ;
1619             pic16_emitcode("lcall","__decdptr");
1620         }
1621         
1622         aop->coff = offset;
1623         
1624         /* if not in accumulater */
1625         MOVA(s);        
1626         
1627         pic16_emitcode ("movx","@dptr,a");
1628         
1629     if (aop->type == AOP_DPTR2)
1630     {
1631         genSetDPTR(0);
1632     }
1633         break;
1634         
1635     case AOP_R0:
1636     case AOP_R1:
1637         while (offset > aop->coff) {
1638             aop->coff++;
1639             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1640         }
1641         while (offset < aop->coff) {
1642             aop->coff-- ;
1643             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1644         }
1645         aop->coff = offset;
1646         
1647         if (aop->paged) {
1648             MOVA(s);           
1649             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1650             
1651         } else
1652             if (*s == '@') {
1653                 MOVA(s);
1654                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1655             } else
1656                 if (strcmp(s,"r0") == 0 ||
1657                     strcmp(s,"r1") == 0 ||
1658                     strcmp(s,"r2") == 0 ||
1659                     strcmp(s,"r3") == 0 ||
1660                     strcmp(s,"r4") == 0 ||
1661                     strcmp(s,"r5") == 0 ||
1662                     strcmp(s,"r6") == 0 || 
1663                     strcmp(s,"r7") == 0 ) {
1664                     char buffer[10];
1665                     sprintf(buffer,"a%s",s);
1666                     pic16_emitcode("mov","@%s,%s",
1667                              aop->aopu.aop_ptr->name,buffer);
1668                 } else
1669                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1670         
1671         break;
1672         
1673     case AOP_STK:
1674         if (strcmp(s,"a") == 0)
1675             pic16_emitcode("push","acc");
1676         else
1677             pic16_emitcode("push","%s",s);
1678         
1679         break;
1680         
1681     case AOP_CRY:
1682         /* if bit variable */
1683         if (!aop->aopu.aop_dir) {
1684             pic16_emitcode("clr","a");
1685             pic16_emitcode("rlc","a");
1686         } else {
1687             if (s == zero) 
1688                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1689             else
1690                 if (s == one)
1691                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1692                 else
1693                     if (!strcmp(s,"c"))
1694                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1695                     else {
1696                         lbl = newiTempLabel(NULL);
1697                         
1698                         if (strcmp(s,"a")) {
1699                             MOVA(s);
1700                         }
1701                         pic16_emitcode("clr","c");
1702                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1703                         pic16_emitcode("cpl","c");
1704                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1705                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1706                     }
1707         }
1708         break;
1709         
1710     case AOP_STR:
1711         aop->coff = offset;
1712         if (strcmp(aop->aopu.aop_str[offset],s))
1713             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1714         break;
1715         
1716     case AOP_ACC:
1717         aop->coff = offset;
1718         if (!offset && (strcmp(s,"acc") == 0))
1719             break;
1720         
1721         if (strcmp(aop->aopu.aop_str[offset],s))
1722             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1723         break;
1724
1725     default :
1726         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1727                "pic16_aopPut got unsupported aop->type");
1728         exit(0);    
1729     }    
1730
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1735 /*-----------------------------------------------------------------*/
1736 static void mov2w (asmop *aop, int offset)
1737 {
1738
1739   if(!aop)
1740     return;
1741
1742   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1743
1744   if ( aop->type == AOP_PCODE ||
1745        aop->type == AOP_LIT )
1746     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1747   else
1748     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1749
1750 }
1751
1752
1753 void pic16_pushpCodeOpReg(pCodeOpReg *pcop)
1754 {
1755         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pcop, &pic16_pc_postdec1, 0));
1756 }
1757
1758 void pic16_poppCodeOpReg(pCodeOpReg *pcop)
1759 {
1760         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, pcop, 0));
1761 }
1762
1763
1764 /*-----------------------------------------------------------------*/
1765 /* pushw - pushes wreg to stack                                    */
1766 /*-----------------------------------------------------------------*/
1767 void pushw(void)
1768 {
1769         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1770         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1771 }
1772
1773                 
1774 /*-----------------------------------------------------------------*/
1775 /* pushaop - pushes aop to stack                                   */
1776 /*-----------------------------------------------------------------*/
1777 void pushaop(asmop *aop, int offset)
1778 {
1779         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1780         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1781 }
1782
1783 /*-----------------------------------------------------------------*/
1784 /* popaop - pops aop from stack                                    */
1785 /*-----------------------------------------------------------------*/
1786 void popaop(asmop *aop, int offset)
1787 {
1788         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1789         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1790 }
1791
1792 void popaopidx(asmop *aop, int offset, int index)
1793 {
1794   int ofs=1;
1795
1796         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1797
1798         if(STACK_MODEL_LARGE)ofs++;
1799
1800         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1801         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* reAdjustPreg - points a register back to where it should        */
1806 /*-----------------------------------------------------------------*/
1807 static void reAdjustPreg (asmop *aop)
1808 {
1809     int size ;
1810
1811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1812     aop->coff = 0;
1813     if ((size = aop->size) <= 1)
1814         return ;
1815     size-- ;
1816     switch (aop->type) {
1817         case AOP_R0 :
1818         case AOP_R1 :
1819             while (size--)
1820                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1821             break;          
1822         case AOP_DPTR :
1823         case AOP_DPTR2:
1824             if (aop->type == AOP_DPTR2)
1825             {
1826                 genSetDPTR(1);
1827             } 
1828             while (size--)
1829             {
1830                 pic16_emitcode("lcall","__decdptr");
1831             }
1832                 
1833             if (aop->type == AOP_DPTR2)
1834             {
1835                 genSetDPTR(0);
1836             }                
1837             break;  
1838
1839     }   
1840
1841 }
1842
1843
1844 #if 0
1845 /*-----------------------------------------------------------------*/
1846 /* opIsGptr: returns non-zero if the passed operand is             */   
1847 /* a generic pointer type.                                         */
1848 /*-----------------------------------------------------------------*/ 
1849 static int opIsGptr(operand *op)
1850 {
1851     sym_link *type = operandType(op);
1852     
1853     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1854     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1855     {
1856         return 1;
1857     }
1858     return 0;        
1859 }
1860 #endif
1861
1862 /*-----------------------------------------------------------------*/
1863 /* pic16_getDataSize - get the operand data size                         */
1864 /*-----------------------------------------------------------------*/
1865 int pic16_getDataSize(operand *op)
1866 {
1867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1868
1869
1870     return AOP_SIZE(op);
1871
1872     // tsd- in the pic port, the genptr size is 1, so this code here
1873     // fails. ( in the 8051 port, the size was 4).
1874 #if 0
1875     int size;
1876     size = AOP_SIZE(op);
1877     if (size == GPTRSIZE)
1878     {
1879         sym_link *type = operandType(op);
1880         if (IS_GENPTR(type))
1881         {
1882             /* generic pointer; arithmetic operations
1883              * should ignore the high byte (pointer type).
1884              */
1885             size--;
1886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1887         }
1888     }
1889     return size;
1890 #endif
1891 }
1892
1893 /*-----------------------------------------------------------------*/
1894 /* pic16_outAcc - output Acc                                             */
1895 /*-----------------------------------------------------------------*/
1896 void pic16_outAcc(operand *result)
1897 {
1898   int size,offset;
1899   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1900   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1901
1902
1903   size = pic16_getDataSize(result);
1904   if(size){
1905     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1906     size--;
1907     offset = 1;
1908     /* unsigned or positive */
1909     while(size--)
1910       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1911   }
1912
1913 }
1914
1915 /*-----------------------------------------------------------------*/
1916 /* pic16_outBitC - output a bit C                                        */
1917 /*-----------------------------------------------------------------*/
1918 void pic16_outBitC(operand *result)
1919 {
1920
1921     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922     /* if the result is bit */
1923     if (AOP_TYPE(result) == AOP_CRY) 
1924         pic16_aopPut(AOP(result),"c",0);
1925     else {
1926         pic16_emitcode("clr","a  ; %d", __LINE__);
1927         pic16_emitcode("rlc","a");
1928         pic16_outAcc(result);
1929     }
1930 }
1931
1932 /*-----------------------------------------------------------------*/
1933 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1934 /*-----------------------------------------------------------------*/
1935 void pic16_toBoolean(operand *oper)
1936 {
1937     int size = AOP_SIZE(oper) - 1;
1938     int offset = 1;
1939
1940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1941
1942     if ( AOP_TYPE(oper) != AOP_ACC) {
1943       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1944     }
1945     while (size--) {
1946       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1947     }
1948 }
1949
1950
1951 #if !defined(GEN_Not)
1952 /*-----------------------------------------------------------------*/
1953 /* genNot - generate code for ! operation                          */
1954 /*-----------------------------------------------------------------*/
1955 static void pic16_genNot (iCode *ic)
1956 {
1957   symbol *tlbl;
1958   int size;
1959
1960   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1961   /* assign asmOps to operand & result */
1962   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1963   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1964
1965   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1966   /* if in bit space then a special case */
1967   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1968     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1969       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1970       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1971     } else {
1972       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1973       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1974       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1975     }
1976     goto release;
1977   }
1978
1979   size = AOP_SIZE(IC_LEFT(ic));
1980   if(size == 1) {
1981     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1982     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1983     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1984     goto release;
1985   }
1986   pic16_toBoolean(IC_LEFT(ic));
1987
1988   tlbl = newiTempLabel(NULL);
1989   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1990   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1991   pic16_outBitC(IC_RESULT(ic));
1992
1993  release:    
1994   /* release the aops */
1995   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1996   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1997 }
1998 #endif
1999
2000
2001 #if !defined(GEN_Cpl)
2002 /*-----------------------------------------------------------------*/
2003 /* genCpl - generate code for complement                           */
2004 /*-----------------------------------------------------------------*/
2005 static void pic16_genCpl (iCode *ic)
2006 {
2007     int offset = 0;
2008     int size ;
2009
2010
2011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2012     /* assign asmOps to operand & result */
2013     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2014     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2015
2016     /* if both are in bit space then 
2017     a special case */
2018     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2019         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2020
2021         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2022         pic16_emitcode("cpl","c"); 
2023         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2024         goto release; 
2025     } 
2026
2027     size = AOP_SIZE(IC_RESULT(ic));
2028     while (size--) {
2029 /*
2030         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2031         MOVA(l);       
2032         pic16_emitcode("cpl","a");
2033         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2034 */
2035         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2036               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2037         } else {
2038                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2039                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2040         }
2041         offset++;
2042
2043     }
2044
2045
2046 release:
2047     /* release the aops */
2048     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2049     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2050 }
2051 #endif
2052
2053 /*-----------------------------------------------------------------*/
2054 /* genUminusFloat - unary minus for floating points                */
2055 /*-----------------------------------------------------------------*/
2056 static void genUminusFloat(operand *op,operand *result)
2057 {
2058     int size ,offset =0 ;
2059     char *l;
2060
2061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2062     /* for this we just need to flip the 
2063     first it then copy the rest in place */
2064     size = AOP_SIZE(op) - 1;
2065     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2066
2067     MOVA(l);    
2068
2069     pic16_emitcode("cpl","acc.7");
2070     pic16_aopPut(AOP(result),"a",3);    
2071
2072     while(size--) {
2073         pic16_aopPut(AOP(result),
2074                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2075                offset);
2076         offset++;
2077     }          
2078 }
2079
2080 /*-----------------------------------------------------------------*/
2081 /* genUminus - unary minus code generation                         */
2082 /*-----------------------------------------------------------------*/
2083 static void genUminus (iCode *ic)
2084 {
2085   int size, i;
2086   sym_link *optype, *rtype;
2087
2088
2089   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090   /* assign asmops */
2091   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2092   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2093
2094   /* if both in bit space then special
2095      case */
2096   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2097       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2098
2099     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2100     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2101     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2102
2103     goto release; 
2104   } 
2105
2106   optype = operandType(IC_LEFT(ic));
2107   rtype = operandType(IC_RESULT(ic));
2108
2109   /* if float then do float stuff */
2110   if (IS_FLOAT(optype)) {
2111     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2112     goto release;
2113   }
2114
2115   /* otherwise subtract from zero by taking the 2's complement */
2116   size = AOP_SIZE(IC_LEFT(ic));
2117
2118   for(i=0; i<size; i++) {
2119     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2120       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2121     else {
2122       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2123       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2124     }
2125   }
2126
2127   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2128   for(i=1; i<size; i++) {
2129     emitSKPNZ;
2130     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2131   }
2132
2133  release:
2134   /* release the aops */
2135   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2136   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2137 }
2138
2139 /*-----------------------------------------------------------------*/
2140 /* saveRegisters - will look for a call and save the registers     */
2141 /*-----------------------------------------------------------------*/
2142 static void saveRegisters(iCode *lic) 
2143 {
2144     int i;
2145     iCode *ic;
2146     bitVect *rsave;
2147     sym_link *dtype;
2148
2149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2150     /* look for call */
2151     for (ic = lic ; ic ; ic = ic->next) 
2152         if (ic->op == CALL || ic->op == PCALL)
2153             break;
2154
2155     if (!ic) {
2156         fprintf(stderr,"found parameter push with no function call\n");
2157         return ;
2158     }
2159
2160     /* if the registers have been saved already then
2161     do nothing */
2162     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2163         return ;
2164
2165     /* find the registers in use at this time 
2166     and push them away to safety */
2167     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2168                           ic->rUsed);
2169
2170     ic->regsSaved = 1;
2171     if (options.useXstack) {
2172         if (bitVectBitValue(rsave,R0_IDX))
2173             pic16_emitcode("mov","b,r0");
2174         pic16_emitcode("mov","r0,%s",spname);
2175         for (i = 0 ; i < pic16_nRegs ; i++) {
2176             if (bitVectBitValue(rsave,i)) {
2177                 if (i == R0_IDX)
2178                     pic16_emitcode("mov","a,b");
2179                 else
2180                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2181                 pic16_emitcode("movx","@r0,a");
2182                 pic16_emitcode("inc","r0");
2183             }
2184         }
2185         pic16_emitcode("mov","%s,r0",spname);
2186         if (bitVectBitValue(rsave,R0_IDX))
2187             pic16_emitcode("mov","r0,b");           
2188     }// else
2189     //for (i = 0 ; i < pic16_nRegs ; i++) {
2190     //    if (bitVectBitValue(rsave,i))
2191     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2192     //}
2193
2194     dtype = operandType(IC_LEFT(ic));
2195     if (currFunc && dtype && 
2196         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2197         IFFUNC_ISISR(currFunc->type) &&
2198         !ic->bankSaved) 
2199
2200         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2201
2202 }
2203 /*-----------------------------------------------------------------*/
2204 /* unsaveRegisters - pop the pushed registers                      */
2205 /*-----------------------------------------------------------------*/
2206 static void unsaveRegisters (iCode *ic)
2207 {
2208     int i;
2209     bitVect *rsave;
2210
2211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2212     /* find the registers in use at this time 
2213     and push them away to safety */
2214     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2215                           ic->rUsed);
2216     
2217     if (options.useXstack) {
2218         pic16_emitcode("mov","r0,%s",spname);   
2219         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2220             if (bitVectBitValue(rsave,i)) {
2221                 pic16_emitcode("dec","r0");
2222                 pic16_emitcode("movx","a,@r0");
2223                 if (i == R0_IDX)
2224                     pic16_emitcode("mov","b,a");
2225                 else
2226                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2227             }       
2228
2229         }
2230         pic16_emitcode("mov","%s,r0",spname);
2231         if (bitVectBitValue(rsave,R0_IDX))
2232             pic16_emitcode("mov","r0,b");
2233     } //else
2234     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2235     //    if (bitVectBitValue(rsave,i))
2236     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2237     //}
2238
2239 }  
2240
2241
2242 /*-----------------------------------------------------------------*/
2243 /* pushSide -                                                      */
2244 /*-----------------------------------------------------------------*/
2245 static void pushSide(operand * oper, int size)
2246 {
2247 #if 0
2248         int offset = 0;
2249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2250         while (size--) {
2251                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2252                 if (AOP_TYPE(oper) != AOP_REG &&
2253                     AOP_TYPE(oper) != AOP_DIR &&
2254                     strcmp(l,"a") ) {
2255                         pic16_emitcode("mov","a,%s",l);
2256                         pic16_emitcode("push","acc");
2257                 } else
2258                         pic16_emitcode("push","%s",l);
2259         }
2260 #endif
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* assignResultValue -                                             */
2265 /*-----------------------------------------------------------------*/
2266 static void assignResultValue(operand * oper)
2267 {
2268   int size = AOP_SIZE(oper);
2269
2270         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2271         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2272
2273         if(!GpsuedoStkPtr) {
2274 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2275                 /* The last byte in the assignment is in W */
2276                 size--;
2277                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2278                 GpsuedoStkPtr++;
2279         }
2280
2281         while (size--) {
2282 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2283 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2284                 
2285 #if STACK_SUPPORT
2286                 if(USE_STACK) {
2287                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2288                 } else {
2289                         pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2290                 }
2291 #else
2292                 pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2293 #endif  /* STACK_SUPPORT */
2294                 GpsuedoStkPtr++;
2295
2296 #if STACK_SUPPORT
2297                 if(!USE_STACK)
2298                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2299 #else
2300                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2301 #endif
2302
2303         }
2304                 
2305 }
2306
2307
2308 /*-----------------------------------------------------------------*/
2309 /* genIpush - genrate code for pushing this gets a little complex  */
2310 /*-----------------------------------------------------------------*/
2311 static void genIpush (iCode *ic)
2312 {
2313
2314   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2315 #if 0
2316     int size, offset = 0 ;
2317     char *l;
2318
2319
2320     /* if this is not a parm push : ie. it is spill push 
2321     and spill push is always done on the local stack */
2322     if (!ic->parmPush) {
2323
2324         /* and the item is spilt then do nothing */
2325         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2326             return ;
2327
2328         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2329         size = AOP_SIZE(IC_LEFT(ic));
2330         /* push it on the stack */
2331         while(size--) {
2332             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2333             if (*l == '#') {
2334                 MOVA(l);
2335                 l = "acc";
2336             }
2337             pic16_emitcode("push","%s",l);
2338         }
2339         return ;        
2340     }
2341
2342     /* this is a paramter push: in this case we call
2343     the routine to find the call and save those
2344     registers that need to be saved */   
2345     saveRegisters(ic);
2346
2347     /* then do the push */
2348     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2349
2350
2351         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2352     size = AOP_SIZE(IC_LEFT(ic));
2353
2354     while (size--) {
2355         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2356         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2357             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2358             strcmp(l,"a") ) {
2359             pic16_emitcode("mov","a,%s",l);
2360             pic16_emitcode("push","acc");
2361         } else
2362             pic16_emitcode("push","%s",l);
2363     }       
2364
2365     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2366 #endif
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling   */
2371 /*-----------------------------------------------------------------*/
2372 static void genIpop (iCode *ic)
2373 {
2374   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2375 #if 0
2376     int size,offset ;
2377
2378
2379     /* if the temp was not pushed then */
2380     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2381         return ;
2382
2383     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2384     size = AOP_SIZE(IC_LEFT(ic));
2385     offset = (size-1);
2386     while (size--) 
2387         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2388                                    FALSE,TRUE));
2389
2390     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2391 #endif
2392 }
2393
2394 /*-----------------------------------------------------------------*/
2395 /* unsaverbank - restores the resgister bank from stack            */
2396 /*-----------------------------------------------------------------*/
2397 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2398 {
2399   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2400 #if 0
2401     int i;
2402     asmop *aop ;
2403     regs *r = NULL;
2404
2405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406     if (popPsw) {
2407         if (options.useXstack) {
2408             aop = newAsmop(0);
2409             r = getFreePtr(ic,&aop,FALSE);
2410             
2411             
2412             pic16_emitcode("mov","%s,_spx",r->name);
2413             pic16_emitcode("movx","a,@%s",r->name);
2414             pic16_emitcode("mov","psw,a");
2415             pic16_emitcode("dec","%s",r->name);
2416             
2417         }else
2418             pic16_emitcode ("pop","psw");
2419     }
2420
2421     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2422         if (options.useXstack) {       
2423             pic16_emitcode("movx","a,@%s",r->name);
2424             //pic16_emitcode("mov","(%s+%d),a",
2425             //       regspic16[i].base,8*bank+regspic16[i].offset);
2426             pic16_emitcode("dec","%s",r->name);
2427
2428         } else 
2429           pic16_emitcode("pop",""); //"(%s+%d)",
2430         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2431     }
2432
2433     if (options.useXstack) {
2434
2435         pic16_emitcode("mov","_spx,%s",r->name);
2436         pic16_freeAsmop(NULL,aop,ic,TRUE);
2437
2438     }
2439 #endif 
2440 }
2441
2442 /*-----------------------------------------------------------------*/
2443 /* saverbank - saves an entire register bank on the stack          */
2444 /*-----------------------------------------------------------------*/
2445 static void saverbank (int bank, iCode *ic, bool pushPsw)
2446 {
2447   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2448 #if 0
2449     int i;
2450     asmop *aop ;
2451     regs *r = NULL;
2452
2453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2454     if (options.useXstack) {
2455
2456         aop = newAsmop(0);
2457         r = getFreePtr(ic,&aop,FALSE);  
2458         pic16_emitcode("mov","%s,_spx",r->name);
2459
2460     }
2461
2462     for (i = 0 ; i < pic16_nRegs ;i++) {
2463         if (options.useXstack) {
2464             pic16_emitcode("inc","%s",r->name);
2465             //pic16_emitcode("mov","a,(%s+%d)",
2466             //         regspic16[i].base,8*bank+regspic16[i].offset);
2467             pic16_emitcode("movx","@%s,a",r->name);           
2468         } else 
2469           pic16_emitcode("push","");// "(%s+%d)",
2470                      //regspic16[i].base,8*bank+regspic16[i].offset);
2471     }
2472     
2473     if (pushPsw) {
2474         if (options.useXstack) {
2475             pic16_emitcode("mov","a,psw");
2476             pic16_emitcode("movx","@%s,a",r->name);     
2477             pic16_emitcode("inc","%s",r->name);
2478             pic16_emitcode("mov","_spx,%s",r->name);       
2479             pic16_freeAsmop (NULL,aop,ic,TRUE);
2480             
2481         } else
2482             pic16_emitcode("push","psw");
2483         
2484         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2485     }
2486     ic->bankSaved = 1;
2487 #endif
2488 }
2489
2490
2491
2492 /*-----------------------------------------------------------------*/
2493 /* genCall - generates a call statement                            */
2494 /*-----------------------------------------------------------------*/
2495 static void genCall (iCode *ic)
2496 {
2497   sym_link *dtype;   
2498   int stackParms=0;
2499   
2500         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2501
2502         /* if caller saves & we have not saved then */
2503         if (!ic->regsSaved)
2504                 saveRegisters(ic);
2505
2506         /* if we are calling a function that is not using
2507          * the same register bank then we need to save the
2508          * destination registers on the stack */
2509         dtype = operandType(IC_LEFT(ic));
2510         if (currFunc && dtype && 
2511                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2512                 IFFUNC_ISISR(currFunc->type) &&
2513                 !ic->bankSaved) 
2514
2515                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2516
2517         /* if send set is not empty the assign */
2518         if (_G.sendSet) {
2519           iCode *sic;
2520
2521                 /* For the Pic port, there is no data stack.
2522                  * So parameters passed to functions are stored
2523                  * in registers. (The pCode optimizer will get
2524                  * rid of most of these :). */
2525
2526           int psuedoStkPtr=-1; 
2527           int firstTimeThruLoop = 1;
2528
2529                 _G.sendSet = reverseSet(_G.sendSet);
2530
2531                 /* First figure how many parameters are getting passed */
2532                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2533                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2534                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2535                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2536                 }
2537
2538                 stackParms = psuedoStkPtr;
2539
2540                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2541                   int size, offset = 0;
2542
2543                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2544                         size = AOP_SIZE(IC_LEFT(sic));
2545
2546                         while (size--) {
2547                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2548                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2549                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2550
2551                                 if(!firstTimeThruLoop) {
2552                                         /* If this is not the first time we've been through the loop
2553                                          * then we need to save the parameter in a temporary
2554                                          * register. The last byte of the last parameter is
2555                                          * passed in W. */
2556
2557 #if STACK_SUPPORT
2558                                         if(USE_STACK) {
2559                                                 pushw();
2560                                                 --psuedoStkPtr;         // sanity check
2561                                         } else {
2562                                                 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2563                                         }
2564 #else
2565                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2566 #endif  /* STACK_SUPPORT */
2567                                 }
2568                         
2569                                 firstTimeThruLoop=0;
2570
2571                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2572                                 offset++;
2573                         }
2574                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2575                 }
2576                 _G.sendSet = NULL;
2577         }
2578
2579         /* make the call */
2580         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2581                         OP_SYMBOL(IC_LEFT(ic))->rname :
2582                         OP_SYMBOL(IC_LEFT(ic))->name));
2583
2584         GpsuedoStkPtr=0;
2585         /* if we need assign a result value */
2586         if ((IS_ITEMP(IC_RESULT(ic)) && 
2587                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2588                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2589                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2590
2591                 _G.accInUse++;
2592                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2593                 _G.accInUse--;
2594
2595                 assignResultValue(IC_RESULT(ic));
2596
2597                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2598                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2599                 
2600                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2601         }
2602
2603 #if STACK_SUPPORT
2604         if(USE_STACK && stackParms>0) {
2605                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2606                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2607                 if(STACK_MODEL_LARGE) {
2608                         emitSKPNC;
2609                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2610                 }
2611         }
2612 #endif
2613
2614         /* adjust the stack for parameters if required */
2615 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2616
2617         if (ic->parmBytes) {
2618           int i;
2619
2620                 if (ic->parmBytes > 3) {
2621                         pic16_emitcode("mov","a,%s",spname);
2622                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2623                         pic16_emitcode("mov","%s,a",spname);
2624                 } else 
2625                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2626                                 pic16_emitcode("dec","%s",spname);
2627         }
2628
2629         /* if register bank was saved then pop them */
2630         if (ic->bankSaved)
2631                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2632
2633         /* if we hade saved some registers then unsave them */
2634         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2635                 unsaveRegisters (ic);
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genPcall - generates a call by pointer statement                */
2640 /*-----------------------------------------------------------------*/
2641 static void genPcall (iCode *ic)
2642 {
2643     sym_link *dtype;
2644     symbol *rlbl = newiTempLabel(NULL);
2645
2646
2647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2648     /* if caller saves & we have not saved then */
2649     if (!ic->regsSaved)
2650         saveRegisters(ic);
2651
2652     /* if we are calling a function that is not using
2653     the same register bank then we need to save the
2654     destination registers on the stack */
2655     dtype = operandType(IC_LEFT(ic));
2656     if (currFunc && dtype && 
2657         IFFUNC_ISISR(currFunc->type) &&
2658         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2659         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2660
2661
2662     /* push the return address on to the stack */
2663     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2664     pic16_emitcode("push","acc");    
2665     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2666     pic16_emitcode("push","acc");
2667     
2668     if (options.model == MODEL_FLAT24)
2669     {
2670         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2671         pic16_emitcode("push","acc");    
2672     }
2673
2674     /* now push the calling address */
2675     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2676
2677     pushSide(IC_LEFT(ic), FPTRSIZE);
2678
2679     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2680
2681     /* if send set is not empty the assign */
2682     if (_G.sendSet) {
2683         iCode *sic ;
2684
2685         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2686              sic = setNextItem(_G.sendSet)) {
2687             int size, offset = 0;
2688             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2689             size = AOP_SIZE(IC_LEFT(sic));
2690             while (size--) {
2691                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2692                                 FALSE,FALSE);
2693                 if (strcmp(l,fReturn[offset]))
2694                     pic16_emitcode("mov","%s,%s",
2695                              fReturn[offset],
2696                              l);
2697                 offset++;
2698             }
2699             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2700         }
2701         _G.sendSet = NULL;
2702     }
2703
2704     pic16_emitcode("ret","");
2705     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2706
2707
2708     /* if we need assign a result value */
2709     if ((IS_ITEMP(IC_RESULT(ic)) &&
2710          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2711           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2712         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2713
2714         _G.accInUse++;
2715         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2716         _G.accInUse--;
2717         
2718         assignResultValue(IC_RESULT(ic));
2719
2720         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2721     }
2722
2723     /* adjust the stack for parameters if 
2724     required */
2725     if (ic->parmBytes) {
2726         int i;
2727         if (ic->parmBytes > 3) {
2728             pic16_emitcode("mov","a,%s",spname);
2729             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2730             pic16_emitcode("mov","%s,a",spname);
2731         } else 
2732             for ( i = 0 ; i <  ic->parmBytes ;i++)
2733                 pic16_emitcode("dec","%s",spname);
2734
2735     }
2736
2737     /* if register bank was saved then unsave them */
2738     if (currFunc && dtype && 
2739         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2740         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2741
2742     /* if we hade saved some registers then
2743     unsave them */
2744     if (ic->regsSaved)
2745         unsaveRegisters (ic);
2746
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* resultRemat - result  is rematerializable                       */
2751 /*-----------------------------------------------------------------*/
2752 static int resultRemat (iCode *ic)
2753 {
2754   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2755   if (SKIP_IC(ic) || ic->op == IFX)
2756     return 0;
2757
2758   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2759     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2760     if (sym->remat && !POINTER_SET(ic)) 
2761       return 1;
2762   }
2763
2764   return 0;
2765 }
2766
2767 #if defined(__BORLANDC__) || defined(_MSC_VER)
2768 #define STRCASECMP stricmp
2769 #else
2770 #define STRCASECMP strcasecmp
2771 #endif
2772
2773 #if 0
2774 /*-----------------------------------------------------------------*/
2775 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2776 /*-----------------------------------------------------------------*/
2777 static bool inExcludeList(char *s)
2778 {
2779   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2780     int i =0;
2781     
2782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2783     if (options.excludeRegs[i] &&
2784     STRCASECMP(options.excludeRegs[i],"none") == 0)
2785         return FALSE ;
2786
2787     for ( i = 0 ; options.excludeRegs[i]; i++) {
2788         if (options.excludeRegs[i] &&
2789         STRCASECMP(s,options.excludeRegs[i]) == 0)
2790             return TRUE;
2791     }
2792     return FALSE ;
2793 }
2794 #endif
2795
2796 /*-----------------------------------------------------------------*/
2797 /* genFunction - generated code for function entry                 */
2798 /*-----------------------------------------------------------------*/
2799 static void genFunction (iCode *ic)
2800 {
2801   symbol *sym;
2802   sym_link *ftype;
2803
2804         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2805
2806         labelOffset += (max_key+4);
2807         max_key=0;
2808         GpsuedoStkPtr=0;
2809         _G.nRegsSaved = 0;
2810         /* create the function header */
2811         pic16_emitcode(";","-----------------------------------------");
2812         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2813         pic16_emitcode(";","-----------------------------------------");
2814
2815         pic16_emitcode("","%s:",sym->rname);
2816         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2817
2818         {
2819           absSym *ab;
2820
2821                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
2822                         if(strcmp(ab->name, sym->name)) {
2823                                 pic16_pBlockConvert2Absolute(pb);
2824                                 break;
2825                         }
2826                 
2827         }
2828
2829         ftype = operandType(IC_LEFT(ic));
2830
2831         if(IFFUNC_ISNAKED(ftype)) {
2832                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2833                 return;
2834         }
2835         
2836
2837         /* if critical function then turn interrupts off */
2838         if (IFFUNC_ISCRITICAL(ftype))
2839                 pic16_emitcode("clr","ea");
2840
2841         /* here we need to generate the equates for the
2842          * register bank if required */
2843 #if 0
2844         if (FUNC_REGBANK(ftype) != rbank) {
2845           int i ;
2846
2847                 rbank = FUNC_REGBANK(ftype);
2848                 for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2849                         if (strcmp(regspic16[i].base,"0") == 0)
2850                                 pic16_emitcode("","%s = 0x%02x",
2851                                         regspic16[i].dname,
2852                                         8*rbank+regspic16[i].offset);
2853                         else
2854                                 pic16_emitcode ("","%s = %s + 0x%02x",
2855                                         regspic16[i].dname,
2856                                         regspic16[i].base,
2857                                         *rbank+regspic16[i].offset);
2858                 }
2859         }
2860 #endif
2861
2862         /* if this is an interrupt service routine then
2863          * save acc, b, dpl, dph  */
2864         if (IFFUNC_ISISR(sym->type)) {
2865                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2866                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2867                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2868                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2869
2870                 pic16_pBlockConvert2ISR(pb);
2871 #if 0  
2872                 if (!inExcludeList("acc"))          
2873                         pic16_emitcode ("push","acc");  
2874                 if (!inExcludeList("b"))
2875                         pic16_emitcode ("push","b");
2876                 if (!inExcludeList("dpl"))
2877                         pic16_emitcode ("push","dpl");
2878                 if (!inExcludeList("dph"))
2879                         pic16_emitcode ("push","dph");
2880                 
2881                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx")) {
2882                         pic16_emitcode ("push", "dpx");
2883
2884                         /* Make sure we're using standard DPTR */
2885                         pic16_emitcode ("push", "dps");
2886                         pic16_emitcode ("mov", "dps, #0x00");
2887                         if (options.stack10bit) {       
2888                                 /* This ISR could conceivably use DPTR2. Better save it. */
2889                                 pic16_emitcode ("push", "dpl1");
2890                                 pic16_emitcode ("push", "dph1");
2891                                 pic16_emitcode ("push", "dpx1");
2892                         }
2893                 }
2894
2895                 /* if this isr has no bank i.e. is going to
2896                  * run with bank 0 , then we need to save more
2897                  * registers :-) */
2898                 if (!FUNC_REGBANK(sym->type)) {
2899
2900                         /* if this function does not call any other
2901                          * function then we can be economical and
2902                          * save only those registers that are used */
2903                         if (! IFFUNC_HASFCALL(sym->type)) {
2904                           int i;
2905
2906                                 /* if any registers used */
2907                                 if (sym->regsUsed) {
2908                                         /* save the registers used */
2909                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2910                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2911                                                         (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2912                                                 pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                           
2913                                         }
2914                                 }
2915
2916                         } else {
2917                                 /* this function has  a function call cannot
2918                                  * determines register usage so we will have the
2919                                  * entire bank */
2920                                 saverbank(0,ic,FALSE);
2921                         }           
2922                 }
2923 #endif
2924         } else {
2925 #if STACK_SUPPORT
2926                 /* emit code to setup stack frame if user enabled,
2927                  * and function is not main() */
2928          
2929 //              fprintf(stderr, "function name: %s\n", sym->name);
2930                 if(USE_STACK && strcmp(sym->name, "main")) {
2931                         if(!options.ommitFramePtr || sym->regsUsed) {
2932                         /* setup the stack frame */
2933                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
2934                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
2935                                 if(STACK_MODEL_LARGE)
2936                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
2937                         }
2938                 }
2939 #endif
2940
2941                 /* if callee-save to be used for this function
2942                 * then save the registers being used in this function */
2943                 if (IFFUNC_CALLEESAVES(sym->type)) {
2944                   int i;
2945             
2946 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
2947                         
2948                         /* if any registers used */
2949                         if (sym->regsUsed
2950 #if STACK_SUPPORT
2951                                 && USE_STACK
2952 #endif
2953                                 ) {
2954                                 /* save the registers used */
2955                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
2956                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2957                                         if (bitVectBitValue(sym->regsUsed,i)) {
2958 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
2959 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
2960 //                                                              pic16_regWithIdx(i)->name);
2961
2962                                                 pic16_pushpCodeOpReg( PCOR(pic16_popRegFromIdx(i) ));
2963 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
2964 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
2965 //                                                      &pic16_pc_postdec1, 0));
2966                                                 _G.nRegsSaved++;
2967                                         }
2968                                 }
2969                         }
2970                 }
2971         }
2972
2973
2974         
2975 #if 0
2976         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2977
2978                 if (options.useXstack) {
2979                         pic16_emitcode("mov","r0,%s",spname);
2980                         pic16_emitcode("mov","a,_bp");
2981                         pic16_emitcode("movx","@r0,a");
2982                         pic16_emitcode("inc","%s",spname);
2983                 } else {
2984                         /* set up the stack */
2985                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
2986                 }
2987                 pic16_emitcode ("mov","_bp,%s",spname);
2988         }
2989 #endif
2990         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
2991
2992         /* adjust the stack for the function */
2993         if (sym->stack) {
2994           int i = sym->stack;
2995
2996                 if (i > 127 ) 
2997                         werror(W_STACK_OVERFLOW,sym->name);
2998
2999                 if (i > 3 && sym->recvSize < 4) {              
3000                         pic16_emitcode ("mov","a,sp");
3001                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3002                         pic16_emitcode ("mov","sp,a");
3003                 } else
3004                         while(i--)
3005                                 pic16_emitcode("inc","sp");
3006         }
3007
3008         if (sym->xstack) {
3009                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3010
3011                 pic16_emitcode ("mov","a,_spx");
3012                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3013                 pic16_emitcode ("mov","_spx,a");
3014         }
3015     
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genEndFunction - generates epilogue for functions               */
3020 /*-----------------------------------------------------------------*/
3021 static void genEndFunction (iCode *ic)
3022 {
3023     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3024
3025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3026
3027     if(IFFUNC_ISNAKED(sym->type)) {
3028         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3029         return;
3030     }
3031
3032 #if 0
3033     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3034     {
3035         pic16_emitcode ("mov","%s,_bp",spname);
3036     }
3037 #endif
3038
3039     /* if use external stack but some variables were
3040     added to the local stack then decrement the
3041     local stack */
3042     if (options.useXstack && sym->stack) {      
3043         pic16_emitcode("mov","a,sp");
3044         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3045         pic16_emitcode("mov","sp,a");
3046     }
3047
3048
3049 #if 0
3050     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3051         if (options.useXstack) {
3052             pic16_emitcode("mov","r0,%s",spname);
3053             pic16_emitcode("movx","a,@r0");
3054             pic16_emitcode("mov","_bp,a");
3055             pic16_emitcode("dec","%s",spname);
3056         }
3057         else
3058         {
3059             pic16_emitcode ("pop","_bp");
3060         }
3061     }
3062 #endif
3063
3064     /* restore the register bank  */    
3065     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3066         pic16_emitcode ("pop","psw");
3067
3068     if (IFFUNC_ISISR(sym->type)) {
3069
3070         /* now we need to restore the registers */
3071         /* if this isr has no bank i.e. is going to
3072            run with bank 0 , then we need to save more
3073            registers :-) */
3074         if (!FUNC_REGBANK(sym->type)) {
3075             
3076             /* if this function does not call any other
3077                function then we can be economical and
3078                save only those registers that are used */
3079             if (! IFFUNC_HASFCALL(sym->type)) {
3080                 int i;
3081                 
3082                 /* if any registers used */
3083                 if (sym->regsUsed) {
3084                     /* save the registers used */
3085                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3086                         if (bitVectBitValue(sym->regsUsed,i) ||
3087                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3088                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3089                     }
3090                 }
3091                 
3092             } else {
3093                 /* this function has  a function call cannot
3094                    determines register usage so we will have the
3095                    entire bank */
3096                 unsaverbank(0,ic,FALSE);
3097             }       
3098         }
3099 #if 0
3100         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3101         {
3102             if (options.stack10bit)
3103             {
3104                 pic16_emitcode ("pop", "dpx1");
3105                 pic16_emitcode ("pop", "dph1");
3106                 pic16_emitcode ("pop", "dpl1");
3107             }   
3108             pic16_emitcode ("pop", "dps");
3109             pic16_emitcode ("pop", "dpx");
3110         }
3111         if (!inExcludeList("dph"))
3112             pic16_emitcode ("pop","dph");
3113         if (!inExcludeList("dpl"))
3114             pic16_emitcode ("pop","dpl");
3115         if (!inExcludeList("b"))
3116             pic16_emitcode ("pop","b");
3117         if (!inExcludeList("acc"))
3118             pic16_emitcode ("pop","acc");
3119
3120         if (IFFUNC_ISCRITICAL(sym->type))
3121             pic16_emitcode("setb","ea");
3122 #endif
3123
3124         /* if debug then send end of function */
3125 /*      if (options.debug && currFunc) { */
3126         if (currFunc) {
3127             _G.debugLine = 1;
3128             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3129                      FileBaseName(ic->filename),currFunc->lastLine,
3130                      ic->level,ic->block); 
3131             if (IS_STATIC(currFunc->etype))         
3132                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3133             else
3134                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3135             _G.debugLine = 0;
3136         }
3137         
3138 //      pic16_emitcode ("reti","");
3139
3140         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3141         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3142         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3143         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3144         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3145
3146 #if 0
3147         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3148 #endif
3149
3150         pic16_emitpcodeNULLop(POC_RETFIE);
3151
3152     }
3153     else {
3154         if (IFFUNC_ISCRITICAL(sym->type))
3155             pic16_emitcode("setb","ea");
3156         
3157         /* if any registers used */
3158         if (sym->regsUsed
3159 #if STACK_SUPPORT
3160                 && USE_STACK
3161 #endif
3162         ) {
3163           int i;
3164                 /* save the registers used */
3165                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3166                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3167                         if (bitVectBitValue(sym->regsUsed,i)) {
3168 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3169 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3170 //                                              pic16_regWithIdx(i)->name);
3171         
3172                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3173                                         &pic16_pc_preinc1,
3174                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3175                         }
3176                 }
3177         }
3178         
3179
3180         /* if debug then send end of function */
3181         if (currFunc) {
3182             _G.debugLine = 1;
3183             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3184                      FileBaseName(ic->filename),currFunc->lastLine,
3185                      ic->level,ic->block); 
3186             if (IS_STATIC(currFunc->etype))         
3187                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3188             else
3189                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3190             _G.debugLine = 0;
3191         }
3192
3193 #if STACK_SUPPORT
3194         /* insert code to restore stack frame, if user enabled it
3195          * and function is not main() */
3196          
3197         if(USE_STACK && strcmp(sym->name, "main")) {
3198                 if(!options.ommitFramePtr || sym->regsUsed) {
3199                         /* restore stack frame */
3200                         if(STACK_MODEL_LARGE)
3201                                 pic16_emitpcode(POC_MOVFF,
3202                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h, 0));
3203                         pic16_emitpcode(POC_MOVFF,
3204                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l, 0));
3205                 }
3206         }
3207 #endif
3208
3209         pic16_emitcode ("return","");
3210         pic16_emitpcodeNULLop(POC_RETURN);
3211
3212         /* Mark the end of a function */
3213         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3214     }
3215
3216 }
3217
3218 /*-----------------------------------------------------------------*/
3219 /* genRet - generate code for return statement                     */
3220 /*-----------------------------------------------------------------*/
3221 static void genRet (iCode *ic)
3222 {
3223   int size,offset = 0 , pushed = 0;
3224     
3225   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3226   /* if we have no return value then
3227      just generate the "ret" */
3228   if (!IC_LEFT(ic)) 
3229     goto jumpret;       
3230     
3231   /* we have something to return then
3232      move the return value into place */
3233   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3234   size = AOP_SIZE(IC_LEFT(ic));
3235     
3236   while (size--) {
3237     char *l ;
3238     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3239       /* #NOCHANGE */
3240       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3241                  FALSE,TRUE);
3242       pic16_emitcode("push","%s",l);
3243       pushed++;
3244     } else {
3245         DEBUGpic16_emitcode(";", "%d", __LINE__);
3246       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3247                  FALSE,FALSE);
3248         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3249       if (strcmp(fReturn[offset],l)) {
3250         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3251             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3252           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3253         }else {
3254           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3255         }
3256         if(size) {
3257           pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3258         }
3259         offset++;
3260       }
3261     }
3262   }    
3263
3264   if (pushed) {
3265     while(pushed) {
3266       pushed--;
3267       if (strcmp(fReturn[pushed],"a"))
3268         pic16_emitcode("pop",fReturn[pushed]);
3269       else
3270         pic16_emitcode("pop","acc");
3271     }
3272   }
3273   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3274     
3275  jumpret:
3276   /* generate a jump to the return label
3277      if the next is not the return statement */
3278   if (!(ic->next && ic->next->op == LABEL &&
3279         IC_LABEL(ic->next) == returnLabel)) {
3280         
3281     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3282     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3283   }
3284     
3285 }
3286
3287 /*-----------------------------------------------------------------*/
3288 /* genLabel - generates a label                                    */
3289 /*-----------------------------------------------------------------*/
3290 static void genLabel (iCode *ic)
3291 {
3292     /* special case never generate */
3293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3294     if (IC_LABEL(ic) == entryLabel)
3295         return ;
3296
3297     pic16_emitpLabel(IC_LABEL(ic)->key);
3298     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3299 }
3300
3301 /*-----------------------------------------------------------------*/
3302 /* genGoto - generates a goto                                      */
3303 /*-----------------------------------------------------------------*/
3304 //tsd
3305 static void genGoto (iCode *ic)
3306 {
3307   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3308   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3309 }
3310
3311
3312 /*-----------------------------------------------------------------*/
3313 /* genMultbits :- multiplication of bits                           */
3314 /*-----------------------------------------------------------------*/
3315 static void genMultbits (operand *left, 
3316                          operand *right, 
3317                          operand *result)
3318 {
3319   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3320
3321   if(!pic16_sameRegs(AOP(result),AOP(right)))
3322     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3323
3324   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3325   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3326   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3327
3328 }
3329
3330
3331 /*-----------------------------------------------------------------*/
3332 /* genMultOneByte : 8 bit multiplication & division                */
3333 /*-----------------------------------------------------------------*/
3334 static void genMultOneByte (operand *left,
3335                             operand *right,
3336                             operand *result)
3337 {
3338   sym_link *opetype = operandType(result);
3339
3340   // symbol *lbl ;
3341   int size,offset;
3342
3343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3344   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3345   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3346
3347   /* (if two literals, the value is computed before) */
3348   /* if one literal, literal on the right */
3349   if (AOP_TYPE(left) == AOP_LIT){
3350     operand *t = right;
3351     right = left;
3352     left = t;
3353   }
3354
3355   size = AOP_SIZE(result);
3356   if(size == 1) {
3357
3358     if (AOP_TYPE(right) == AOP_LIT){
3359       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3360                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3361                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3362                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3363       pic16_emitcode("call","genMultLit");
3364     } else {
3365       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3366                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3367                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3368                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3369       pic16_emitcode("call","pic16_genMult8X8_8");
3370
3371     }
3372     pic16_genMult8X8_8 (left, right,result);
3373
3374
3375     /* signed or unsigned */
3376     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3377     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3378     //MOVA(l);       
3379     //pic16_emitcode("mul","ab");
3380     /* if result size = 1, mul signed = mul unsigned */
3381     //pic16_aopPut(AOP(result),"a",0);
3382
3383   } else {  // (size > 1)
3384
3385     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3386                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3387                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3388                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3389
3390     if (SPEC_USIGN(opetype)){
3391       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3392       pic16_genUMult8X8_16 (left, right, result, NULL);
3393
3394       if (size > 2) {
3395         /* for filling the MSBs */
3396         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3397         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3398       }
3399     }
3400     else{
3401       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3402
3403       pic16_emitcode("mov","a,b");
3404
3405       /* adjust the MSB if left or right neg */
3406
3407       /* if one literal */
3408       if (AOP_TYPE(right) == AOP_LIT){
3409         pic16_emitcode("multiply ","right is a lit");
3410         /* AND literal negative */
3411         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3412           /* adjust MSB (c==0 after mul) */
3413           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3414         }
3415       }
3416       else{
3417         pic16_genSMult8X8_16 (left, right, result, NULL);
3418       }
3419
3420       if(size > 2){
3421         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3422         /* get the sign */
3423         pic16_emitcode("rlc","a");
3424         pic16_emitcode("subb","a,acc");
3425       }
3426     }
3427
3428     size -= 2;   
3429     offset = 2;
3430     if (size > 0)
3431       while (size--)
3432         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3433     //pic16_aopPut(AOP(result),"a",offset++);
3434   }
3435 }
3436
3437 /*-----------------------------------------------------------------*/
3438 /* genMult - generates code for multiplication                     */
3439 /*-----------------------------------------------------------------*/
3440 static void genMult (iCode *ic)
3441 {
3442     operand *left = IC_LEFT(ic);
3443     operand *right = IC_RIGHT(ic);
3444     operand *result= IC_RESULT(ic);   
3445
3446     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3447     /* assign the amsops */
3448     pic16_aopOp (left,ic,FALSE);
3449     pic16_aopOp (right,ic,FALSE);
3450     pic16_aopOp (result,ic,TRUE);
3451
3452   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3453
3454     /* special cases first */
3455     /* both are bits */
3456     if (AOP_TYPE(left) == AOP_CRY &&
3457         AOP_TYPE(right)== AOP_CRY) {
3458         genMultbits(left,right,result);
3459         goto release ;
3460     }
3461
3462     /* if both are of size == 1 */
3463     if (AOP_SIZE(left) == 1 &&
3464         AOP_SIZE(right) == 1 ) {
3465         genMultOneByte(left,right,result);
3466         goto release ;
3467     }
3468
3469     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3470
3471     /* should have been converted to function call */
3472     //assert(0) ;
3473
3474 release :
3475     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3477     pic16_freeAsmop(result,NULL,ic,TRUE); 
3478 }
3479
3480 /*-----------------------------------------------------------------*/
3481 /* genDivbits :- division of bits                                  */
3482 /*-----------------------------------------------------------------*/
3483 static void genDivbits (operand *left, 
3484                         operand *right, 
3485                         operand *result)
3486 {
3487
3488     char *l;
3489
3490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3491     /* the result must be bit */    
3492     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3493     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3494
3495     MOVA(l);    
3496
3497     pic16_emitcode("div","ab");
3498     pic16_emitcode("rrc","a");
3499     pic16_aopPut(AOP(result),"c",0);
3500 }
3501
3502 /*-----------------------------------------------------------------*/
3503 /* genDivOneByte : 8 bit division                                  */
3504 /*-----------------------------------------------------------------*/
3505 static void genDivOneByte (operand *left,
3506                            operand *right,
3507                            operand *result)
3508 {
3509     sym_link *opetype = operandType(result);
3510     char *l ;
3511     symbol *lbl ;
3512     int size,offset;
3513
3514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3515     size = AOP_SIZE(result) - 1;
3516     offset = 1;
3517     /* signed or unsigned */
3518     if (SPEC_USIGN(opetype)) {
3519         /* unsigned is easy */
3520         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3521         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3522         MOVA(l);        
3523         pic16_emitcode("div","ab");
3524         pic16_aopPut(AOP(result),"a",0);
3525         while (size--)
3526             pic16_aopPut(AOP(result),zero,offset++);
3527         return ;
3528     }
3529
3530     /* signed is a little bit more difficult */
3531
3532     /* save the signs of the operands */
3533     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3534     MOVA(l);    
3535     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3536     pic16_emitcode("push","acc"); /* save it on the stack */
3537
3538     /* now sign adjust for both left & right */
3539     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3540     MOVA(l);       
3541     lbl = newiTempLabel(NULL);
3542     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3543     pic16_emitcode("cpl","a");   
3544     pic16_emitcode("inc","a");
3545     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3546     pic16_emitcode("mov","b,a");
3547
3548     /* sign adjust left side */
3549     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3550     MOVA(l);
3551
3552     lbl = newiTempLabel(NULL);
3553     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3554     pic16_emitcode("cpl","a");
3555     pic16_emitcode("inc","a");
3556     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3557
3558     /* now the division */
3559     pic16_emitcode("div","ab");
3560     /* we are interested in the lower order
3561     only */
3562     pic16_emitcode("mov","b,a");
3563     lbl = newiTempLabel(NULL);
3564     pic16_emitcode("pop","acc");   
3565     /* if there was an over flow we don't 
3566     adjust the sign of the result */
3567     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3568     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3569     CLRC;
3570     pic16_emitcode("clr","a");
3571     pic16_emitcode("subb","a,b");
3572     pic16_emitcode("mov","b,a");
3573     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3574
3575     /* now we are done */
3576     pic16_aopPut(AOP(result),"b",0);
3577     if(size > 0){
3578         pic16_emitcode("mov","c,b.7");
3579         pic16_emitcode("subb","a,acc");   
3580     }
3581     while (size--)
3582         pic16_aopPut(AOP(result),"a",offset++);
3583
3584 }
3585
3586 /*-----------------------------------------------------------------*/
3587 /* genDiv - generates code for division                            */
3588 /*-----------------------------------------------------------------*/
3589 static void genDiv (iCode *ic)
3590 {
3591     operand *left = IC_LEFT(ic);
3592     operand *right = IC_RIGHT(ic);
3593     operand *result= IC_RESULT(ic);   
3594
3595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3596     /* assign the amsops */
3597     pic16_aopOp (left,ic,FALSE);
3598     pic16_aopOp (right,ic,FALSE);
3599     pic16_aopOp (result,ic,TRUE);
3600
3601     /* special cases first */
3602     /* both are bits */
3603     if (AOP_TYPE(left) == AOP_CRY &&
3604         AOP_TYPE(right)== AOP_CRY) {
3605         genDivbits(left,right,result);
3606         goto release ;
3607     }
3608
3609     /* if both are of size == 1 */
3610     if (AOP_SIZE(left) == 1 &&
3611         AOP_SIZE(right) == 1 ) {
3612         genDivOneByte(left,right,result);
3613         goto release ;
3614     }
3615
3616     /* should have been converted to function call */
3617     assert(0);
3618 release :
3619     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3620     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3621     pic16_freeAsmop(result,NULL,ic,TRUE); 
3622 }
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genModbits :- modulus of bits                                   */
3626 /*-----------------------------------------------------------------*/
3627 static void genModbits (operand *left, 
3628                         operand *right, 
3629                         operand *result)
3630 {
3631
3632     char *l;
3633
3634     /* the result must be bit */    
3635     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3636     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3637
3638     MOVA(l);       
3639
3640     pic16_emitcode("div","ab");
3641     pic16_emitcode("mov","a,b");
3642     pic16_emitcode("rrc","a");
3643     pic16_aopPut(AOP(result),"c",0);
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genModOneByte : 8 bit modulus                                   */
3648 /*-----------------------------------------------------------------*/
3649 static void genModOneByte (operand *left,
3650                            operand *right,
3651                            operand *result)
3652 {
3653     sym_link *opetype = operandType(result);
3654     char *l ;
3655     symbol *lbl ;
3656
3657     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3658     /* signed or unsigned */
3659     if (SPEC_USIGN(opetype)) {
3660         /* unsigned is easy */
3661         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3662         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3663         MOVA(l);    
3664         pic16_emitcode("div","ab");
3665         pic16_aopPut(AOP(result),"b",0);
3666         return ;
3667     }
3668
3669     /* signed is a little bit more difficult */
3670
3671     /* save the signs of the operands */
3672     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3673     MOVA(l);
3674
3675     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3676     pic16_emitcode("push","acc"); /* save it on the stack */
3677
3678     /* now sign adjust for both left & right */
3679     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3680     MOVA(l);
3681
3682     lbl = newiTempLabel(NULL);
3683     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3684     pic16_emitcode("cpl","a");   
3685     pic16_emitcode("inc","a");
3686     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3687     pic16_emitcode("mov","b,a"); 
3688
3689     /* sign adjust left side */
3690     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3691     MOVA(l);
3692
3693     lbl = newiTempLabel(NULL);
3694     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3695     pic16_emitcode("cpl","a");   
3696     pic16_emitcode("inc","a");
3697     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3698
3699     /* now the multiplication */
3700     pic16_emitcode("div","ab");
3701     /* we are interested in the lower order
3702     only */
3703     lbl = newiTempLabel(NULL);
3704     pic16_emitcode("pop","acc");   
3705     /* if there was an over flow we don't 
3706     adjust the sign of the result */
3707     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3708     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3709     CLRC ;
3710     pic16_emitcode("clr","a");
3711     pic16_emitcode("subb","a,b");
3712     pic16_emitcode("mov","b,a");
3713     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3714
3715     /* now we are done */
3716     pic16_aopPut(AOP(result),"b",0);
3717
3718 }
3719
3720 /*-----------------------------------------------------------------*/
3721 /* genMod - generates code for division                            */
3722 /*-----------------------------------------------------------------*/
3723 static void genMod (iCode *ic)
3724 {
3725     operand *left = IC_LEFT(ic);
3726     operand *right = IC_RIGHT(ic);
3727     operand *result= IC_RESULT(ic);  
3728
3729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3730     /* assign the amsops */
3731     pic16_aopOp (left,ic,FALSE);
3732     pic16_aopOp (right,ic,FALSE);
3733     pic16_aopOp (result,ic,TRUE);
3734
3735     /* special cases first */
3736     /* both are bits */
3737     if (AOP_TYPE(left) == AOP_CRY &&
3738         AOP_TYPE(right)== AOP_CRY) {
3739         genModbits(left,right,result);
3740         goto release ;
3741     }
3742
3743     /* if both are of size == 1 */
3744     if (AOP_SIZE(left) == 1 &&
3745         AOP_SIZE(right) == 1 ) {
3746         genModOneByte(left,right,result);
3747         goto release ;
3748     }
3749
3750     /* should have been converted to function call */
3751     assert(0);
3752
3753 release :
3754     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3755     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3756     pic16_freeAsmop(result,NULL,ic,TRUE); 
3757 }
3758
3759 /*-----------------------------------------------------------------*/
3760 /* genIfxJump :- will create a jump depending on the ifx           */
3761 /*-----------------------------------------------------------------*/
3762 /*
3763   note: May need to add parameter to indicate when a variable is in bit space.
3764 */
3765 static void genIfxJump (iCode *ic, char *jval)
3766 {
3767
3768     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3769     /* if true label then we jump if condition
3770     supplied is true */
3771     if ( IC_TRUE(ic) ) {
3772
3773         if(strcmp(jval,"a") == 0)
3774           emitSKPZ;
3775         else if (strcmp(jval,"c") == 0)
3776           emitSKPC;
3777         else {
3778           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3779           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3780         }
3781
3782         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3783         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3784
3785     }
3786     else {
3787         /* false label is present */
3788         if(strcmp(jval,"a") == 0)
3789           emitSKPNZ;
3790         else if (strcmp(jval,"c") == 0)
3791           emitSKPNC;
3792         else {
3793           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3794           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3795         }
3796
3797         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3798         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3799
3800     }
3801
3802
3803     /* mark the icode as generated */
3804     ic->generated = 1;
3805 }
3806
3807 /*-----------------------------------------------------------------*/
3808 /* genSkip                                                         */
3809 /*-----------------------------------------------------------------*/
3810 static void genSkip(iCode *ifx,int status_bit)
3811 {
3812   if(!ifx)
3813     return;
3814
3815   if ( IC_TRUE(ifx) ) {
3816     switch(status_bit) {
3817     case 'z':
3818       emitSKPNZ;
3819       break;
3820
3821     case 'c':
3822       emitSKPNC;
3823       break;
3824
3825     case 'd':
3826       emitSKPDC;
3827       break;
3828
3829     }
3830
3831     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3832     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3833
3834   } else {
3835
3836     switch(status_bit) {
3837
3838     case 'z':
3839       emitSKPZ;
3840       break;
3841
3842     case 'c':
3843       emitSKPC;
3844       break;
3845
3846     case 'd':
3847       emitSKPDC;
3848       break;
3849     }
3850     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3851     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3852
3853   }
3854
3855 }
3856
3857 /*-----------------------------------------------------------------*/
3858 /* genSkipc                                                        */
3859 /*-----------------------------------------------------------------*/
3860 static void genSkipc(resolvedIfx *rifx)
3861 {
3862   if(!rifx)
3863     return;
3864
3865   if(rifx->condition)
3866     emitSKPC;
3867   else
3868     emitSKPNC;
3869
3870   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3871   rifx->generated = 1;
3872 }
3873
3874 /*-----------------------------------------------------------------*/
3875 /* genSkipz2                                                       */
3876 /*-----------------------------------------------------------------*/
3877 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3878 {
3879   if(!rifx)
3880     return;
3881
3882   if( (rifx->condition ^ invert_condition) & 1)
3883     emitSKPZ;
3884   else
3885     emitSKPNZ;
3886
3887   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3888   rifx->generated = 1;
3889 }
3890
3891 /*-----------------------------------------------------------------*/
3892 /* genSkipz                                                        */
3893 /*-----------------------------------------------------------------*/
3894 static void genSkipz(iCode *ifx, int condition)
3895 {
3896   if(!ifx)
3897     return;
3898
3899   if(condition)
3900     emitSKPNZ;
3901   else
3902     emitSKPZ;
3903
3904   if ( IC_TRUE(ifx) )
3905     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3906   else
3907     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3908
3909   if ( IC_TRUE(ifx) )
3910     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3911   else
3912     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3913
3914 }
3915 /*-----------------------------------------------------------------*/
3916 /* genSkipCond                                                     */
3917 /*-----------------------------------------------------------------*/
3918 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3919 {
3920   if(!rifx)
3921     return;
3922
3923   if(rifx->condition)
3924     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3925   else
3926     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3927
3928
3929   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3930   rifx->generated = 1;
3931 }
3932
3933 #if 0
3934 /*-----------------------------------------------------------------*/
3935 /* genChkZeroes :- greater or less than comparison                 */
3936 /*     For each byte in a literal that is zero, inclusive or the   */
3937 /*     the corresponding byte in the operand with W                */
3938 /*     returns true if any of the bytes are zero                   */
3939 /*-----------------------------------------------------------------*/
3940 static int genChkZeroes(operand *op, int lit,  int size)
3941 {
3942
3943   int i;
3944   int flag =1;
3945
3946   while(size--) {
3947     i = (lit >> (size*8)) & 0xff;
3948
3949     if(i==0) {
3950       if(flag) 
3951         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3952       else
3953         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3954       flag = 0;
3955     }
3956   }
3957
3958   return (flag==0);
3959 }
3960 #endif
3961
3962 /*-----------------------------------------------------------------*/
3963 /* genCmp :- greater or less than comparison                       */
3964 /*-----------------------------------------------------------------*/
3965 static void genCmp (operand *left,operand *right,
3966                     operand *result, iCode *ifx, int sign)
3967 {
3968   int size; //, offset = 0 ;
3969   unsigned long lit = 0L,i = 0;
3970   resolvedIfx rFalseIfx;
3971   //  resolvedIfx rTrueIfx;
3972   symbol *truelbl;
3973   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3974 /*
3975   if(ifx) {
3976     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3977     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3978   }
3979 */
3980
3981   resolveIfx(&rFalseIfx,ifx);
3982   truelbl  = newiTempLabel(NULL);
3983   size = max(AOP_SIZE(left),AOP_SIZE(right));
3984
3985   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3986
3987 #define _swapp
3988
3989   /* if literal is on the right then swap with left */
3990   if ((AOP_TYPE(right) == AOP_LIT)) {
3991     operand *tmp = right ;
3992     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3993     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3994 #ifdef _swapp
3995
3996     lit = (lit - 1) & mask;
3997     right = left;
3998     left = tmp;
3999     rFalseIfx.condition ^= 1;
4000 #endif
4001
4002   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4003     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4004   }
4005
4006
4007   //if(IC_TRUE(ifx) == NULL)
4008   /* if left & right are bit variables */
4009   if (AOP_TYPE(left) == AOP_CRY &&
4010       AOP_TYPE(right) == AOP_CRY ) {
4011     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4012     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4013   } else {
4014     /* subtract right from left if at the
4015        end the carry flag is set then we know that
4016        left is greater than right */
4017
4018     //    {
4019
4020     symbol *lbl  = newiTempLabel(NULL);
4021
4022 #ifndef _swapp
4023     if(AOP_TYPE(right) == AOP_LIT) {
4024
4025       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4026
4027       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4028
4029       /* special cases */
4030
4031       if(lit == 0) {
4032
4033         if(sign != 0) 
4034           genSkipCond(&rFalseIfx,left,size-1,7);
4035         else 
4036           /* no need to compare to 0...*/
4037           /* NOTE: this is a de-generate compare that most certainly 
4038            *       creates some dead code. */
4039           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4040
4041         if(ifx) ifx->generated = 1;
4042         return;
4043
4044       }
4045       size--;
4046
4047       if(size == 0) {
4048         //i = (lit >> (size*8)) & 0xff;
4049         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4050         
4051         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4052
4053         i = ((0-lit) & 0xff);
4054         if(sign) {
4055           if( i == 0x81) { 
4056             /* lit is 0x7f, all signed chars are less than
4057              * this except for 0x7f itself */
4058             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4059             genSkipz2(&rFalseIfx,0);
4060           } else {
4061             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4062             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4063             genSkipc(&rFalseIfx);
4064           }
4065
4066         } else {
4067           if(lit == 1) {
4068             genSkipz2(&rFalseIfx,1);
4069           } else {
4070             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4071             genSkipc(&rFalseIfx);
4072           }
4073         }
4074
4075         if(ifx) ifx->generated = 1;
4076         return;
4077       }
4078
4079       /* chars are out of the way. now do ints and longs */
4080
4081
4082       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4083         
4084       /* special cases */
4085
4086       if(sign) {
4087
4088         if(lit == 0) {
4089           genSkipCond(&rFalseIfx,left,size,7);
4090           if(ifx) ifx->generated = 1;
4091           return;
4092         }
4093
4094         if(lit <0x100) {
4095           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4096
4097           //rFalseIfx.condition ^= 1;
4098           //genSkipCond(&rFalseIfx,left,size,7);
4099           //rFalseIfx.condition ^= 1;
4100
4101           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4102           if(rFalseIfx.condition)
4103             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4104           else
4105             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4106
4107           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4108           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4109           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4110
4111           while(size > 1)
4112             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4113
4114           if(rFalseIfx.condition) {
4115             emitSKPZ;
4116             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4117
4118           } else {
4119             emitSKPNZ;
4120           }
4121
4122           genSkipc(&rFalseIfx);
4123           pic16_emitpLabel(truelbl->key);
4124           if(ifx) ifx->generated = 1;
4125           return;
4126
4127         }
4128
4129         if(size == 1) {
4130
4131           if( (lit & 0xff) == 0) {
4132             /* lower byte is zero */
4133             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4134             i = ((lit >> 8) & 0xff) ^0x80;
4135             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4136             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4137             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4138             genSkipc(&rFalseIfx);
4139
4140
4141             if(ifx) ifx->generated = 1;
4142             return;
4143
4144           }
4145         } else {
4146           /* Special cases for signed longs */
4147           if( (lit & 0xffffff) == 0) {
4148             /* lower byte is zero */
4149             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4150             i = ((lit >> 8*3) & 0xff) ^0x80;
4151             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4152             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4153             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4154             genSkipc(&rFalseIfx);
4155
4156
4157             if(ifx) ifx->generated = 1;
4158             return;
4159
4160           }
4161
4162         }
4163
4164
4165         if(lit & (0x80 << (size*8))) {
4166           /* lit is negative */
4167           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4168
4169           //genSkipCond(&rFalseIfx,left,size,7);
4170
4171           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4172
4173           if(rFalseIfx.condition)
4174             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4175           else
4176             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4177
4178
4179         } else {
4180           /* lit is positive */
4181           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4182           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4183           if(rFalseIfx.condition)
4184             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4185           else
4186             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4187
4188         }
4189
4190         /*
4191           This works, but is only good for ints.
4192           It also requires a "known zero" register.
4193           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4194           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4195           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4196           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4197           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4198           genSkipc(&rFalseIfx);
4199
4200           pic16_emitpLabel(truelbl->key);
4201           if(ifx) ifx->generated = 1;
4202           return;
4203         **/
4204           
4205         /* There are no more special cases, so perform a general compare */
4206   
4207         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4208         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4209
4210         while(size--) {
4211
4212           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4213           emitSKPNZ;
4214           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4215         }
4216         //rFalseIfx.condition ^= 1;
4217         genSkipc(&rFalseIfx);
4218
4219         pic16_emitpLabel(truelbl->key);
4220
4221         if(ifx) ifx->generated = 1;
4222         return;
4223
4224
4225       }
4226
4227
4228       /* sign is out of the way. So now do an unsigned compare */
4229       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4230
4231
4232       /* General case - compare to an unsigned literal on the right.*/
4233
4234       i = (lit >> (size*8)) & 0xff;
4235       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4236       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4237       while(size--) {
4238         i = (lit >> (size*8)) & 0xff;
4239
4240         if(i) {
4241           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4242           emitSKPNZ;
4243           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4244         } else {
4245           /* this byte of the lit is zero, 
4246            *if it's not the last then OR in the variable */
4247           if(size)
4248             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4249         }
4250       }
4251
4252
4253       pic16_emitpLabel(lbl->key);
4254       //if(emitFinalCheck)
4255       genSkipc(&rFalseIfx);
4256       if(sign)
4257         pic16_emitpLabel(truelbl->key);
4258
4259       if(ifx) ifx->generated = 1;
4260       return;
4261
4262
4263     }
4264 #endif  // _swapp
4265
4266     if(AOP_TYPE(left) == AOP_LIT) {
4267       //symbol *lbl = newiTempLabel(NULL);
4268
4269       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4270
4271
4272       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4273
4274       /* Special cases */
4275       if((lit == 0) && (sign == 0)){
4276
4277         size--;
4278         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4279         while(size) 
4280           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4281
4282         genSkipz2(&rFalseIfx,0);
4283         if(ifx) ifx->generated = 1;
4284         return;
4285       }
4286
4287       if(size==1) {
4288         /* Special cases */
4289         lit &= 0xff;
4290         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4291           /* degenerate compare can never be true */
4292           if(rFalseIfx.condition == 0)
4293             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4294
4295           if(ifx) ifx->generated = 1;
4296           return;
4297         }
4298
4299         if(sign) {
4300           /* signed comparisons to a literal byte */
4301
4302           int lp1 = (lit+1) & 0xff;
4303
4304           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4305           switch (lp1) {
4306           case 0:
4307             rFalseIfx.condition ^= 1;
4308             genSkipCond(&rFalseIfx,right,0,7);
4309             break;
4310           case 0x7f:
4311             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4312             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4313             genSkipz2(&rFalseIfx,1);
4314             break;
4315           default:
4316             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4317             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4318             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4319             rFalseIfx.condition ^= 1;
4320             genSkipc(&rFalseIfx);
4321             break;
4322           }
4323         } else {
4324           /* unsigned comparisons to a literal byte */
4325
4326           switch(lit & 0xff ) {
4327           case 0:
4328             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4329             genSkipz2(&rFalseIfx,0);
4330             break;
4331           case 0x7f:
4332             rFalseIfx.condition ^= 1;
4333             genSkipCond(&rFalseIfx,right,0,7);
4334             break;
4335
4336           default:
4337             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4338             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4339             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4340             rFalseIfx.condition ^= 1;
4341             if (AOP_TYPE(result) == AOP_CRY)
4342               genSkipc(&rFalseIfx);
4343             else {
4344               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4345               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4346             }         
4347             break;
4348           }
4349         }
4350
4351         if(ifx) ifx->generated = 1;
4352         //goto check_carry;
4353         return;
4354
4355       } else {
4356
4357         /* Size is greater than 1 */
4358
4359         if(sign) {
4360           int lp1 = lit+1;
4361
4362           size--;
4363
4364           if(lp1 == 0) {
4365             /* this means lit = 0xffffffff, or -1 */
4366
4367
4368             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4369             rFalseIfx.condition ^= 1;
4370             genSkipCond(&rFalseIfx,right,size,7);
4371             if(ifx) ifx->generated = 1;
4372             return;
4373           }
4374
4375           if(lit == 0) {
4376             int s = size;
4377
4378             if(rFalseIfx.condition) {
4379               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4380               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4381             }
4382
4383             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4384             while(size--)
4385               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4386
4387
4388             emitSKPZ;
4389             if(rFalseIfx.condition) {
4390               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4391               pic16_emitpLabel(truelbl->key);
4392             }else {
4393               rFalseIfx.condition ^= 1;
4394               genSkipCond(&rFalseIfx,right,s,7);
4395             }
4396
4397             if(ifx) ifx->generated = 1;
4398             return;
4399           }
4400
4401           if((size == 1) &&  (0 == (lp1&0xff))) {
4402             /* lower byte of signed word is zero */
4403             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4404             i = ((lp1 >> 8) & 0xff) ^0x80;
4405             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4406             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4407             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4408             rFalseIfx.condition ^= 1;
4409             genSkipc(&rFalseIfx);
4410
4411
4412             if(ifx) ifx->generated = 1;
4413             return;
4414           }
4415
4416           if(lit & (0x80 << (size*8))) {
4417             /* Lit is less than zero */
4418             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4419             //rFalseIfx.condition ^= 1;
4420             //genSkipCond(&rFalseIfx,left,size,7);
4421             //rFalseIfx.condition ^= 1;
4422             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4423             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4424
4425             if(rFalseIfx.condition)
4426               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4427             else
4428               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4429
4430
4431           } else {
4432             /* Lit is greater than or equal to zero */
4433             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4434             //rFalseIfx.condition ^= 1;
4435             //genSkipCond(&rFalseIfx,right,size,7);
4436             //rFalseIfx.condition ^= 1;
4437
4438             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4439             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4440
4441             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4442             if(rFalseIfx.condition)
4443               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4444             else
4445               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4446
4447           }
4448
4449
4450           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4451           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4452
4453           while(size--) {
4454
4455             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4456             emitSKPNZ;
4457             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4458           }
4459           rFalseIfx.condition ^= 1;
4460           //rFalseIfx.condition = 1;
4461           genSkipc(&rFalseIfx);
4462
4463           pic16_emitpLabel(truelbl->key);
4464
4465           if(ifx) ifx->generated = 1;
4466           return;
4467           // end of if (sign)
4468         } else {
4469
4470           /* compare word or long to an unsigned literal on the right.*/
4471
4472
4473           size--;
4474           if(lit < 0xff) {
4475             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4476             switch (lit) {
4477             case 0:
4478               break; /* handled above */
4479 /*
4480             case 0xff:
4481               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4482               while(size--)
4483                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4484               genSkipz2(&rFalseIfx,0);
4485               break;
4486 */
4487             default:
4488               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4489               while(--size)
4490                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4491
4492               emitSKPZ;
4493               if(rFalseIfx.condition)
4494                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4495               else
4496                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4497
4498
4499               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4500               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4501
4502               rFalseIfx.condition ^= 1;
4503               genSkipc(&rFalseIfx);
4504             }
4505
4506             pic16_emitpLabel(truelbl->key);
4507
4508             if(ifx) ifx->generated = 1;
4509             return;
4510           }
4511
4512
4513           lit++;
4514           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4515           i = (lit >> (size*8)) & 0xff;
4516
4517           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4518           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4519
4520           while(size--) {
4521             i = (lit >> (size*8)) & 0xff;
4522
4523             if(i) {
4524               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4525               emitSKPNZ;
4526               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4527             } else {
4528               /* this byte of the lit is zero, 
4529                *if it's not the last then OR in the variable */
4530               if(size)
4531                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4532             }
4533           }
4534
4535
4536           pic16_emitpLabel(lbl->key);
4537
4538           rFalseIfx.condition ^= 1;
4539           genSkipc(&rFalseIfx);
4540         }
4541
4542         if(sign)
4543           pic16_emitpLabel(truelbl->key);
4544         if(ifx) ifx->generated = 1;
4545         return;
4546       }
4547     }
4548     /* Compare two variables */
4549
4550     DEBUGpic16_emitcode(";sign","%d",sign);
4551
4552     size--;
4553     if(sign) {
4554       /* Sigh. thus sucks... */
4555       if(size) {
4556         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4557         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4558         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4559         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4560         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4561         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4562       } else {
4563         /* Signed char comparison */
4564         /* Special thanks to Nikolai Golovchenko for this snippet */
4565         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4566         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4567         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4568         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4569         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4570         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4571
4572         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4573         genSkipc(&rFalseIfx);
4574           
4575         if(ifx) ifx->generated = 1;
4576         return;
4577       }
4578
4579     } else {
4580
4581       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4582       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4583     }
4584
4585
4586     /* The rest of the bytes of a multi-byte compare */
4587     while (size) {
4588
4589       emitSKPZ;
4590       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4591       size--;
4592
4593       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4594       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4595
4596
4597     }
4598
4599     pic16_emitpLabel(lbl->key);
4600
4601     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4602     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4603         (AOP_TYPE(result) == AOP_REG)) {
4604       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4605       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4606     } else {
4607       genSkipc(&rFalseIfx);
4608     }         
4609     //genSkipc(&rFalseIfx);
4610     if(ifx) ifx->generated = 1;
4611
4612     return;
4613
4614   }
4615
4616   // check_carry:
4617   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4619     pic16_outBitC(result);
4620   } else {
4621     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4622     /* if the result is used in the next
4623        ifx conditional branch then generate
4624        code a little differently */
4625     if (ifx )
4626       genIfxJump (ifx,"c");
4627     else
4628       pic16_outBitC(result);
4629     /* leave the result in acc */
4630   }
4631
4632 }
4633
4634 /*-----------------------------------------------------------------*/
4635 /* genCmpGt :- greater than comparison                             */
4636 /*-----------------------------------------------------------------*/
4637 static void genCmpGt (iCode *ic, iCode *ifx)
4638 {
4639     operand *left, *right, *result;
4640     sym_link *letype , *retype;
4641     int sign ;
4642
4643     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4644     left = IC_LEFT(ic);
4645     right= IC_RIGHT(ic);
4646     result = IC_RESULT(ic);
4647
4648     letype = getSpec(operandType(left));
4649     retype =getSpec(operandType(right));
4650     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4651     /* assign the amsops */
4652     pic16_aopOp (left,ic,FALSE);
4653     pic16_aopOp (right,ic,FALSE);
4654     pic16_aopOp (result,ic,TRUE);
4655
4656     genCmp(right, left, result, ifx, sign);
4657
4658     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4659     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4660     pic16_freeAsmop(result,NULL,ic,TRUE); 
4661 }
4662
4663 /*-----------------------------------------------------------------*/
4664 /* genCmpLt - less than comparisons                                */
4665 /*-----------------------------------------------------------------*/
4666 static void genCmpLt (iCode *ic, iCode *ifx)
4667 {
4668     operand *left, *right, *result;
4669     sym_link *letype , *retype;
4670     int sign ;
4671
4672     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4673     left = IC_LEFT(ic);
4674     right= IC_RIGHT(ic);
4675     result = IC_RESULT(ic);
4676
4677     letype = getSpec(operandType(left));
4678     retype =getSpec(operandType(right));
4679     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4680
4681     /* assign the amsops */
4682     pic16_aopOp (left,ic,FALSE);
4683     pic16_aopOp (right,ic,FALSE);
4684     pic16_aopOp (result,ic,TRUE);
4685
4686     genCmp(left, right, result, ifx, sign);
4687
4688     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4689     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4690     pic16_freeAsmop(result,NULL,ic,TRUE); 
4691 }
4692
4693 /*-----------------------------------------------------------------*/
4694 /* genc16bit2lit - compare a 16 bit value to a literal             */
4695 /*-----------------------------------------------------------------*/
4696 static void genc16bit2lit(operand *op, int lit, int offset)
4697 {
4698   int i;
4699
4700   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4701   if( (lit&0xff) == 0) 
4702     i=1;
4703   else
4704     i=0;
4705
4706   switch( BYTEofLONG(lit,i)) { 
4707   case 0:
4708     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4709     break;
4710   case 1:
4711     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4712     break;
4713   case 0xff:
4714     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4715     break;
4716   default:
4717     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4718     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4719   }
4720
4721   i ^= 1;
4722
4723   switch( BYTEofLONG(lit,i)) { 
4724   case 0:
4725     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4726     break;
4727   case 1:
4728     emitSKPNZ;
4729     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4730     break;
4731   case 0xff:
4732     emitSKPNZ;
4733     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4734     break;
4735   default:
4736     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4737     emitSKPNZ;
4738     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4739
4740   }
4741
4742 }
4743
4744 /*-----------------------------------------------------------------*/
4745 /* gencjneshort - compare and jump if not equal                    */
4746 /*-----------------------------------------------------------------*/
4747 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4748 {
4749   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4750   int offset = 0;
4751   int res_offset = 0;  /* the result may be a different size then left or right */
4752   int res_size = AOP_SIZE(result);
4753   resolvedIfx rIfx;
4754   symbol *lbl;
4755
4756   unsigned long lit = 0L;
4757   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4758   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4759   if(result)
4760     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4761   resolveIfx(&rIfx,ifx);
4762   lbl =  newiTempLabel(NULL);
4763
4764
4765   /* if the left side is a literal or 
4766      if the right is in a pointer register and left 
4767      is not */
4768   if ((AOP_TYPE(left) == AOP_LIT) || 
4769       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4770     operand *t = right;
4771     right = left;
4772     left = t;
4773   }
4774   if(AOP_TYPE(right) == AOP_LIT)
4775     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4776
4777   /* if the right side is a literal then anything goes */
4778   if (AOP_TYPE(right) == AOP_LIT &&
4779       AOP_TYPE(left) != AOP_DIR ) {
4780     switch(size) {
4781     case 2:
4782       genc16bit2lit(left, lit, 0);
4783       emitSKPNZ;
4784       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4785       break;
4786     default:
4787       while (size--) {
4788         if(lit & 0xff) {
4789           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4790           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4791         } else {
4792           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4793         }
4794
4795         emitSKPNZ;
4796         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4797         offset++;
4798         if(res_offset < res_size-1)
4799           res_offset++;
4800         lit >>= 8;
4801       }
4802       break;
4803     }
4804   }
4805
4806   /* if the right side is in a register or in direct space or
4807      if the left is a pointer register & right is not */    
4808   else if (AOP_TYPE(right) == AOP_REG ||
4809            AOP_TYPE(right) == AOP_DIR || 
4810            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4811            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4812     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4813     int lbl_key = lbl->key;
4814
4815     if(result) {
4816       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4817       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4818     }else {
4819       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4820       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4821               __FUNCTION__,__LINE__);
4822       return;
4823     }
4824
4825 /*     switch(size) { */
4826 /*     case 2: */
4827 /*       genc16bit2lit(left, lit, 0); */
4828 /*       emitSKPNZ; */
4829 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4830 /*       break; */
4831 /*     default: */
4832     while (size--) {
4833       int emit_skip=1;
4834       if((AOP_TYPE(left) == AOP_DIR) && 
4835          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4836
4837         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4838         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4839
4840       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4841             
4842         switch (lit & 0xff) {
4843         case 0:
4844           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4845           break;
4846         case 1:
4847           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4848           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4849           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4850           emit_skip=0;
4851           break;
4852         case 0xff:
4853           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4854           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4855           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4856           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4857           emit_skip=0;
4858           break;
4859         default:
4860           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4861           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4862         }
4863         lit >>= 8;
4864
4865       } else {
4866         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4867       }
4868       if(emit_skip) {
4869         if(AOP_TYPE(result) == AOP_CRY) {
4870           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4871           if(rIfx.condition)
4872             emitSKPNZ;
4873           else
4874             emitSKPZ;
4875           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4876         } else {
4877           /* fix me. probably need to check result size too */
4878           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4879           if(rIfx.condition)
4880             emitSKPZ;
4881           else
4882             emitSKPNZ;
4883           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4884           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4885         }
4886         if(ifx)
4887           ifx->generated=1;
4888       }
4889       emit_skip++;
4890       offset++;
4891       if(res_offset < res_size-1)
4892         res_offset++;
4893     }
4894 /*       break; */
4895 /*     } */
4896   } else if(AOP_TYPE(right) == AOP_REG &&
4897             AOP_TYPE(left) != AOP_DIR){
4898
4899     while(size--) {
4900       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4901       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4902       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4903       if(rIfx.condition)
4904         emitSKPNZ;
4905       else
4906         emitSKPZ;
4907       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4908       offset++;
4909       if(res_offset < res_size-1)
4910         res_offset++;
4911     }
4912       
4913   }else{
4914     /* right is a pointer reg need both a & b */
4915     while(size--) {
4916       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4917       if(strcmp(l,"b"))
4918         pic16_emitcode("mov","b,%s",l);
4919       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4920       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4921       offset++;
4922     }
4923   }
4924
4925   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4926   if(!rIfx.condition)
4927     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4928
4929   pic16_emitpLabel(lbl->key);
4930
4931   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4932
4933   if(ifx)
4934     ifx->generated = 1;
4935 }
4936
4937 #if 0
4938 /*-----------------------------------------------------------------*/
4939 /* gencjne - compare and jump if not equal                         */
4940 /*-----------------------------------------------------------------*/
4941 static void gencjne(operand *left, operand *right, iCode *ifx)
4942 {
4943     symbol *tlbl  = newiTempLabel(NULL);
4944
4945     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4946     gencjneshort(left, right, lbl);
4947
4948     pic16_emitcode("mov","a,%s",one);
4949     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4950     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4951     pic16_emitcode("clr","a");
4952     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4953
4954     pic16_emitpLabel(lbl->key);
4955     pic16_emitpLabel(tlbl->key);
4956
4957 }
4958 #endif
4959
4960 /*-----------------------------------------------------------------*/
4961 /* genCmpEq - generates code for equal to                          */
4962 /*-----------------------------------------------------------------*/
4963 static void genCmpEq (iCode *ic, iCode *ifx)
4964 {
4965     operand *left, *right, *result;
4966     unsigned long lit = 0L;
4967     int size,offset=0;
4968
4969     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4970
4971     if(ifx)
4972       DEBUGpic16_emitcode ("; ifx is non-null","");
4973     else
4974       DEBUGpic16_emitcode ("; ifx is null","");
4975
4976     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4977     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4978     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4979
4980     size = max(AOP_SIZE(left),AOP_SIZE(right));
4981
4982     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4983
4984     /* if literal, literal on the right or 
4985     if the right is in a pointer register and left 
4986     is not */
4987     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4988         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4989       operand *tmp = right ;
4990       right = left;
4991       left = tmp;
4992     }
4993
4994
4995     if(ifx && !AOP_SIZE(result)){
4996         symbol *tlbl;
4997         /* if they are both bit variables */
4998         if (AOP_TYPE(left) == AOP_CRY &&
4999             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5000             if(AOP_TYPE(right) == AOP_LIT){
5001                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5002                 if(lit == 0L){
5003                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5004                     pic16_emitcode("cpl","c");
5005                 } else if(lit == 1L) {
5006                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5007                 } else {
5008                     pic16_emitcode("clr","c");
5009                 }
5010                 /* AOP_TYPE(right) == AOP_CRY */
5011             } else {
5012                 symbol *lbl = newiTempLabel(NULL);
5013                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5014                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5015                 pic16_emitcode("cpl","c");
5016                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5017             }
5018             /* if true label then we jump if condition
5019             supplied is true */
5020             tlbl = newiTempLabel(NULL);
5021             if ( IC_TRUE(ifx) ) {
5022                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5023                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5024             } else {
5025                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5026                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5027             }
5028             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5029
5030             {
5031               /* left and right are both bit variables, result is carry */
5032               resolvedIfx rIfx;
5033               
5034               resolveIfx(&rIfx,ifx);
5035
5036               pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5037               pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5038               pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5039               pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5040               genSkipz2(&rIfx,0);
5041             }
5042         } else {
5043
5044           /* They're not both bit variables. Is the right a literal? */
5045           if(AOP_TYPE(right) == AOP_LIT) {
5046             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5047             
5048             switch(size) {
5049
5050             case 1:
5051               switch(lit & 0xff) {
5052               case 1:
5053                 if ( IC_TRUE(ifx) ) {
5054                   pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5055                   emitSKPNZ;
5056                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5057                 } else {
5058                   pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5059                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5060                 }
5061                 break;
5062               case 0xff:
5063                 if ( IC_TRUE(ifx) ) {
5064                   pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5065                   emitSKPNZ;
5066                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5067                 } else {
5068                   pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5069                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5070                 }
5071                 break;
5072               default:
5073                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5074                 if(lit)
5075                   pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5076                 genSkip(ifx,'z');
5077               }
5078
5079
5080               /* end of size == 1 */
5081               break;
5082               
5083             case 2:
5084               genc16bit2lit(left,lit,offset);
5085               genSkip(ifx,'z');
5086               break;
5087               /* end of size == 2 */
5088
5089             default:
5090               /* size is 4 */
5091               if(lit==0) {
5092                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5093                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5094                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5095                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5096
5097               } else {
5098
5099                 /* search for patterns that can be optimized */
5100
5101                 genc16bit2lit(left,lit,0);
5102                 lit >>= 16;
5103                 if(lit) {
5104                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
5105                   //genSkip(ifx,'z');
5106                   genc16bit2lit(left,lit,2);
5107                 } else {
5108                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5109                   pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5110
5111                 }
5112                 
5113               }
5114
5115               genSkip(ifx,'z');
5116             }
5117           
5118             ifx->generated = 1;
5119             goto release ;
5120             
5121
5122           } else if(AOP_TYPE(right) == AOP_CRY ) {
5123             /* we know the left is not a bit, but that the right is */
5124             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5125             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5126                       pic16_popGet(AOP(right),offset));
5127             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5128
5129             /* if the two are equal, then W will be 0 and the Z bit is set
5130              * we could test Z now, or go ahead and check the high order bytes if
5131              * the variable we're comparing is larger than a byte. */
5132
5133             while(--size)
5134               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5135
5136             if ( IC_TRUE(ifx) ) {
5137               emitSKPNZ;
5138               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5139               pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5140             } else {
5141               emitSKPZ;
5142               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5143               pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5144             }
5145
5146           } else {
5147             /* They're both variables that are larger than bits */
5148             int s = size;
5149
5150             tlbl = newiTempLabel(NULL);
5151
5152             while(size--) {
5153               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5154               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5155
5156               if ( IC_TRUE(ifx) ) {
5157                 if(size) {
5158                   emitSKPZ;
5159                 
5160                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5161
5162                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5163                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5164                 } else {
5165                   emitSKPNZ;
5166
5167                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5168
5169
5170                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5171                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5172                 }
5173               } else {
5174                 emitSKPZ;
5175
5176                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5177
5178                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5179                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5180               }
5181               offset++;
5182             }
5183             if(s>1 && IC_TRUE(ifx)) {
5184               pic16_emitpLabel(tlbl->key);
5185               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5186             }
5187           }
5188         }
5189         /* mark the icode as generated */
5190         ifx->generated = 1;
5191         goto release ;
5192     }
5193
5194     /* if they are both bit variables */
5195     if (AOP_TYPE(left) == AOP_CRY &&
5196         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5197         if(AOP_TYPE(right) == AOP_LIT){
5198             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5199             if(lit == 0L){
5200                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5201                 pic16_emitcode("cpl","c");
5202             } else if(lit == 1L) {
5203                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5204             } else {
5205                 pic16_emitcode("clr","c");
5206             }
5207             /* AOP_TYPE(right) == AOP_CRY */
5208         } else {
5209             symbol *lbl = newiTempLabel(NULL);
5210             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5211             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5212             pic16_emitcode("cpl","c");
5213             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5214         }
5215         /* c = 1 if egal */
5216         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5217             pic16_outBitC(result);
5218             goto release ;
5219         }
5220         if (ifx) {
5221             genIfxJump (ifx,"c");
5222             goto release ;
5223         }
5224         /* if the result is used in an arithmetic operation
5225         then put the result in place */
5226         pic16_outBitC(result);
5227     } else {
5228       
5229       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5230       gencjne(left,right,result,ifx);
5231 /*
5232       if(ifx) 
5233         gencjne(left,right,newiTempLabel(NULL));
5234       else {
5235         if(IC_TRUE(ifx)->key)
5236           gencjne(left,right,IC_TRUE(ifx)->key);
5237         else
5238           gencjne(left,right,IC_FALSE(ifx)->key);
5239         ifx->generated = 1;
5240         goto release ;
5241       }
5242       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5243         pic16_aopPut(AOP(result),"a",0);
5244         goto release ;
5245       }
5246
5247       if (ifx) {
5248         genIfxJump (ifx,"a");
5249         goto release ;
5250       }
5251 */
5252       /* if the result is used in an arithmetic operation
5253          then put the result in place */
5254 /*
5255       if (AOP_TYPE(result) != AOP_CRY) 
5256         pic16_outAcc(result);
5257 */
5258       /* leave the result in acc */
5259     }
5260
5261 release:
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 /* ifxForOp - returns the icode containing the ifx for operand     */
5269 /*-----------------------------------------------------------------*/
5270 static iCode *ifxForOp ( operand *op, iCode *ic )
5271 {
5272     /* if true symbol then needs to be assigned */
5273     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5274     if (IS_TRUE_SYMOP(op))
5275         return NULL ;
5276
5277     /* if this has register type condition and
5278     the next instruction is ifx with the same operand
5279     and live to of the operand is upto the ifx only then */
5280     if (ic->next &&
5281         ic->next->op == IFX &&
5282         IC_COND(ic->next)->key == op->key &&
5283         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5284         return ic->next;
5285
5286     if (ic->next &&
5287         ic->next->op == IFX &&
5288         IC_COND(ic->next)->key == op->key) {
5289       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5290       return ic->next;
5291     }
5292
5293     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5294     if (ic->next &&
5295         ic->next->op == IFX)
5296       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5297
5298     if (ic->next &&
5299         ic->next->op == IFX &&
5300         IC_COND(ic->next)->key == op->key) {
5301       DEBUGpic16_emitcode ("; "," key is okay");
5302       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5303                            OP_SYMBOL(op)->liveTo,
5304                            ic->next->seq);
5305     }
5306
5307
5308     return NULL;
5309 }
5310 /*-----------------------------------------------------------------*/
5311 /* genAndOp - for && operation                                     */
5312 /*-----------------------------------------------------------------*/
5313 static void genAndOp (iCode *ic)
5314 {
5315     operand *left,*right, *result;
5316 /*     symbol *tlbl; */
5317
5318     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5319     /* note here that && operations that are in an
5320     if statement are taken away by backPatchLabels
5321     only those used in arthmetic operations remain */
5322     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5323     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5324     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5325
5326     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5327
5328     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5329     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5330     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5331
5332     /* if both are bit variables */
5333 /*     if (AOP_TYPE(left) == AOP_CRY && */
5334 /*         AOP_TYPE(right) == AOP_CRY ) { */
5335 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5336 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5337 /*         pic16_outBitC(result); */
5338 /*     } else { */
5339 /*         tlbl = newiTempLabel(NULL); */
5340 /*         pic16_toBoolean(left);     */
5341 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5342 /*         pic16_toBoolean(right); */
5343 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5344 /*         pic16_outBitAcc(result); */
5345 /*     } */
5346
5347     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5348     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5349     pic16_freeAsmop(result,NULL,ic,TRUE);
5350 }
5351
5352
5353 /*-----------------------------------------------------------------*/
5354 /* genOrOp - for || operation                                      */
5355 /*-----------------------------------------------------------------*/
5356 /*
5357   tsd pic port -
5358   modified this code, but it doesn't appear to ever get called
5359 */
5360
5361 static void genOrOp (iCode *ic)
5362 {
5363     operand *left,*right, *result;
5364     symbol *tlbl;
5365
5366     /* note here that || operations that are in an
5367     if statement are taken away by backPatchLabels
5368     only those used in arthmetic operations remain */
5369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5370     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5371     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5372     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5373
5374     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5375
5376     /* if both are bit variables */
5377     if (AOP_TYPE(left) == AOP_CRY &&
5378         AOP_TYPE(right) == AOP_CRY ) {
5379       pic16_emitcode("clrc","");
5380       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5381                AOP(left)->aopu.aop_dir,
5382                AOP(left)->aopu.aop_dir);
5383       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5384                AOP(right)->aopu.aop_dir,
5385                AOP(right)->aopu.aop_dir);
5386       pic16_emitcode("setc","");
5387
5388     } else {
5389         tlbl = newiTempLabel(NULL);
5390         pic16_toBoolean(left);
5391         emitSKPZ;
5392         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5393         pic16_toBoolean(right);
5394         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5395
5396         pic16_outBitAcc(result);
5397     }
5398
5399     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5400     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5401     pic16_freeAsmop(result,NULL,ic,TRUE);            
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* isLiteralBit - test if lit == 2^n                               */
5406 /*-----------------------------------------------------------------*/
5407 static int isLiteralBit(unsigned long lit)
5408 {
5409     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5410     0x100L,0x200L,0x400L,0x800L,
5411     0x1000L,0x2000L,0x4000L,0x8000L,
5412     0x10000L,0x20000L,0x40000L,0x80000L,
5413     0x100000L,0x200000L,0x400000L,0x800000L,
5414     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5415     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5416     int idx;
5417     
5418     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5419     for(idx = 0; idx < 32; idx++)
5420         if(lit == pw[idx])
5421             return idx+1;
5422     return 0;
5423 }
5424
5425 /*-----------------------------------------------------------------*/
5426 /* continueIfTrue -                                                */
5427 /*-----------------------------------------------------------------*/
5428 static void continueIfTrue (iCode *ic)
5429 {
5430     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5431     if(IC_TRUE(ic))
5432         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5433     ic->generated = 1;
5434 }
5435
5436 /*-----------------------------------------------------------------*/
5437 /* jmpIfTrue -                                                     */
5438 /*-----------------------------------------------------------------*/
5439 static void jumpIfTrue (iCode *ic)
5440 {
5441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5442     if(!IC_TRUE(ic))
5443         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5444     ic->generated = 1;
5445 }
5446
5447 /*-----------------------------------------------------------------*/
5448 /* jmpTrueOrFalse -                                                */
5449 /*-----------------------------------------------------------------*/
5450 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5451 {
5452     // ugly but optimized by peephole
5453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5454     if(IC_TRUE(ic)){
5455         symbol *nlbl = newiTempLabel(NULL);
5456         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5457         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5458         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5459         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5460     }
5461     else{
5462         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5463         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5464     }
5465     ic->generated = 1;
5466 }
5467
5468 /*-----------------------------------------------------------------*/
5469 /* genAnd  - code for and                                          */
5470 /*-----------------------------------------------------------------*/
5471 static void genAnd (iCode *ic, iCode *ifx)
5472 {
5473   operand *left, *right, *result;
5474   int size, offset=0;  
5475   unsigned long lit = 0L;
5476   int bytelit = 0;
5477   resolvedIfx rIfx;
5478
5479
5480   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5481   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5482   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5483   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5484
5485   resolveIfx(&rIfx,ifx);
5486
5487   /* if left is a literal & right is not then exchange them */
5488   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5489       AOP_NEEDSACC(left)) {
5490     operand *tmp = right ;
5491     right = left;
5492     left = tmp;
5493   }
5494
5495   /* if result = right then exchange them */
5496   if(pic16_sameRegs(AOP(result),AOP(right))){
5497     operand *tmp = right ;
5498     right = left;
5499     left = tmp;
5500   }
5501
5502   /* if right is bit then exchange them */
5503   if (AOP_TYPE(right) == AOP_CRY &&
5504       AOP_TYPE(left) != AOP_CRY){
5505     operand *tmp = right ;
5506     right = left;
5507     left = tmp;
5508   }
5509   if(AOP_TYPE(right) == AOP_LIT)
5510     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5511
5512   size = AOP_SIZE(result);
5513
5514   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5515
5516   // if(bit & yy)
5517   // result = bit & yy;
5518   if (AOP_TYPE(left) == AOP_CRY){
5519     // c = bit & literal;
5520     if(AOP_TYPE(right) == AOP_LIT){
5521       if(lit & 1) {
5522         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5523           // no change
5524           goto release;
5525         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5526       } else {
5527         // bit(result) = 0;
5528         if(size && (AOP_TYPE(result) == AOP_CRY)){
5529           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5530           goto release;
5531         }
5532         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5533           jumpIfTrue(ifx);
5534           goto release;
5535         }
5536         pic16_emitcode("clr","c");
5537       }
5538     } else {
5539       if (AOP_TYPE(right) == AOP_CRY){
5540         // c = bit & bit;
5541         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5542         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5543       } else {
5544         // c = bit & val;
5545         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5546         // c = lsb
5547         pic16_emitcode("rrc","a");
5548         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5549       }
5550     }
5551     // bit = c
5552     // val = c
5553     if(size)
5554       pic16_outBitC(result);
5555     // if(bit & ...)
5556     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5557       genIfxJump(ifx, "c");           
5558     goto release ;
5559   }
5560
5561   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5562   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5563   if((AOP_TYPE(right) == AOP_LIT) &&
5564      (AOP_TYPE(result) == AOP_CRY) &&
5565      (AOP_TYPE(left) != AOP_CRY)){
5566     int posbit = isLiteralBit(lit);
5567     /* left &  2^n */
5568     if(posbit){
5569       posbit--;
5570       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5571       // bit = left & 2^n
5572       if(size)
5573         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5574       // if(left &  2^n)
5575       else{
5576         if(ifx){
5577 /*
5578           if(IC_TRUE(ifx)) {
5579             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5580             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5581           } else {
5582             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5583             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5584           }
5585 */
5586           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5587                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5588           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5589           
5590           ifx->generated = 1;
5591         }
5592         goto release;
5593       }
5594     } else {
5595       symbol *tlbl = newiTempLabel(NULL);
5596       int sizel = AOP_SIZE(left);
5597       if(size)
5598         pic16_emitcode("setb","c");
5599       while(sizel--){
5600         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5601           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5602           // byte ==  2^n ?
5603           if((posbit = isLiteralBit(bytelit)) != 0)
5604             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5605           else{
5606             if(bytelit != 0x0FFL)
5607               pic16_emitcode("anl","a,%s",
5608                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5609             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5610           }
5611         }
5612         offset++;
5613       }
5614       // bit = left & literal
5615       if(size){
5616         pic16_emitcode("clr","c");
5617         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5618       }
5619       // if(left & literal)
5620       else{
5621         if(ifx)
5622           jmpTrueOrFalse(ifx, tlbl);
5623         goto release ;
5624       }
5625     }
5626     pic16_outBitC(result);
5627     goto release ;
5628   }
5629
5630   /* if left is same as result */
5631   if(pic16_sameRegs(AOP(result),AOP(left))){
5632     int know_W = -1;
5633     for(;size--; offset++,lit>>=8) {
5634       if(AOP_TYPE(right) == AOP_LIT){
5635         switch(lit & 0xff) {
5636         case 0x00:
5637           /*  and'ing with 0 has clears the result */
5638 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5639           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5640           break;
5641         case 0xff:
5642           /* and'ing with 0xff is a nop when the result and left are the same */
5643           break;
5644
5645         default:
5646           {
5647             int p = my_powof2( (~lit) & 0xff );
5648             if(p>=0) {
5649               /* only one bit is set in the literal, so use a bcf instruction */
5650 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5651               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5652
5653             } else {
5654               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5655               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5656               if(know_W != (lit&0xff))
5657                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5658               know_W = lit &0xff;
5659               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5660             }
5661           }    
5662         }
5663       } else {
5664         if (AOP_TYPE(left) == AOP_ACC) {
5665           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5666         } else {                    
5667           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5668           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5669
5670         }
5671       }
5672     }
5673
5674   } else {
5675     // left & result in different registers
5676     if(AOP_TYPE(result) == AOP_CRY){
5677       // result = bit
5678       // if(size), result in bit
5679       // if(!size && ifx), conditional oper: if(left & right)
5680       symbol *tlbl = newiTempLabel(NULL);
5681       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5682       if(size)
5683         pic16_emitcode("setb","c");
5684       while(sizer--){
5685         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5686         pic16_emitcode("anl","a,%s",
5687                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5688         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5689         offset++;
5690       }
5691       if(size){
5692         CLRC;
5693         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5694         pic16_outBitC(result);
5695       } else if(ifx)
5696         jmpTrueOrFalse(ifx, tlbl);
5697     } else {
5698       for(;(size--);offset++) {
5699         // normal case
5700         // result = left & right
5701         if(AOP_TYPE(right) == AOP_LIT){
5702           int t = (lit >> (offset*8)) & 0x0FFL;
5703           switch(t) { 
5704           case 0x00:
5705             pic16_emitcode("clrf","%s",
5706                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5707             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5708             break;
5709           case 0xff:
5710             pic16_emitcode("movf","%s,w",
5711                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5712             pic16_emitcode("movwf","%s",
5713                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5714             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5715             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5716             break;
5717           default:
5718             pic16_emitcode("movlw","0x%x",t);
5719             pic16_emitcode("andwf","%s,w",
5720                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5721             pic16_emitcode("movwf","%s",
5722                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5723               
5724             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5725             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5726             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5727           }
5728           continue;
5729         }
5730
5731         if (AOP_TYPE(left) == AOP_ACC) {
5732           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5733           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5734         } else {
5735           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5736           pic16_emitcode("andwf","%s,w",
5737                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5738           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5739           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5740         }
5741         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5742         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5743       }
5744     }
5745   }
5746
5747   release :
5748     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5749   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5750   pic16_freeAsmop(result,NULL,ic,TRUE);     
5751 }
5752
5753 /*-----------------------------------------------------------------*/
5754 /* genOr  - code for or                                            */
5755 /*-----------------------------------------------------------------*/
5756 static void genOr (iCode *ic, iCode *ifx)
5757 {
5758     operand *left, *right, *result;
5759     int size, offset=0;
5760     unsigned long lit = 0L;
5761
5762     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5763
5764     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5765     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5766     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5767
5768     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5769
5770     /* if left is a literal & right is not then exchange them */
5771     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5772         AOP_NEEDSACC(left)) {
5773         operand *tmp = right ;
5774         right = left;
5775         left = tmp;
5776     }
5777
5778     /* if result = right then exchange them */
5779     if(pic16_sameRegs(AOP(result),AOP(right))){
5780         operand *tmp = right ;
5781         right = left;
5782         left = tmp;
5783     }
5784
5785     /* if right is bit then exchange them */
5786     if (AOP_TYPE(right) == AOP_CRY &&
5787         AOP_TYPE(left) != AOP_CRY){
5788         operand *tmp = right ;
5789         right = left;
5790         left = tmp;
5791     }
5792
5793     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5794
5795     if(AOP_TYPE(right) == AOP_LIT)
5796         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5797
5798     size = AOP_SIZE(result);
5799
5800     // if(bit | yy)
5801     // xx = bit | yy;
5802     if (AOP_TYPE(left) == AOP_CRY){
5803         if(AOP_TYPE(right) == AOP_LIT){
5804             // c = bit & literal;
5805             if(lit){
5806                 // lit != 0 => result = 1
5807                 if(AOP_TYPE(result) == AOP_CRY){
5808                   if(size)
5809                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5810                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5811                   //     AOP(result)->aopu.aop_dir,
5812                   //     AOP(result)->aopu.aop_dir);
5813                     else if(ifx)
5814                         continueIfTrue(ifx);
5815                     goto release;
5816                 }
5817             } else {
5818                 // lit == 0 => result = left
5819                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5820                     goto release;
5821                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5822             }
5823         } else {
5824             if (AOP_TYPE(right) == AOP_CRY){
5825               if(pic16_sameRegs(AOP(result),AOP(left))){
5826                 // c = bit | bit;
5827                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5828                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5829                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5830
5831                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5832                          AOP(result)->aopu.aop_dir,
5833                          AOP(result)->aopu.aop_dir);
5834                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5835                          AOP(right)->aopu.aop_dir,
5836                          AOP(right)->aopu.aop_dir);
5837                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5838                          AOP(result)->aopu.aop_dir,
5839                          AOP(result)->aopu.aop_dir);
5840               } else {
5841                 if( AOP_TYPE(result) == AOP_ACC) {
5842                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5843                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5844                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5845                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5846
5847                 } else {
5848
5849                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5850                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5851                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5852                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5853
5854                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5855                                  AOP(result)->aopu.aop_dir,
5856                                  AOP(result)->aopu.aop_dir);
5857                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5858                                  AOP(right)->aopu.aop_dir,
5859                                  AOP(right)->aopu.aop_dir);
5860                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5861                                  AOP(left)->aopu.aop_dir,
5862                                  AOP(left)->aopu.aop_dir);
5863                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5864                                  AOP(result)->aopu.aop_dir,
5865                                  AOP(result)->aopu.aop_dir);
5866                 }
5867               }
5868             } else {
5869                 // c = bit | val;
5870                 symbol *tlbl = newiTempLabel(NULL);
5871                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5872
5873
5874                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5875                 if( AOP_TYPE(right) == AOP_ACC) {
5876                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5877                   emitSKPNZ;
5878                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5879                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5880                 }
5881
5882
5883
5884                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5885                     pic16_emitcode(";XXX setb","c");
5886                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5887                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5888                 pic16_toBoolean(right);
5889                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5890                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5891                     jmpTrueOrFalse(ifx, tlbl);
5892                     goto release;
5893                 } else {
5894                     CLRC;
5895                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5896                 }
5897             }
5898         }
5899         // bit = c
5900         // val = c
5901         if(size)
5902             pic16_outBitC(result);
5903         // if(bit | ...)
5904         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5905             genIfxJump(ifx, "c");           
5906         goto release ;
5907     }
5908
5909     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5910     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5911     if((AOP_TYPE(right) == AOP_LIT) &&
5912        (AOP_TYPE(result) == AOP_CRY) &&
5913        (AOP_TYPE(left) != AOP_CRY)){
5914         if(lit){
5915           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5916             // result = 1
5917             if(size)
5918                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5919             else 
5920                 continueIfTrue(ifx);
5921             goto release;
5922         } else {
5923           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5924             // lit = 0, result = boolean(left)
5925             if(size)
5926                 pic16_emitcode(";XXX setb","c");
5927             pic16_toBoolean(right);
5928             if(size){
5929                 symbol *tlbl = newiTempLabel(NULL);
5930                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5931                 CLRC;
5932                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5933             } else {
5934                 genIfxJump (ifx,"a");
5935                 goto release;
5936             }
5937         }
5938         pic16_outBitC(result);
5939         goto release ;
5940     }
5941
5942     /* if left is same as result */
5943     if(pic16_sameRegs(AOP(result),AOP(left))){
5944       int know_W = -1;
5945       for(;size--; offset++,lit>>=8) {
5946         if(AOP_TYPE(right) == AOP_LIT){
5947           if((lit & 0xff) == 0)
5948             /*  or'ing with 0 has no effect */
5949             continue;
5950           else {
5951             int p = my_powof2(lit & 0xff);
5952             if(p>=0) {
5953               /* only one bit is set in the literal, so use a bsf instruction */
5954               pic16_emitpcode(POC_BSF,
5955                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5956             } else {
5957               if(know_W != (lit & 0xff))
5958                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5959               know_W = lit & 0xff;
5960               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5961             }
5962                     
5963           }
5964         } else {
5965           if (AOP_TYPE(left) == AOP_ACC) {
5966             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5967             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5968           } else {                  
5969             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5970             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5971
5972             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5973             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5974
5975           }
5976         }
5977       }
5978     } else {
5979         // left & result in different registers
5980         if(AOP_TYPE(result) == AOP_CRY){
5981             // result = bit
5982             // if(size), result in bit
5983             // if(!size && ifx), conditional oper: if(left | right)
5984             symbol *tlbl = newiTempLabel(NULL);
5985             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5986             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5987
5988
5989             if(size)
5990                 pic16_emitcode(";XXX setb","c");
5991             while(sizer--){
5992                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5993                 pic16_emitcode(";XXX orl","a,%s",
5994                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5995                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5996                 offset++;
5997             }
5998             if(size){
5999                 CLRC;
6000                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6001                 pic16_outBitC(result);
6002             } else if(ifx)
6003                 jmpTrueOrFalse(ifx, tlbl);
6004         } else for(;(size--);offset++){
6005           // normal case
6006           // result = left & right
6007           if(AOP_TYPE(right) == AOP_LIT){
6008             int t = (lit >> (offset*8)) & 0x0FFL;
6009             switch(t) { 
6010             case 0x00:
6011               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6012               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6013
6014               pic16_emitcode("movf","%s,w",
6015                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6016               pic16_emitcode("movwf","%s",
6017                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6018               break;
6019             default:
6020               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6021               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6022               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6023
6024               pic16_emitcode("movlw","0x%x",t);
6025               pic16_emitcode("iorwf","%s,w",
6026                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6027               pic16_emitcode("movwf","%s",
6028                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6029               
6030             }
6031             continue;
6032           }
6033
6034           // faster than result <- left, anl result,right
6035           // and better if result is SFR
6036           if (AOP_TYPE(left) == AOP_ACC) {
6037             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6038             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6039           } else {
6040             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6041             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6042
6043             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6044             pic16_emitcode("iorwf","%s,w",
6045                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6046           }
6047           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6048           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6049         }
6050     }
6051
6052 release :
6053     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6054     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6055     pic16_freeAsmop(result,NULL,ic,TRUE);     
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* genXor - code for xclusive or                                   */
6060 /*-----------------------------------------------------------------*/
6061 static void genXor (iCode *ic, iCode *ifx)
6062 {
6063   operand *left, *right, *result;
6064   int size, offset=0;
6065   unsigned long lit = 0L;
6066
6067   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6068
6069   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6070   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6071   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6072
6073   /* if left is a literal & right is not ||
6074      if left needs acc & right does not */
6075   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6076       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6077     operand *tmp = right ;
6078     right = left;
6079     left = tmp;
6080   }
6081
6082   /* if result = right then exchange them */
6083   if(pic16_sameRegs(AOP(result),AOP(right))){
6084     operand *tmp = right ;
6085     right = left;
6086     left = tmp;
6087   }
6088
6089   /* if right is bit then exchange them */
6090   if (AOP_TYPE(right) == AOP_CRY &&
6091       AOP_TYPE(left) != AOP_CRY){
6092     operand *tmp = right ;
6093     right = left;
6094     left = tmp;
6095   }
6096   if(AOP_TYPE(right) == AOP_LIT)
6097     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6098
6099   size = AOP_SIZE(result);
6100
6101   // if(bit ^ yy)
6102   // xx = bit ^ yy;
6103   if (AOP_TYPE(left) == AOP_CRY){
6104     if(AOP_TYPE(right) == AOP_LIT){
6105       // c = bit & literal;
6106       if(lit>>1){
6107         // lit>>1  != 0 => result = 1
6108         if(AOP_TYPE(result) == AOP_CRY){
6109           if(size)
6110             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6111             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6112           else if(ifx)
6113             continueIfTrue(ifx);
6114           goto release;
6115         }
6116         pic16_emitcode("setb","c");
6117       } else{
6118         // lit == (0 or 1)
6119         if(lit == 0){
6120           // lit == 0, result = left
6121           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6122             goto release;
6123           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6124         } else{
6125           // lit == 1, result = not(left)
6126           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6127             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6128             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6129             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6130             goto release;
6131           } else {
6132             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6133             pic16_emitcode("cpl","c");
6134           }
6135         }
6136       }
6137
6138     } else {
6139       // right != literal
6140       symbol *tlbl = newiTempLabel(NULL);
6141       if (AOP_TYPE(right) == AOP_CRY){
6142         // c = bit ^ bit;
6143         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6144       }
6145       else{
6146         int sizer = AOP_SIZE(right);
6147         // c = bit ^ val
6148         // if val>>1 != 0, result = 1
6149         pic16_emitcode("setb","c");
6150         while(sizer){
6151           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6152           if(sizer == 1)
6153             // test the msb of the lsb
6154             pic16_emitcode("anl","a,#0xfe");
6155           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6156           sizer--;
6157         }
6158         // val = (0,1)
6159         pic16_emitcode("rrc","a");
6160       }
6161       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6162       pic16_emitcode("cpl","c");
6163       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6164     }
6165     // bit = c
6166     // val = c
6167     if(size)
6168       pic16_outBitC(result);
6169     // if(bit | ...)
6170     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6171       genIfxJump(ifx, "c");           
6172     goto release ;
6173   }
6174
6175   if(pic16_sameRegs(AOP(result),AOP(left))){
6176     /* if left is same as result */
6177     for(;size--; offset++) {
6178       if(AOP_TYPE(right) == AOP_LIT){
6179         int t  = (lit >> (offset*8)) & 0x0FFL;
6180         if(t == 0x00L)
6181           continue;
6182         else
6183           if (IS_AOP_PREG(left)) {
6184             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6185             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6186             pic16_aopPut(AOP(result),"a",offset);
6187           } else {
6188             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6189             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6190             pic16_emitcode("xrl","%s,%s",
6191                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6192                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6193           }
6194       } else {
6195         if (AOP_TYPE(left) == AOP_ACC)
6196           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6197         else {
6198           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6199           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6200 /*
6201           if (IS_AOP_PREG(left)) {
6202             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6203             pic16_aopPut(AOP(result),"a",offset);
6204           } else
6205             pic16_emitcode("xrl","%s,a",
6206                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6207 */
6208         }
6209       }
6210     }
6211   } else {
6212     // left & result in different registers
6213     if(AOP_TYPE(result) == AOP_CRY){
6214       // result = bit
6215       // if(size), result in bit
6216       // if(!size && ifx), conditional oper: if(left ^ right)
6217       symbol *tlbl = newiTempLabel(NULL);
6218       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6219       if(size)
6220         pic16_emitcode("setb","c");
6221       while(sizer--){
6222         if((AOP_TYPE(right) == AOP_LIT) &&
6223            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6224           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6225         } else {
6226           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6227           pic16_emitcode("xrl","a,%s",
6228                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6229         }
6230         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6231         offset++;
6232       }
6233       if(size){
6234         CLRC;
6235         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6236         pic16_outBitC(result);
6237       } else if(ifx)
6238         jmpTrueOrFalse(ifx, tlbl);
6239     } else for(;(size--);offset++){
6240       // normal case
6241       // result = left & right
6242       if(AOP_TYPE(right) == AOP_LIT){
6243         int t = (lit >> (offset*8)) & 0x0FFL;
6244         switch(t) { 
6245         case 0x00:
6246           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6247           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6248           pic16_emitcode("movf","%s,w",
6249                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6250           pic16_emitcode("movwf","%s",
6251                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6252           break;
6253         case 0xff:
6254           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6255           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6256           pic16_emitcode("comf","%s,w",
6257                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6258           pic16_emitcode("movwf","%s",
6259                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6260           break;
6261         default:
6262           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6263           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6264           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6265           pic16_emitcode("movlw","0x%x",t);
6266           pic16_emitcode("xorwf","%s,w",
6267                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6268           pic16_emitcode("movwf","%s",
6269                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6270
6271         }
6272         continue;
6273       }
6274
6275       // faster than result <- left, anl result,right
6276       // and better if result is SFR
6277       if (AOP_TYPE(left) == AOP_ACC) {
6278         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6279         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6280       } else {
6281         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6282         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6283         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6284         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6285       }
6286       if ( AOP_TYPE(result) != AOP_ACC){
6287         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6288         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6289       }
6290     }
6291   }
6292
6293   release :
6294     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296   pic16_freeAsmop(result,NULL,ic,TRUE);     
6297 }
6298
6299 /*-----------------------------------------------------------------*/
6300 /* genInline - write the inline code out                           */
6301 /*-----------------------------------------------------------------*/
6302 static void genInline (iCode *ic)
6303 {
6304     char *buffer, *bp, *bp1;
6305     
6306     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6307
6308     _G.inLine += (!options.asmpeep);
6309
6310     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6311     strcpy(buffer,IC_INLINE(ic));
6312
6313     /* emit each line as a code */
6314     while (*bp) {
6315         if (*bp == '\n') {
6316             *bp++ = '\0';
6317
6318             if(*bp1)
6319               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));       //pic16_AssembleLine(bp1, 0));
6320                                         // inline directly, no process
6321             bp1 = bp;
6322         } else {
6323             if (*bp == ':') {
6324                 bp++;
6325                 *bp = '\0';
6326                 bp++;
6327                 pic16_emitcode(bp1,"");
6328                 bp1 = bp;
6329             } else
6330                 bp++;
6331         }
6332     }
6333     if ((bp1 != bp) && *bp1)
6334       pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));               //pic16_AssembleLine(bp1, 0));
6335
6336     Safe_free(buffer);
6337
6338     _G.inLine -= (!options.asmpeep);
6339 }
6340
6341 /*-----------------------------------------------------------------*/
6342 /* genRRC - rotate right with carry                                */
6343 /*-----------------------------------------------------------------*/
6344 static void genRRC (iCode *ic)
6345 {
6346   operand *left , *result ;
6347   int size, offset = 0, same;
6348
6349   /* rotate right with carry */
6350   left = IC_LEFT(ic);
6351   result=IC_RESULT(ic);
6352   pic16_aopOp (left,ic,FALSE);
6353   pic16_aopOp (result,ic,FALSE);
6354
6355   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6356
6357   same = pic16_sameRegs(AOP(result),AOP(left));
6358
6359   size = AOP_SIZE(result);    
6360
6361   /* get the lsb and put it into the carry */
6362   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6363
6364   offset = 0 ;
6365
6366   while(size--) {
6367
6368     if(same) {
6369       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6370     } else {
6371       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6372       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6373     }
6374
6375     offset++;
6376   }
6377
6378   pic16_freeAsmop(left,NULL,ic,TRUE);
6379   pic16_freeAsmop(result,NULL,ic,TRUE);
6380 }
6381
6382 /*-----------------------------------------------------------------*/
6383 /* genRLC - generate code for rotate left with carry               */
6384 /*-----------------------------------------------------------------*/
6385 static void genRLC (iCode *ic)
6386 {    
6387   operand *left , *result ;
6388   int size, offset = 0;
6389   int same;
6390
6391   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6392   /* rotate right with carry */
6393   left = IC_LEFT(ic);
6394   result=IC_RESULT(ic);
6395   pic16_aopOp (left,ic,FALSE);
6396   pic16_aopOp (result,ic,FALSE);
6397
6398   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6399
6400   same = pic16_sameRegs(AOP(result),AOP(left));
6401
6402   /* move it to the result */
6403   size = AOP_SIZE(result);    
6404
6405   /* get the msb and put it into the carry */
6406   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6407
6408   offset = 0 ;
6409
6410   while(size--) {
6411
6412     if(same) {
6413       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6414     } else {
6415       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6416       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6417     }
6418
6419     offset++;
6420   }
6421
6422
6423   pic16_freeAsmop(left,NULL,ic,TRUE);
6424   pic16_freeAsmop(result,NULL,ic,TRUE);
6425 }
6426
6427 /*-----------------------------------------------------------------*/
6428 /* genGetHbit - generates code get highest order bit               */
6429 /*-----------------------------------------------------------------*/
6430 static void genGetHbit (iCode *ic)
6431 {
6432     operand *left, *result;
6433     left = IC_LEFT(ic);
6434     result=IC_RESULT(ic);
6435     pic16_aopOp (left,ic,FALSE);
6436     pic16_aopOp (result,ic,FALSE);
6437
6438     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6439     /* get the highest order byte into a */
6440     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6441     if(AOP_TYPE(result) == AOP_CRY){
6442         pic16_emitcode("rlc","a");
6443         pic16_outBitC(result);
6444     }
6445     else{
6446         pic16_emitcode("rl","a");
6447         pic16_emitcode("anl","a,#0x01");
6448         pic16_outAcc(result);
6449     }
6450
6451
6452     pic16_freeAsmop(left,NULL,ic,TRUE);
6453     pic16_freeAsmop(result,NULL,ic,TRUE);
6454 }
6455
6456 /*-----------------------------------------------------------------*/
6457 /* AccRol - rotate left accumulator by known count                 */
6458 /*-----------------------------------------------------------------*/
6459 static void AccRol (int shCount)
6460 {
6461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6462     shCount &= 0x0007;              // shCount : 0..7
6463     switch(shCount){
6464         case 0 :
6465             break;
6466         case 1 :
6467             pic16_emitcode("rl","a");
6468             break;
6469         case 2 :
6470             pic16_emitcode("rl","a");
6471             pic16_emitcode("rl","a");
6472             break;
6473         case 3 :
6474             pic16_emitcode("swap","a");
6475             pic16_emitcode("rr","a");
6476             break;
6477         case 4 :
6478             pic16_emitcode("swap","a");
6479             break;
6480         case 5 :
6481             pic16_emitcode("swap","a");
6482             pic16_emitcode("rl","a");
6483             break;
6484         case 6 :
6485             pic16_emitcode("rr","a");
6486             pic16_emitcode("rr","a");
6487             break;
6488         case 7 :
6489             pic16_emitcode("rr","a");
6490             break;
6491     }
6492 }
6493
6494 /*-----------------------------------------------------------------*/
6495 /* AccLsh - left shift accumulator by known count                  */
6496 /*-----------------------------------------------------------------*/
6497 static void AccLsh (int shCount)
6498 {
6499     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6500     if(shCount != 0){
6501         if(shCount == 1)
6502             pic16_emitcode("add","a,acc");
6503         else 
6504             if(shCount == 2) {
6505             pic16_emitcode("add","a,acc");
6506             pic16_emitcode("add","a,acc");
6507         } else {
6508             /* rotate left accumulator */
6509             AccRol(shCount);
6510             /* and kill the lower order bits */
6511             pic16_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6512         }
6513     }
6514 }
6515
6516 /*-----------------------------------------------------------------*/
6517 /* AccRsh - right shift accumulator by known count                 */
6518 /*-----------------------------------------------------------------*/
6519 static void AccRsh (int shCount)
6520 {
6521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6522     if(shCount != 0){
6523         if(shCount == 1){
6524             CLRC;
6525             pic16_emitcode("rrc","a");
6526         } else {
6527             /* rotate right accumulator */
6528             AccRol(8 - shCount);
6529             /* and kill the higher order bits */
6530             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6531         }
6532     }
6533 }
6534
6535 #if 0
6536 /*-----------------------------------------------------------------*/
6537 /* AccSRsh - signed right shift accumulator by known count                 */
6538 /*-----------------------------------------------------------------*/
6539 static void AccSRsh (int shCount)
6540 {
6541     symbol *tlbl ;
6542     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6543     if(shCount != 0){
6544         if(shCount == 1){
6545             pic16_emitcode("mov","c,acc.7");
6546             pic16_emitcode("rrc","a");
6547         } else if(shCount == 2){
6548             pic16_emitcode("mov","c,acc.7");
6549             pic16_emitcode("rrc","a");
6550             pic16_emitcode("mov","c,acc.7");
6551             pic16_emitcode("rrc","a");
6552         } else {
6553             tlbl = newiTempLabel(NULL);
6554             /* rotate right accumulator */
6555             AccRol(8 - shCount);
6556             /* and kill the higher order bits */
6557             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6558             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6559             pic16_emitcode("orl","a,#0x%02x",
6560                      (unsigned char)~SRMask[shCount]);
6561             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6562         }
6563     }
6564 }
6565 #endif
6566 /*-----------------------------------------------------------------*/
6567 /* shiftR1Left2Result - shift right one byte from left to result   */
6568 /*-----------------------------------------------------------------*/
6569 static void shiftR1Left2ResultSigned (operand *left, int offl,
6570                                 operand *result, int offr,
6571                                 int shCount)
6572 {
6573   int same;
6574
6575   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6576
6577   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6578
6579   switch(shCount) {
6580   case 1:
6581     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6582     if(same) 
6583       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6584     else {
6585       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6586       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6587     }
6588
6589     break;
6590   case 2:
6591
6592     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6593     if(same) 
6594       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6595     else {
6596       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6597       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6598     }
6599     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6600     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6601
6602     break;
6603
6604   case 3:
6605     if(same)
6606       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6607     else {
6608       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6609       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6610     }
6611
6612     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6613     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6614     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6615
6616     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6617     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6618
6619     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6620     break;
6621
6622   case 4:
6623     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6624     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6625     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6626     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6627     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6628     break;
6629   case 5:
6630     if(same) {
6631       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6632     } else {
6633       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6634       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6635     }
6636     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6637     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6638     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6639     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6640     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6641     break;
6642
6643   case 6:
6644     if(same) {
6645       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6646       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6647       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6648       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6649       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6650       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6651     } else {
6652       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6653       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6654       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6655       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6656       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6657     }
6658     break;
6659
6660   case 7:
6661     if(same) {
6662       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6663       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6664       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6665       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6666     } else {
6667       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6668       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6669       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6670     }
6671
6672   default:
6673     break;
6674   }
6675 }
6676
6677 /*-----------------------------------------------------------------*/
6678 /* shiftR1Left2Result - shift right one byte from left to result   */
6679 /*-----------------------------------------------------------------*/
6680 static void shiftR1Left2Result (operand *left, int offl,
6681                                 operand *result, int offr,
6682                                 int shCount, int sign)
6683 {
6684   int same;
6685
6686   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6687
6688   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6689
6690   /* Copy the msb into the carry if signed. */
6691   if(sign) {
6692     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6693     return;
6694   }
6695
6696
6697
6698   switch(shCount) {
6699   case 1:
6700     emitCLRC;
6701     if(same) 
6702       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6703     else {
6704       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6706     }
6707     break;
6708   case 2:
6709     emitCLRC;
6710     if(same) {
6711       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6712     } else {
6713       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6714       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6715     }
6716     emitCLRC;
6717     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6718
6719     break;
6720   case 3:
6721     if(same)
6722       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6723     else {
6724       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6725       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6726     }
6727
6728     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6729     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6730     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6731     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6732     break;
6733       
6734   case 4:
6735     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6736     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6737     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6738     break;
6739
6740   case 5:
6741     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6742     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6743     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6744     emitCLRC;
6745     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6746
6747     break;
6748   case 6:
6749
6750     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6751     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6752     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6753     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6754     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6755     break;
6756
6757   case 7:
6758
6759     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6760     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6761     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6762
6763     break;
6764
6765   default:
6766     break;
6767   }
6768 }
6769
6770 /*-----------------------------------------------------------------*/
6771 /* shiftL1Left2Result - shift left one byte from left to result    */
6772 /*-----------------------------------------------------------------*/
6773 static void shiftL1Left2Result (operand *left, int offl,
6774                                 operand *result, int offr, int shCount)
6775 {
6776   int same;
6777
6778   //    char *l;
6779   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6780
6781   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6782   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6783     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6784     //    MOVA(l);
6785     /* shift left accumulator */
6786     //AccLsh(shCount); // don't comment out just yet...
6787   //    pic16_aopPut(AOP(result),"a",offr);
6788
6789   switch(shCount) {
6790   case 1:
6791     /* Shift left 1 bit position */
6792     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6793     if(same) {
6794       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6795     } else {
6796       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6797       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6798     }
6799     break;
6800   case 2:
6801     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6802     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6803     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6804     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6805     break;
6806   case 3:
6807     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6808     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6809     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6810     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6811     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6812     break;
6813   case 4:
6814     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6815     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6816     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6817     break;
6818   case 5:
6819     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6820     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6821     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6822     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6823     break;
6824   case 6:
6825     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6826     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6827     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6828     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6829     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6830     break;
6831   case 7:
6832     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6833     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6834     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6835     break;
6836
6837   default:
6838     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6839   }
6840
6841 }
6842
6843 /*-----------------------------------------------------------------*/
6844 /* movLeft2Result - move byte from left to result                  */
6845 /*-----------------------------------------------------------------*/
6846 static void movLeft2Result (operand *left, int offl,
6847                             operand *result, int offr)
6848 {
6849   char *l;
6850   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6851   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6852     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6853
6854     if (*l == '@' && (IS_AOP_PREG(result))) {
6855       pic16_emitcode("mov","a,%s",l);
6856       pic16_aopPut(AOP(result),"a",offr);
6857     } else {
6858       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6859       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6860     }
6861   }
6862 }
6863
6864 /*-----------------------------------------------------------------*/
6865 /* shiftL2Left2Result - shift left two bytes from left to result   */
6866 /*-----------------------------------------------------------------*/
6867 static void shiftL2Left2Result (operand *left, int offl,
6868                                 operand *result, int offr, int shCount)
6869 {
6870
6871
6872   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6873
6874   if(pic16_sameRegs(AOP(result), AOP(left))) {
6875     switch(shCount) {
6876     case 0:
6877       break;
6878     case 1:
6879     case 2:
6880     case 3:
6881
6882       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6883       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6884       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6885
6886       while(--shCount) {
6887         emitCLRC;
6888         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6889         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6890       }
6891
6892       break;
6893     case 4:
6894     case 5:
6895       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6896       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6897       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6898       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6899       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6900       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6901       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6902       if(shCount >=5) {
6903         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6904         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6905       }
6906       break;
6907     case 6:
6908       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6909       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6910       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6911       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6912       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6913       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6914       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6915       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6916       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6917       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6918       break;
6919     case 7:
6920       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6921       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6922       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6923       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6924       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6925     }
6926
6927   } else {
6928     switch(shCount) {
6929     case 0:
6930       break;
6931     case 1:
6932     case 2:
6933     case 3:
6934       /* note, use a mov/add for the shift since the mov has a
6935          chance of getting optimized out */
6936       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6937       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6938       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6939       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6940       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6941
6942       while(--shCount) {
6943         emitCLRC;
6944         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6945         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6946       }
6947       break;
6948
6949     case 4:
6950     case 5:
6951       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6952       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6953       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6954       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6955       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6956       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6957       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6958       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6959
6960
6961       if(shCount == 5) {
6962         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6963         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6964       }
6965       break;
6966     case 6:
6967       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6968       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6969       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
6970       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6971
6972       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6973       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6975       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6976       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6977       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6978       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6979       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6980       break;
6981     case 7:
6982       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
6983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6984       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6985       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6986       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6987     }
6988   }
6989
6990 }
6991 /*-----------------------------------------------------------------*/
6992 /* shiftR2Left2Result - shift right two bytes from left to result  */
6993 /*-----------------------------------------------------------------*/
6994 static void shiftR2Left2Result (operand *left, int offl,
6995                                 operand *result, int offr,
6996                                 int shCount, int sign)
6997 {
6998   int same=0;
6999
7000   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7001   same = pic16_sameRegs(AOP(result), AOP(left));
7002
7003   if(same && ((offl + MSB16) == offr)){
7004     same=1;
7005     /* don't crash result[offr] */
7006     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7007     pic16_emitcode("xch","a,%s", pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7008   }
7009 /* else {
7010     movLeft2Result(left,offl, result, offr);
7011     MOVA(pic16_aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7012   }
7013 */
7014   /* a:x >> shCount (x = lsb(result))*/
7015 /*
7016   if(sign)
7017     AccAXRshS( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7018   else {
7019     AccAXRsh( pic16_aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7020 */
7021   switch(shCount) {
7022   case 0:
7023     break;
7024   case 1:
7025   case 2:
7026   case 3:
7027     if(sign)
7028       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7029     else
7030       emitCLRC;
7031
7032     if(same) {
7033       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7034       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7035     } else {
7036       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7037       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7040     }
7041
7042     while(--shCount) {
7043       if(sign)
7044         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7045       else
7046         emitCLRC;
7047       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7048       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7049     }
7050     break;
7051   case 4:
7052   case 5:
7053     if(same) {
7054
7055       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7056       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7057       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7058
7059       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7060       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7061       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7062       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7063     } else {
7064       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7065       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7066       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7067
7068       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7069       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7070       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7071       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7072       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7073     }
7074
7075     if(shCount >=5) {
7076       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7077       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7078     }
7079
7080     if(sign) {
7081       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7082       pic16_emitpcode(POC_BTFSC, 
7083                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7084       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7085     }
7086
7087     break;
7088
7089   case 6:
7090     if(same) {
7091
7092       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7093       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7094
7095       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7096       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7097       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7098       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7099       if(sign) {
7100         pic16_emitpcode(POC_BTFSC, 
7101                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7102         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7103       }
7104       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7105       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7106       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7107       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7108     } else {
7109       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7110       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7111       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7112       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7113       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7114       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7115       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7116       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7117       if(sign) {
7118         pic16_emitpcode(POC_BTFSC, 
7119                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7120         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7121       }
7122       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7123       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7124
7125         
7126     }
7127
7128     break;
7129   case 7:
7130     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7131     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7132     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7133     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7134     if(sign) {
7135       emitSKPNC;
7136       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7137     } else 
7138       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7139   }
7140 }
7141
7142
7143 /*-----------------------------------------------------------------*/
7144 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7145 /*-----------------------------------------------------------------*/
7146 static void shiftLLeftOrResult (operand *left, int offl,
7147                                 operand *result, int offr, int shCount)
7148 {
7149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7150     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7151     /* shift left accumulator */
7152     AccLsh(shCount);
7153     /* or with result */
7154     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
7155     /* back to result */
7156     pic16_aopPut(AOP(result),"a",offr);
7157 }
7158
7159 /*-----------------------------------------------------------------*/
7160 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7161 /*-----------------------------------------------------------------*/
7162 static void shiftRLeftOrResult (operand *left, int offl,
7163                                 operand *result, int offr, int shCount)
7164 {
7165     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7166     MOVA(pic16_aopGet(AOP(left),offl,FALSE,FALSE));
7167     /* shift right accumulator */
7168     AccRsh(shCount);
7169     /* or with result */
7170     pic16_emitcode("orl","a,%s", pic16_aopGet(AOP(result),offr,FALSE,FALSE));
7171     /* back to result */
7172     pic16_aopPut(AOP(result),"a",offr);
7173 }
7174
7175 /*-----------------------------------------------------------------*/
7176 /* genlshOne - left shift a one byte quantity by known count       */
7177 /*-----------------------------------------------------------------*/
7178 static void genlshOne (operand *result, operand *left, int shCount)
7179 {       
7180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7181     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7182 }
7183
7184 /*-----------------------------------------------------------------*/
7185 /* genlshTwo - left shift two bytes by known amount != 0           */
7186 /*-----------------------------------------------------------------*/
7187 static void genlshTwo (operand *result,operand *left, int shCount)
7188 {
7189     int size;
7190     
7191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7192     size = pic16_getDataSize(result);
7193
7194     /* if shCount >= 8 */
7195     if (shCount >= 8) {
7196         shCount -= 8 ;
7197
7198         if (size > 1){
7199             if (shCount)
7200                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7201             else 
7202                 movLeft2Result(left, LSB, result, MSB16);
7203         }
7204         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7205     }
7206
7207     /*  1 <= shCount <= 7 */
7208     else {  
7209         if(size == 1)
7210             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7211         else 
7212             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7213     }
7214 }
7215
7216 /*-----------------------------------------------------------------*/
7217 /* shiftLLong - shift left one long from left to result            */
7218 /* offl = LSB or MSB16                                             */
7219 /*-----------------------------------------------------------------*/
7220 static void shiftLLong (operand *left, operand *result, int offr )
7221 {
7222     char *l;
7223     int size = AOP_SIZE(result);
7224
7225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7226     if(size >= LSB+offr){
7227         l = pic16_aopGet(AOP(left),LSB,FALSE,FALSE);
7228         MOVA(l);
7229         pic16_emitcode("add","a,acc");
7230         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7231             size >= MSB16+offr && offr != LSB )
7232             pic16_emitcode("xch","a,%s",
7233                      pic16_aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7234         else        
7235             pic16_aopPut(AOP(result),"a",LSB+offr);
7236     }
7237
7238     if(size >= MSB16+offr){
7239         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7240             l = pic16_aopGet(AOP(left),MSB16,FALSE,FALSE);
7241             MOVA(l);
7242         }
7243         pic16_emitcode("rlc","a");
7244         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7245             size >= MSB24+offr && offr != LSB)
7246             pic16_emitcode("xch","a,%s",
7247                      pic16_aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7248         else        
7249             pic16_aopPut(AOP(result),"a",MSB16+offr);
7250     }
7251
7252     if(size >= MSB24+offr){
7253         if (!(pic16_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7254             l = pic16_aopGet(AOP(left),MSB24,FALSE,FALSE);
7255             MOVA(l);
7256         }
7257         pic16_emitcode("rlc","a");
7258         if (pic16_sameRegs(AOP(left),AOP(result)) && 
7259             size >= MSB32+offr && offr != LSB )
7260             pic16_emitcode("xch","a,%s",
7261                      pic16_aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7262         else        
7263             pic16_aopPut(AOP(result),"a",MSB24+offr);
7264     }
7265
7266     if(size > MSB32+offr){
7267         if (!(pic16_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7268             l = pic16_aopGet(AOP(left),MSB32,FALSE,FALSE);
7269             MOVA(l);    
7270         }
7271         pic16_emitcode("rlc","a");
7272         pic16_aopPut(AOP(result),"a",MSB32+offr);
7273     }
7274     if(offr != LSB)
7275         pic16_aopPut(AOP(result),zero,LSB);       
7276 }
7277
7278 /*-----------------------------------------------------------------*/
7279 /* genlshFour - shift four byte by a known amount != 0             */
7280 /*-----------------------------------------------------------------*/
7281 static void genlshFour (operand *result, operand *left, int shCount)
7282 {
7283     int size;
7284
7285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7286     size = AOP_SIZE(result);
7287
7288     /* if shifting more that 3 bytes */
7289     if (shCount >= 24 ) {
7290         shCount -= 24;
7291         if (shCount)
7292             /* lowest order of left goes to the highest
7293             order of the destination */
7294             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7295         else
7296             movLeft2Result(left, LSB, result, MSB32);
7297         pic16_aopPut(AOP(result),zero,LSB);
7298         pic16_aopPut(AOP(result),zero,MSB16);
7299         pic16_aopPut(AOP(result),zero,MSB32);
7300         return;
7301     }
7302
7303     /* more than two bytes */
7304     else if ( shCount >= 16 ) {
7305         /* lower order two bytes goes to higher order two bytes */
7306         shCount -= 16;
7307         /* if some more remaining */
7308         if (shCount)
7309             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7310         else {
7311             movLeft2Result(left, MSB16, result, MSB32);
7312             movLeft2Result(left, LSB, result, MSB24);
7313         }
7314         pic16_aopPut(AOP(result),zero,MSB16);
7315         pic16_aopPut(AOP(result),zero,LSB);
7316         return;
7317     }    
7318
7319     /* if more than 1 byte */
7320     else if ( shCount >= 8 ) {
7321         /* lower order three bytes goes to higher order  three bytes */
7322         shCount -= 8;
7323         if(size == 2){
7324             if(shCount)
7325                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7326             else
7327                 movLeft2Result(left, LSB, result, MSB16);
7328         }
7329         else{   /* size = 4 */
7330             if(shCount == 0){
7331                 movLeft2Result(left, MSB24, result, MSB32);
7332                 movLeft2Result(left, MSB16, result, MSB24);
7333                 movLeft2Result(left, LSB, result, MSB16);
7334                 pic16_aopPut(AOP(result),zero,LSB);
7335             }
7336             else if(shCount == 1)
7337                 shiftLLong(left, result, MSB16);
7338             else{
7339                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7340                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7341                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7342                 pic16_aopPut(AOP(result),zero,LSB);
7343             }
7344         }
7345     }
7346
7347     /* 1 <= shCount <= 7 */
7348     else if(shCount <= 2){
7349         shiftLLong(left, result, LSB);
7350         if(shCount == 2)
7351             shiftLLong(result, result, LSB);
7352     }
7353     /* 3 <= shCount <= 7, optimize */
7354     else{
7355         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7356         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7357         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7358     }
7359 }
7360
7361 /*-----------------------------------------------------------------*/
7362 /* genLeftShiftLiteral - left shifting by known count              */
7363 /*-----------------------------------------------------------------*/
7364 static void genLeftShiftLiteral (operand *left,
7365                                  operand *right,
7366                                  operand *result,
7367                                  iCode *ic)
7368 {    
7369     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7370     int size;
7371
7372     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7373     pic16_freeAsmop(right,NULL,ic,TRUE);
7374
7375     pic16_aopOp(left,ic,FALSE);
7376     pic16_aopOp(result,ic,FALSE);
7377
7378     size = getSize(operandType(result));
7379
7380 #if VIEW_SIZE
7381     pic16_emitcode("; shift left ","result %d, left %d",size,
7382              AOP_SIZE(left));
7383 #endif
7384
7385     /* I suppose that the left size >= result size */
7386     if(shCount == 0){
7387         while(size--){
7388             movLeft2Result(left, size, result, size);
7389         }
7390     }
7391
7392     else if(shCount >= (size * 8))
7393         while(size--)
7394             pic16_aopPut(AOP(result),zero,size);
7395     else{
7396         switch (size) {
7397             case 1:
7398                 genlshOne (result,left,shCount);
7399                 break;
7400
7401             case 2:
7402             case 3:
7403                 genlshTwo (result,left,shCount);
7404                 break;
7405
7406             case 4:
7407                 genlshFour (result,left,shCount);
7408                 break;
7409         }
7410     }
7411     pic16_freeAsmop(left,NULL,ic,TRUE);
7412     pic16_freeAsmop(result,NULL,ic,TRUE);
7413 }
7414
7415 /*-----------------------------------------------------------------*
7416  * genMultiAsm - repeat assembly instruction for size of register.
7417  * if endian == 1, then the high byte (i.e base address + size of 
7418  * register) is used first else the low byte is used first;
7419  *-----------------------------------------------------------------*/
7420 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7421 {
7422
7423   int offset = 0;
7424
7425   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7426
7427   if(!reg)
7428     return;
7429
7430   if(!endian) {
7431     endian = 1;
7432   } else {
7433     endian = -1;
7434     offset = size-1;
7435   }
7436
7437   while(size--) {
7438     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7439     offset += endian;
7440   }
7441
7442 }
7443 /*-----------------------------------------------------------------*/
7444 /* genLeftShift - generates code for left shifting                 */
7445 /*-----------------------------------------------------------------*/
7446 static void genLeftShift (iCode *ic)
7447 {
7448   operand *left,*right, *result;
7449   int size, offset;
7450   char *l;
7451   symbol *tlbl , *tlbl1;
7452   pCodeOp *pctemp;
7453
7454   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455
7456   right = IC_RIGHT(ic);
7457   left  = IC_LEFT(ic);
7458   result = IC_RESULT(ic);
7459
7460   pic16_aopOp(right,ic,FALSE);
7461
7462   /* if the shift count is known then do it 
7463      as efficiently as possible */
7464   if (AOP_TYPE(right) == AOP_LIT) {
7465     genLeftShiftLiteral (left,right,result,ic);
7466     return ;
7467   }
7468
7469   /* shift count is unknown then we have to form 
7470      a loop get the loop count in B : Note: we take
7471      only the lower order byte since shifting
7472      more that 32 bits make no sense anyway, ( the
7473      largest size of an object can be only 32 bits ) */  
7474
7475     
7476   pic16_aopOp(left,ic,FALSE);
7477   pic16_aopOp(result,ic,FALSE);
7478
7479   /* now move the left to the result if they are not the
7480      same */
7481   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7482       AOP_SIZE(result) > 1) {
7483
7484     size = AOP_SIZE(result);
7485     offset=0;
7486     while (size--) {
7487       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7488       if (*l == '@' && (IS_AOP_PREG(result))) {
7489
7490         pic16_emitcode("mov","a,%s",l);
7491         pic16_aopPut(AOP(result),"a",offset);
7492       } else {
7493         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7494         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7495         //pic16_aopPut(AOP(result),l,offset);
7496       }
7497       offset++;
7498     }
7499   }
7500
7501   size = AOP_SIZE(result);
7502
7503   /* if it is only one byte then */
7504   if (size == 1) {
7505     if(optimized_for_speed) {
7506       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7507       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7508       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7509       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7510       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7511       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7512       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7513       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7514       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7515       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7516       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7517       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7518     } else {
7519
7520       tlbl = newiTempLabel(NULL);
7521       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7522         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7523         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7524       }
7525
7526       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7527       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7528       pic16_emitpLabel(tlbl->key);
7529       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7530       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7531       emitSKPC;
7532       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7533     }
7534     goto release ;
7535   }
7536     
7537   if (pic16_sameRegs(AOP(left),AOP(result))) {
7538
7539     tlbl = newiTempLabel(NULL);
7540     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7541     genMultiAsm(POC_RRCF, result, size,1);
7542     pic16_emitpLabel(tlbl->key);
7543     genMultiAsm(POC_RLCF, result, size,0);
7544     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7545     emitSKPC;
7546     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7547     goto release;
7548   }
7549
7550   //tlbl = newiTempLabel(NULL);
7551   //offset = 0 ;   
7552   //tlbl1 = newiTempLabel(NULL);
7553
7554   //reAdjustPreg(AOP(result));    
7555     
7556   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7557   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7558   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7559   //MOVA(l);
7560   //pic16_emitcode("add","a,acc");         
7561   //pic16_aopPut(AOP(result),"a",offset++);
7562   //while (--size) {
7563   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7564   //  MOVA(l);
7565   //  pic16_emitcode("rlc","a");         
7566   //  pic16_aopPut(AOP(result),"a",offset++);
7567   //}
7568   //reAdjustPreg(AOP(result));
7569
7570   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7571   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7572
7573
7574   tlbl = newiTempLabel(NULL);
7575   tlbl1= newiTempLabel(NULL);
7576
7577   size = AOP_SIZE(result);
7578   offset = 1;
7579
7580   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7581
7582   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7583
7584   /* offset should be 0, 1 or 3 */
7585   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7586   emitSKPNZ;
7587   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7588
7589   pic16_emitpcode(POC_MOVWF, pctemp);
7590
7591
7592   pic16_emitpLabel(tlbl->key);
7593
7594   emitCLRC;
7595   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7596   while(--size)
7597     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7598
7599   pic16_emitpcode(POC_DECFSZ,  pctemp);
7600   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7601   pic16_emitpLabel(tlbl1->key);
7602
7603   pic16_popReleaseTempReg(pctemp);
7604
7605
7606  release:
7607   pic16_freeAsmop (right,NULL,ic,TRUE);
7608   pic16_freeAsmop(left,NULL,ic,TRUE);
7609   pic16_freeAsmop(result,NULL,ic,TRUE);
7610 }
7611
7612 /*-----------------------------------------------------------------*/
7613 /* genrshOne - right shift a one byte quantity by known count      */
7614 /*-----------------------------------------------------------------*/
7615 static void genrshOne (operand *result, operand *left,
7616                        int shCount, int sign)
7617 {
7618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7619     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7620 }
7621
7622 /*-----------------------------------------------------------------*/
7623 /* genrshTwo - right shift two bytes by known amount != 0          */
7624 /*-----------------------------------------------------------------*/
7625 static void genrshTwo (operand *result,operand *left,
7626                        int shCount, int sign)
7627 {
7628   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7629   /* if shCount >= 8 */
7630   if (shCount >= 8) {
7631     shCount -= 8 ;
7632     if (shCount)
7633       shiftR1Left2Result(left, MSB16, result, LSB,
7634                          shCount, sign);
7635     else
7636       movLeft2Result(left, MSB16, result, LSB);
7637
7638     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7639
7640     if(sign) {
7641       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7642       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7643     }
7644   }
7645
7646   /*  1 <= shCount <= 7 */
7647   else
7648     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7649 }
7650
7651 /*-----------------------------------------------------------------*/
7652 /* shiftRLong - shift right one long from left to result           */
7653 /* offl = LSB or MSB16                                             */
7654 /*-----------------------------------------------------------------*/
7655 static void shiftRLong (operand *left, int offl,
7656                         operand *result, int sign)
7657 {
7658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7659     if(!sign)
7660         pic16_emitcode("clr","c");
7661     MOVA(pic16_aopGet(AOP(left),MSB32,FALSE,FALSE));
7662     if(sign)
7663         pic16_emitcode("mov","c,acc.7");
7664     pic16_emitcode("rrc","a");
7665     pic16_aopPut(AOP(result),"a",MSB32-offl);
7666     if(offl == MSB16)
7667         /* add sign of "a" */
7668         pic16_addSign(result, MSB32, sign);
7669
7670     MOVA(pic16_aopGet(AOP(left),MSB24,FALSE,FALSE));
7671     pic16_emitcode("rrc","a");
7672     pic16_aopPut(AOP(result),"a",MSB24-offl);
7673
7674     MOVA(pic16_aopGet(AOP(left),MSB16,FALSE,FALSE));
7675     pic16_emitcode("rrc","a");
7676     pic16_aopPut(AOP(result),"a",MSB16-offl);
7677
7678     if(offl == LSB){
7679         MOVA(pic16_aopGet(AOP(left),LSB,FALSE,FALSE));
7680         pic16_emitcode("rrc","a");
7681         pic16_aopPut(AOP(result),"a",LSB);
7682     }
7683 }
7684
7685 /*-----------------------------------------------------------------*/
7686 /* genrshFour - shift four byte by a known amount != 0             */
7687 /*-----------------------------------------------------------------*/
7688 static void genrshFour (operand *result, operand *left,
7689                         int shCount, int sign)
7690 {
7691   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7692   /* if shifting more that 3 bytes */
7693   if(shCount >= 24 ) {
7694     shCount -= 24;
7695     if(shCount)
7696       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7697     else
7698       movLeft2Result(left, MSB32, result, LSB);
7699
7700     pic16_addSign(result, MSB16, sign);
7701   }
7702   else if(shCount >= 16){
7703     shCount -= 16;
7704     if(shCount)
7705       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7706     else{
7707       movLeft2Result(left, MSB24, result, LSB);
7708       movLeft2Result(left, MSB32, result, MSB16);
7709     }
7710     pic16_addSign(result, MSB24, sign);
7711   }
7712   else if(shCount >= 8){
7713     shCount -= 8;
7714     if(shCount == 1)
7715       shiftRLong(left, MSB16, result, sign);
7716     else if(shCount == 0){
7717       movLeft2Result(left, MSB16, result, LSB);
7718       movLeft2Result(left, MSB24, result, MSB16);
7719       movLeft2Result(left, MSB32, result, MSB24);
7720       pic16_addSign(result, MSB32, sign);
7721     }
7722     else{
7723       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7724       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7725       /* the last shift is signed */
7726       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7727       pic16_addSign(result, MSB32, sign);
7728     }
7729   }
7730   else{   /* 1 <= shCount <= 7 */
7731     if(shCount <= 2){
7732       shiftRLong(left, LSB, result, sign);
7733       if(shCount == 2)
7734         shiftRLong(result, LSB, result, sign);
7735     }
7736     else{
7737       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7738       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7739       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7740     }
7741   }
7742 }
7743
7744 /*-----------------------------------------------------------------*/
7745 /* genRightShiftLiteral - right shifting by known count            */
7746 /*-----------------------------------------------------------------*/
7747 static void genRightShiftLiteral (operand *left,
7748                                   operand *right,
7749                                   operand *result,
7750                                   iCode *ic,
7751                                   int sign)
7752 {    
7753   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7754   int lsize,res_size;
7755
7756   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7757   pic16_freeAsmop(right,NULL,ic,TRUE);
7758
7759   pic16_aopOp(left,ic,FALSE);
7760   pic16_aopOp(result,ic,FALSE);
7761
7762 #if VIEW_SIZE
7763   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7764                  AOP_SIZE(left));
7765 #endif
7766
7767   lsize = pic16_getDataSize(left);
7768   res_size = pic16_getDataSize(result);
7769   /* test the LEFT size !!! */
7770
7771   /* I suppose that the left size >= result size */
7772   if(shCount == 0){
7773     while(res_size--)
7774       movLeft2Result(left, lsize, result, res_size);
7775   }
7776
7777   else if(shCount >= (lsize * 8)){
7778
7779     if(res_size == 1) {
7780       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7781       if(sign) {
7782         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7783         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7784       }
7785     } else {
7786
7787       if(sign) {
7788         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7789         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7790         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7791         while(res_size--)
7792           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7793
7794       } else {
7795
7796         while(res_size--)
7797           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7798       }
7799     }
7800   } else {
7801
7802     switch (res_size) {
7803     case 1:
7804       genrshOne (result,left,shCount,sign);
7805       break;
7806
7807     case 2:
7808       genrshTwo (result,left,shCount,sign);
7809       break;
7810
7811     case 4:
7812       genrshFour (result,left,shCount,sign);
7813       break;
7814     default :
7815       break;
7816     }
7817
7818   }
7819
7820   pic16_freeAsmop(left,NULL,ic,TRUE);
7821   pic16_freeAsmop(result,NULL,ic,TRUE);
7822 }
7823
7824 /*-----------------------------------------------------------------*/
7825 /* genSignedRightShift - right shift of signed number              */
7826 /*-----------------------------------------------------------------*/
7827 static void genSignedRightShift (iCode *ic)
7828 {
7829   operand *right, *left, *result;
7830   int size, offset;
7831   //  char *l;
7832   symbol *tlbl, *tlbl1 ;
7833   pCodeOp *pctemp;
7834
7835   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7836
7837   /* we do it the hard way put the shift count in b
7838      and loop thru preserving the sign */
7839   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7840
7841   right = IC_RIGHT(ic);
7842   left  = IC_LEFT(ic);
7843   result = IC_RESULT(ic);
7844
7845   pic16_aopOp(right,ic,FALSE);  
7846   pic16_aopOp(left,ic,FALSE);
7847   pic16_aopOp(result,ic,FALSE);
7848
7849
7850   if ( AOP_TYPE(right) == AOP_LIT) {
7851     genRightShiftLiteral (left,right,result,ic,1);
7852     return ;
7853   }
7854   /* shift count is unknown then we have to form 
7855      a loop get the loop count in B : Note: we take
7856      only the lower order byte since shifting
7857      more that 32 bits make no sense anyway, ( the
7858      largest size of an object can be only 32 bits ) */  
7859
7860   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7861   //pic16_emitcode("inc","b");
7862   //pic16_freeAsmop (right,NULL,ic,TRUE);
7863   //pic16_aopOp(left,ic,FALSE);
7864   //pic16_aopOp(result,ic,FALSE);
7865
7866   /* now move the left to the result if they are not the
7867      same */
7868   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7869       AOP_SIZE(result) > 1) {
7870
7871     size = AOP_SIZE(result);
7872     offset=0;
7873     while (size--) { 
7874       /*
7875         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7876         if (*l == '@' && IS_AOP_PREG(result)) {
7877
7878         pic16_emitcode("mov","a,%s",l);
7879         pic16_aopPut(AOP(result),"a",offset);
7880         } else
7881         pic16_aopPut(AOP(result),l,offset);
7882       */
7883       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7884       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7885
7886       offset++;
7887     }
7888   }
7889
7890   /* mov the highest order bit to OVR */    
7891   tlbl = newiTempLabel(NULL);
7892   tlbl1= newiTempLabel(NULL);
7893
7894   size = AOP_SIZE(result);
7895   offset = size - 1;
7896
7897   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7898
7899   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7900
7901   /* offset should be 0, 1 or 3 */
7902   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7903   emitSKPNZ;
7904   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7905
7906   pic16_emitpcode(POC_MOVWF, pctemp);
7907
7908
7909   pic16_emitpLabel(tlbl->key);
7910
7911   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
7912   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
7913
7914   while(--size) {
7915     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
7916   }
7917
7918   pic16_emitpcode(POC_DECFSZ,  pctemp);
7919   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7920   pic16_emitpLabel(tlbl1->key);
7921
7922   pic16_popReleaseTempReg(pctemp);
7923 #if 0
7924   size = AOP_SIZE(result);
7925   offset = size - 1;
7926   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7927   pic16_emitcode("rlc","a");
7928   pic16_emitcode("mov","ov,c");
7929   /* if it is only one byte then */
7930   if (size == 1) {
7931     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
7932     MOVA(l);
7933     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7934     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7935     pic16_emitcode("mov","c,ov");
7936     pic16_emitcode("rrc","a");
7937     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7938     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7939     pic16_aopPut(AOP(result),"a",0);
7940     goto release ;
7941   }
7942
7943   reAdjustPreg(AOP(result));
7944   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7945   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7946   pic16_emitcode("mov","c,ov");
7947   while (size--) {
7948     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7949     MOVA(l);
7950     pic16_emitcode("rrc","a");         
7951     pic16_aopPut(AOP(result),"a",offset--);
7952   }
7953   reAdjustPreg(AOP(result));
7954   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7955   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7956
7957  release:
7958 #endif
7959
7960   pic16_freeAsmop(left,NULL,ic,TRUE);
7961   pic16_freeAsmop(result,NULL,ic,TRUE);
7962   pic16_freeAsmop(right,NULL,ic,TRUE);
7963 }
7964
7965 /*-----------------------------------------------------------------*/
7966 /* genRightShift - generate code for right shifting                */
7967 /*-----------------------------------------------------------------*/
7968 static void genRightShift (iCode *ic)
7969 {
7970     operand *right, *left, *result;
7971     sym_link *retype ;
7972     int size, offset;
7973     char *l;
7974     symbol *tlbl, *tlbl1 ;
7975
7976     /* if signed then we do it the hard way preserve the
7977     sign bit moving it inwards */
7978     retype = getSpec(operandType(IC_RESULT(ic)));
7979     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7980
7981     if (!SPEC_USIGN(retype)) {
7982         genSignedRightShift (ic);
7983         return ;
7984     }
7985
7986     /* signed & unsigned types are treated the same : i.e. the
7987     signed is NOT propagated inwards : quoting from the
7988     ANSI - standard : "for E1 >> E2, is equivalent to division
7989     by 2**E2 if unsigned or if it has a non-negative value,
7990     otherwise the result is implementation defined ", MY definition
7991     is that the sign does not get propagated */
7992
7993     right = IC_RIGHT(ic);
7994     left  = IC_LEFT(ic);
7995     result = IC_RESULT(ic);
7996
7997     pic16_aopOp(right,ic,FALSE);
7998
7999     /* if the shift count is known then do it 
8000     as efficiently as possible */
8001     if (AOP_TYPE(right) == AOP_LIT) {
8002         genRightShiftLiteral (left,right,result,ic, 0);
8003         return ;
8004     }
8005
8006     /* shift count is unknown then we have to form 
8007     a loop get the loop count in B : Note: we take
8008     only the lower order byte since shifting
8009     more that 32 bits make no sense anyway, ( the
8010     largest size of an object can be only 32 bits ) */  
8011
8012     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8013     pic16_emitcode("inc","b");
8014     pic16_aopOp(left,ic,FALSE);
8015     pic16_aopOp(result,ic,FALSE);
8016
8017     /* now move the left to the result if they are not the
8018     same */
8019     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8020         AOP_SIZE(result) > 1) {
8021
8022         size = AOP_SIZE(result);
8023         offset=0;
8024         while (size--) {
8025             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8026             if (*l == '@' && IS_AOP_PREG(result)) {
8027
8028                 pic16_emitcode("mov","a,%s",l);
8029                 pic16_aopPut(AOP(result),"a",offset);
8030             } else
8031                 pic16_aopPut(AOP(result),l,offset);
8032             offset++;
8033         }
8034     }
8035
8036     tlbl = newiTempLabel(NULL);
8037     tlbl1= newiTempLabel(NULL);
8038     size = AOP_SIZE(result);
8039     offset = size - 1;
8040
8041     /* if it is only one byte then */
8042     if (size == 1) {
8043
8044       tlbl = newiTempLabel(NULL);
8045       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8046         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8047         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8048       }
8049
8050       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8051       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8052       pic16_emitpLabel(tlbl->key);
8053       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8054       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8055       emitSKPC;
8056       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8057
8058       goto release ;
8059     }
8060
8061     reAdjustPreg(AOP(result));
8062     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8063     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8064     CLRC;
8065     while (size--) {
8066         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8067         MOVA(l);
8068         pic16_emitcode("rrc","a");         
8069         pic16_aopPut(AOP(result),"a",offset--);
8070     }
8071     reAdjustPreg(AOP(result));
8072
8073     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8074     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8075
8076 release:
8077     pic16_freeAsmop(left,NULL,ic,TRUE);
8078     pic16_freeAsmop (right,NULL,ic,TRUE);
8079     pic16_freeAsmop(result,NULL,ic,TRUE);
8080 }
8081
8082 /*-----------------------------------------------------------------*/
8083 /* genUnpackBits - generates code for unpacking bits               */
8084 /*-----------------------------------------------------------------*/
8085 static void genUnpackBits (operand *result, char *rname, int ptype)
8086 {    
8087     int shCnt ;
8088     int rlen = 0 ;
8089     sym_link *etype;
8090     int offset = 0 ;
8091
8092     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8093     etype = getSpec(operandType(result));
8094
8095     /* read the first byte  */
8096     switch (ptype) {
8097
8098     case POINTER:
8099     case IPOINTER:
8100         pic16_emitcode("mov","a,@%s",rname);
8101         break;
8102         
8103     case PPOINTER:
8104         pic16_emitcode("movx","a,@%s",rname);
8105         break;
8106         
8107     case FPOINTER:
8108         pic16_emitcode("movx","a,@dptr");
8109         break;
8110
8111     case CPOINTER:
8112         pic16_emitcode("clr","a");
8113         pic16_emitcode("movc","a","@a+dptr");
8114         break;
8115
8116     case GPOINTER:
8117         pic16_emitcode("lcall","__gptrget");
8118         break;
8119     }
8120
8121     /* if we have bitdisplacement then it fits   */
8122     /* into this byte completely or if length is */
8123     /* less than a byte                          */
8124     if ((shCnt = SPEC_BSTR(etype)) || 
8125         (SPEC_BLEN(etype) <= 8))  {
8126
8127         /* shift right acc */
8128         AccRsh(shCnt);
8129
8130         pic16_emitcode("anl","a,#0x%02x",
8131                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8132         pic16_aopPut(AOP(result),"a",offset);
8133         return ;
8134     }
8135
8136     /* bit field did not fit in a byte  */
8137     rlen = SPEC_BLEN(etype) - 8;
8138     pic16_aopPut(AOP(result),"a",offset++);
8139
8140     while (1)  {
8141
8142         switch (ptype) {
8143         case POINTER:
8144         case IPOINTER:
8145             pic16_emitcode("inc","%s",rname);
8146             pic16_emitcode("mov","a,@%s",rname);
8147             break;
8148             
8149         case PPOINTER:
8150             pic16_emitcode("inc","%s",rname);
8151             pic16_emitcode("movx","a,@%s",rname);
8152             break;
8153
8154         case FPOINTER:
8155             pic16_emitcode("inc","dptr");
8156             pic16_emitcode("movx","a,@dptr");
8157             break;
8158             
8159         case CPOINTER:
8160             pic16_emitcode("clr","a");
8161             pic16_emitcode("inc","dptr");
8162             pic16_emitcode("movc","a","@a+dptr");
8163             break;
8164             
8165         case GPOINTER:
8166             pic16_emitcode("inc","dptr");
8167             pic16_emitcode("lcall","__gptrget");
8168             break;
8169         }
8170
8171         rlen -= 8;            
8172         /* if we are done */
8173         if ( rlen <= 0 )
8174             break ;
8175         
8176         pic16_aopPut(AOP(result),"a",offset++);
8177                               
8178     }
8179     
8180     if (rlen) {
8181         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8182         pic16_aopPut(AOP(result),"a",offset);          
8183     }
8184     
8185     return ;
8186 }
8187
8188 #if 0
8189 /*-----------------------------------------------------------------*/
8190 /* genDataPointerGet - generates code when ptr offset is known     */
8191 /*-----------------------------------------------------------------*/
8192 static void genDataPointerGet (operand *left, 
8193                                operand *result, 
8194                                iCode *ic)
8195 {
8196   int size , offset = 0;
8197
8198
8199   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8200
8201
8202   /* optimization - most of the time, left and result are the same
8203    * address, but different types. for the pic code, we could omit
8204    * the following
8205    */
8206
8207   pic16_aopOp(result,ic,TRUE);
8208
8209   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8210
8211   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8212
8213   size = AOP_SIZE(result);
8214
8215   while (size--) {
8216     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8217     offset++;
8218   }
8219
8220   pic16_freeAsmop(left,NULL,ic,TRUE);
8221   pic16_freeAsmop(result,NULL,ic,TRUE);
8222 }
8223 #endif
8224 /*-----------------------------------------------------------------*/
8225 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8226 /*-----------------------------------------------------------------*/
8227 static void genNearPointerGet (operand *left, 
8228                                operand *result, 
8229                                iCode *ic)
8230 {
8231     asmop *aop = NULL;
8232     //regs *preg = NULL ;
8233     char *rname ;
8234     sym_link *rtype, *retype;
8235     sym_link *ltype = operandType(left);    
8236     //char buffer[80];
8237
8238     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8239
8240     rtype = operandType(result);
8241     retype= getSpec(rtype);
8242     
8243     pic16_aopOp(left,ic,FALSE);
8244     
8245     /* if left is rematerialisable and
8246        result is not bit variable type and
8247        the left is pointer to data space i.e
8248        lower 128 bytes of space */
8249     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8250         !IS_BITVAR(retype)         &&
8251         DCL_TYPE(ltype) == POINTER) {
8252       //genDataPointerGet (left,result,ic);
8253         return ;
8254     }
8255     
8256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8257
8258         /* if the value is already in a pointer register
8259        then don't need anything more */
8260     if (!AOP_INPREG(AOP(left))) {
8261         /* otherwise get a free pointer register */
8262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8263 /*
8264         aop = newAsmop(0);
8265         preg = getFreePtr(ic,&aop,FALSE);
8266         pic16_emitcode("mov","%s,%s",
8267                 preg->name,
8268                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8269         rname = preg->name ;
8270 */
8271     rname ="BAD";
8272     } else
8273         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8274     
8275     pic16_aopOp (result,ic,FALSE);
8276     
8277       /* if bitfield then unpack the bits */
8278     if (IS_BITVAR(retype)) 
8279         genUnpackBits (result,rname,POINTER);
8280     else {
8281         /* we have can just get the values */
8282       int size = AOP_SIZE(result);
8283       int offset = 0 ;  
8284         
8285       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8286
8287       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8288       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8289       while(size--) {
8290         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8291         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8292         if(size)
8293           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8294       }
8295 /*
8296         while (size--) {
8297             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8298
8299                 pic16_emitcode("mov","a,@%s",rname);
8300                 pic16_aopPut(AOP(result),"a",offset);
8301             } else {
8302                 sprintf(buffer,"@%s",rname);
8303                 pic16_aopPut(AOP(result),buffer,offset);
8304             }
8305             offset++ ;
8306             if (size)
8307                 pic16_emitcode("inc","%s",rname);
8308         }
8309 */
8310     }
8311
8312     /* now some housekeeping stuff */
8313     if (aop) {
8314         /* we had to allocate for this iCode */
8315     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8316         pic16_freeAsmop(NULL,aop,ic,TRUE);
8317     } else { 
8318         /* we did not allocate which means left
8319            already in a pointer register, then
8320            if size > 0 && this could be used again
8321            we have to point it back to where it 
8322            belongs */
8323     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8324         if (AOP_SIZE(result) > 1 &&
8325             !OP_SYMBOL(left)->remat &&
8326             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8327               ic->depth )) {
8328             int size = AOP_SIZE(result) - 1;
8329             while (size--)
8330                 pic16_emitcode("dec","%s",rname);
8331         }
8332     }
8333
8334     /* done */
8335     pic16_freeAsmop(left,NULL,ic,TRUE);
8336     pic16_freeAsmop(result,NULL,ic,TRUE);
8337      
8338 }
8339
8340 /*-----------------------------------------------------------------*/
8341 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8342 /*-----------------------------------------------------------------*/
8343 static void genPagedPointerGet (operand *left, 
8344                                operand *result, 
8345                                iCode *ic)
8346 {
8347     asmop *aop = NULL;
8348     regs *preg = NULL ;
8349     char *rname ;
8350     sym_link *rtype, *retype;    
8351
8352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8353
8354     rtype = operandType(result);
8355     retype= getSpec(rtype);
8356     
8357     pic16_aopOp(left,ic,FALSE);
8358
8359   /* if the value is already in a pointer register
8360        then don't need anything more */
8361     if (!AOP_INPREG(AOP(left))) {
8362         /* otherwise get a free pointer register */
8363         aop = newAsmop(0);
8364         preg = getFreePtr(ic,&aop,FALSE);
8365         pic16_emitcode("mov","%s,%s",
8366                 preg->name,
8367                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8368         rname = preg->name ;
8369     } else
8370         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8371     
8372     pic16_freeAsmop(left,NULL,ic,TRUE);
8373     pic16_aopOp (result,ic,FALSE);
8374
8375     /* if bitfield then unpack the bits */
8376     if (IS_BITVAR(retype)) 
8377         genUnpackBits (result,rname,PPOINTER);
8378     else {
8379         /* we have can just get the values */
8380         int size = AOP_SIZE(result);
8381         int offset = 0 ;        
8382         
8383         while (size--) {
8384             
8385             pic16_emitcode("movx","a,@%s",rname);
8386             pic16_aopPut(AOP(result),"a",offset);
8387             
8388             offset++ ;
8389             
8390             if (size)
8391                 pic16_emitcode("inc","%s",rname);
8392         }
8393     }
8394
8395     /* now some housekeeping stuff */
8396     if (aop) {
8397         /* we had to allocate for this iCode */
8398         pic16_freeAsmop(NULL,aop,ic,TRUE);
8399     } else { 
8400         /* we did not allocate which means left
8401            already in a pointer register, then
8402            if size > 0 && this could be used again
8403            we have to point it back to where it 
8404            belongs */
8405         if (AOP_SIZE(result) > 1 &&
8406             !OP_SYMBOL(left)->remat &&
8407             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8408               ic->depth )) {
8409             int size = AOP_SIZE(result) - 1;
8410             while (size--)
8411                 pic16_emitcode("dec","%s",rname);
8412         }
8413     }
8414
8415     /* done */
8416     pic16_freeAsmop(result,NULL,ic,TRUE);
8417     
8418         
8419 }
8420
8421 /*-----------------------------------------------------------------*/
8422 /* genFarPointerGet - gget value from far space                    */
8423 /*-----------------------------------------------------------------*/
8424 static void genFarPointerGet (operand *left,
8425                               operand *result, iCode *ic)
8426 {
8427     int size, offset ;
8428     sym_link *retype = getSpec(operandType(result));
8429
8430     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8431
8432     pic16_aopOp(left,ic,FALSE);
8433
8434     /* if the operand is already in dptr 
8435     then we do nothing else we move the value to dptr */
8436     if (AOP_TYPE(left) != AOP_STR) {
8437         /* if this is remateriazable */
8438         if (AOP_TYPE(left) == AOP_IMMD)
8439             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8440         else { /* we need to get it byte by byte */
8441             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8442             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8443             if (options.model == MODEL_FLAT24)
8444             {
8445                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8446             }
8447         }
8448     }
8449     /* so dptr know contains the address */
8450     pic16_freeAsmop(left,NULL,ic,TRUE);
8451     pic16_aopOp(result,ic,FALSE);
8452
8453     /* if bit then unpack */
8454     if (IS_BITVAR(retype)) 
8455         genUnpackBits(result,"dptr",FPOINTER);
8456     else {
8457         size = AOP_SIZE(result);
8458         offset = 0 ;
8459
8460         while (size--) {
8461             pic16_emitcode("movx","a,@dptr");
8462             pic16_aopPut(AOP(result),"a",offset++);
8463             if (size)
8464                 pic16_emitcode("inc","dptr");
8465         }
8466     }
8467
8468     pic16_freeAsmop(result,NULL,ic,TRUE);
8469 }
8470 #if 0
8471 /*-----------------------------------------------------------------*/
8472 /* genCodePointerGet - get value from code space                  */
8473 /*-----------------------------------------------------------------*/
8474 static void genCodePointerGet (operand *left,
8475                                 operand *result, iCode *ic)
8476 {
8477     int size, offset ;
8478     sym_link *retype = getSpec(operandType(result));
8479
8480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8481
8482     pic16_aopOp(left,ic,FALSE);
8483
8484     /* if the operand is already in dptr 
8485     then we do nothing else we move the value to dptr */
8486     if (AOP_TYPE(left) != AOP_STR) {
8487         /* if this is remateriazable */
8488         if (AOP_TYPE(left) == AOP_IMMD)
8489             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8490         else { /* we need to get it byte by byte */
8491             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8492             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8493             if (options.model == MODEL_FLAT24)
8494             {
8495                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8496             }
8497         }
8498     }
8499     /* so dptr know contains the address */
8500     pic16_freeAsmop(left,NULL,ic,TRUE);
8501     pic16_aopOp(result,ic,FALSE);
8502
8503     /* if bit then unpack */
8504     if (IS_BITVAR(retype)) 
8505         genUnpackBits(result,"dptr",CPOINTER);
8506     else {
8507         size = AOP_SIZE(result);
8508         offset = 0 ;
8509
8510         while (size--) {
8511             pic16_emitcode("clr","a");
8512             pic16_emitcode("movc","a,@a+dptr");
8513             pic16_aopPut(AOP(result),"a",offset++);
8514             if (size)
8515                 pic16_emitcode("inc","dptr");
8516         }
8517     }
8518
8519     pic16_freeAsmop(result,NULL,ic,TRUE);
8520 }
8521 #endif
8522 /*-----------------------------------------------------------------*/
8523 /* genGenPointerGet - gget value from generic pointer space        */
8524 /*-----------------------------------------------------------------*/
8525 static void genGenPointerGet (operand *left,
8526                               operand *result, iCode *ic)
8527 {
8528   int size, offset ;
8529   sym_link *retype = getSpec(operandType(result));
8530
8531   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8532   pic16_aopOp(left,ic,FALSE);
8533   pic16_aopOp(result,ic,FALSE);
8534
8535
8536   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8537
8538   /* if the operand is already in dptr 
8539      then we do nothing else we move the value to dptr */
8540   //  if (AOP_TYPE(left) != AOP_STR) {
8541     /* if this is remateriazable */
8542     if (AOP_TYPE(left) == AOP_IMMD) {
8543       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8544       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8545     }
8546     else { /* we need to get it byte by byte */
8547
8548       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8549       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8550
8551       size = AOP_SIZE(result);
8552       offset = 0 ;
8553
8554       while(size--) {
8555         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8556         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8557         if(size)
8558           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8559       }
8560       goto release;
8561     }
8562     //}
8563   /* so dptr know contains the address */
8564
8565   /* if bit then unpack */
8566         if (IS_BITVAR(retype)) 
8567         genUnpackBits(result,"BAD",GPOINTER);
8568
8569  release:
8570   pic16_freeAsmop(left,NULL,ic,TRUE);
8571   pic16_freeAsmop(result,NULL,ic,TRUE);
8572
8573 }
8574
8575 /*-----------------------------------------------------------------*/
8576 /* genConstPointerGet - get value from const generic pointer space */
8577 /*-----------------------------------------------------------------*/
8578 static void genConstPointerGet (operand *left,
8579                                 operand *result, iCode *ic)
8580 {
8581   //sym_link *retype = getSpec(operandType(result));
8582   symbol *albl = newiTempLabel(NULL);
8583   symbol *blbl = newiTempLabel(NULL);
8584   PIC_OPCODE poc;
8585
8586   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8587   pic16_aopOp(left,ic,FALSE);
8588   pic16_aopOp(result,ic,FALSE);
8589
8590
8591   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8592
8593   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8594
8595   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8596   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8597   pic16_emitpLabel(albl->key);
8598
8599   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8600     
8601   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8602   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8603   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8604   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8605   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8606
8607   pic16_emitpLabel(blbl->key);
8608
8609   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8610
8611
8612   pic16_freeAsmop(left,NULL,ic,TRUE);
8613   pic16_freeAsmop(result,NULL,ic,TRUE);
8614
8615 }
8616 /*-----------------------------------------------------------------*/
8617 /* genPointerGet - generate code for pointer get                   */
8618 /*-----------------------------------------------------------------*/
8619 static void genPointerGet (iCode *ic)
8620 {
8621     operand *left, *result ;
8622     sym_link *type, *etype;
8623     int p_type;
8624
8625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8626
8627     left = IC_LEFT(ic);
8628     result = IC_RESULT(ic) ;
8629
8630     /* depending on the type of pointer we need to
8631     move it to the correct pointer register */
8632     type = operandType(left);
8633     etype = getSpec(type);
8634
8635 #if 0
8636     if (IS_PTR_CONST(type))
8637 #else
8638     if (IS_CODEPTR(type))
8639 #endif
8640       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8641
8642     /* if left is of type of pointer then it is simple */
8643     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8644         p_type = DCL_TYPE(type);
8645     else {
8646         /* we have to go by the storage class */
8647         p_type = PTR_TYPE(SPEC_OCLS(etype));
8648
8649         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8650
8651         if (SPEC_OCLS(etype)->codesp ) {
8652           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8653           //p_type = CPOINTER ; 
8654         }
8655         else
8656             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8657               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8658                /*p_type = FPOINTER ;*/ 
8659             else
8660                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8661                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8662 /*                  p_type = PPOINTER; */
8663                 else
8664                     if (SPEC_OCLS(etype) == idata )
8665                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8666 /*                      p_type = IPOINTER; */
8667                     else
8668                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8669 /*                      p_type = POINTER ; */
8670     }
8671
8672     /* now that we have the pointer type we assign
8673     the pointer values */
8674     switch (p_type) {
8675
8676     case POINTER:       
8677     case IPOINTER:
8678         genNearPointerGet (left,result,ic);
8679         break;
8680
8681     case PPOINTER:
8682         genPagedPointerGet(left,result,ic);
8683         break;
8684
8685     case FPOINTER:
8686         genFarPointerGet (left,result,ic);
8687         break;
8688
8689     case CPOINTER:
8690         genConstPointerGet (left,result,ic);
8691         //pic16_emitcodePointerGet (left,result,ic);
8692         break;
8693
8694     case GPOINTER:
8695 #if 0
8696       if (IS_PTR_CONST(type))
8697         genConstPointerGet (left,result,ic);
8698       else
8699 #endif
8700         genGenPointerGet (left,result,ic);
8701       break;
8702     }
8703
8704 }
8705
8706 /*-----------------------------------------------------------------*/
8707 /* genPackBits - generates code for packed bit storage             */
8708 /*-----------------------------------------------------------------*/
8709 static void genPackBits (sym_link    *etype ,
8710                          operand *right ,
8711                          char *rname, int p_type)
8712 {
8713     int shCount = 0 ;
8714     int offset = 0  ;
8715     int rLen = 0 ;
8716     int blen, bstr ;   
8717     char *l ;
8718
8719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8720     blen = SPEC_BLEN(etype);
8721     bstr = SPEC_BSTR(etype);
8722
8723     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8724     MOVA(l);   
8725
8726     /* if the bit lenth is less than or    */
8727     /* it exactly fits a byte then         */
8728     if (SPEC_BLEN(etype) <= 8 )  {
8729         shCount = SPEC_BSTR(etype) ;
8730
8731         /* shift left acc */
8732         AccLsh(shCount);
8733
8734         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8735
8736
8737             switch (p_type) {
8738                 case POINTER:
8739                     pic16_emitcode ("mov","b,a");
8740                     pic16_emitcode("mov","a,@%s",rname);
8741                     break;
8742
8743                 case FPOINTER:
8744                     pic16_emitcode ("mov","b,a");
8745                     pic16_emitcode("movx","a,@dptr");
8746                     break;
8747
8748                 case GPOINTER:
8749                     pic16_emitcode ("push","b");
8750                     pic16_emitcode ("push","acc");
8751                     pic16_emitcode ("lcall","__gptrget");
8752                     pic16_emitcode ("pop","b");
8753                     break;
8754             }
8755
8756             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8757                       ((unsigned char)(0xFF << (blen+bstr)) | 
8758                        (unsigned char)(0xFF >> (8-bstr)) ) );
8759             pic16_emitcode ("orl","a,b");
8760             if (p_type == GPOINTER)
8761                 pic16_emitcode("pop","b");
8762         }
8763     }
8764
8765     switch (p_type) {
8766         case POINTER:
8767             pic16_emitcode("mov","@%s,a",rname);
8768             break;
8769
8770         case FPOINTER:
8771             pic16_emitcode("movx","@dptr,a");
8772             break;
8773
8774         case GPOINTER:
8775             DEBUGpic16_emitcode(";lcall","__gptrput");
8776             break;
8777     }
8778
8779     /* if we r done */
8780     if ( SPEC_BLEN(etype) <= 8 )
8781         return ;
8782
8783     pic16_emitcode("inc","%s",rname);
8784     rLen = SPEC_BLEN(etype) ;     
8785
8786     /* now generate for lengths greater than one byte */
8787     while (1) {
8788
8789         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8790
8791         rLen -= 8 ;
8792         if (rLen <= 0 )
8793             break ;
8794
8795         switch (p_type) {
8796             case POINTER:
8797                 if (*l == '@') {
8798                     MOVA(l);
8799                     pic16_emitcode("mov","@%s,a",rname);
8800                 } else
8801                     pic16_emitcode("mov","@%s,%s",rname,l);
8802                 break;
8803
8804             case FPOINTER:
8805                 MOVA(l);
8806                 pic16_emitcode("movx","@dptr,a");
8807                 break;
8808
8809             case GPOINTER:
8810                 MOVA(l);
8811                 DEBUGpic16_emitcode(";lcall","__gptrput");
8812                 break;  
8813         }   
8814         pic16_emitcode ("inc","%s",rname);
8815     }
8816
8817     MOVA(l);
8818
8819     /* last last was not complete */
8820     if (rLen)   {
8821         /* save the byte & read byte */
8822         switch (p_type) {
8823             case POINTER:
8824                 pic16_emitcode ("mov","b,a");
8825                 pic16_emitcode("mov","a,@%s",rname);
8826                 break;
8827
8828             case FPOINTER:
8829                 pic16_emitcode ("mov","b,a");
8830                 pic16_emitcode("movx","a,@dptr");
8831                 break;
8832
8833             case GPOINTER:
8834                 pic16_emitcode ("push","b");
8835                 pic16_emitcode ("push","acc");
8836                 pic16_emitcode ("lcall","__gptrget");
8837                 pic16_emitcode ("pop","b");
8838                 break;
8839         }
8840
8841         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8842         pic16_emitcode ("orl","a,b");
8843     }
8844
8845     if (p_type == GPOINTER)
8846         pic16_emitcode("pop","b");
8847
8848     switch (p_type) {
8849
8850     case POINTER:
8851         pic16_emitcode("mov","@%s,a",rname);
8852         break;
8853         
8854     case FPOINTER:
8855         pic16_emitcode("movx","@dptr,a");
8856         break;
8857         
8858     case GPOINTER:
8859         DEBUGpic16_emitcode(";lcall","__gptrput");
8860         break;                  
8861     }
8862 }
8863 /*-----------------------------------------------------------------*/
8864 /* genDataPointerSet - remat pointer to data space                 */
8865 /*-----------------------------------------------------------------*/
8866 static void genDataPointerSet(operand *right,
8867                               operand *result,
8868                               iCode *ic)
8869 {
8870     int size, offset = 0 ;
8871     char *l, buffer[256];
8872
8873     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8874     pic16_aopOp(right,ic,FALSE);
8875     
8876     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8877     size = AOP_SIZE(right);
8878 /*
8879     if ( AOP_TYPE(result) == AOP_PCODE) {
8880       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8881               AOP(result)->aopu.pcop->name,
8882               PCOI(AOP(result)->aopu.pcop)->offset);
8883     }
8884 */
8885
8886     // tsd, was l+1 - the underline `_' prefix was being stripped
8887     while (size--) {
8888       if (offset) {
8889         sprintf(buffer,"(%s + %d)",l,offset);
8890         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
8891       } else
8892         sprintf(buffer,"%s",l);
8893
8894         if (AOP_TYPE(right) == AOP_LIT) {
8895           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8896           lit = lit >> (8*offset);
8897           if(lit&0xff) {
8898             pic16_emitcode("movlw","%d",lit);
8899             pic16_emitcode("movwf","%s",buffer);
8900
8901             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8902             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8903             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8904
8905           } else {
8906             pic16_emitcode("clrf","%s",buffer);
8907             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
8908             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
8909           }
8910         }else {
8911           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8912           pic16_emitcode("movwf","%s",buffer);
8913
8914           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
8915           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8916           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8917
8918         }
8919
8920         offset++;
8921     }
8922
8923     pic16_freeAsmop(right,NULL,ic,TRUE);
8924     pic16_freeAsmop(result,NULL,ic,TRUE);
8925 }
8926
8927 /*-----------------------------------------------------------------*/
8928 /* genNearPointerSet - pic16_emitcode for near pointer put                */
8929 /*-----------------------------------------------------------------*/
8930 static void genNearPointerSet (operand *right,
8931                                operand *result, 
8932                                iCode *ic)
8933 {
8934   asmop *aop = NULL;
8935   char *l;
8936   sym_link *retype;
8937   sym_link *ptype = operandType(result);
8938
8939     
8940   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8941   retype= getSpec(operandType(right));
8942
8943   pic16_aopOp(result,ic,FALSE);
8944
8945     
8946   /* if the result is rematerializable &
8947      in data space & not a bit variable */
8948   //if (AOP_TYPE(result) == AOP_IMMD &&
8949   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8950       DCL_TYPE(ptype) == POINTER   &&
8951       !IS_BITVAR(retype)) {
8952     genDataPointerSet (right,result,ic);
8953     pic16_freeAsmop(result,NULL,ic,TRUE);
8954     return;
8955   }
8956
8957   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8958   pic16_aopOp(right,ic,FALSE);
8959   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8960
8961   /* if the value is already in a pointer register
8962      then don't need anything more */
8963   if (!AOP_INPREG(AOP(result))) {
8964     /* otherwise get a free pointer register */
8965     //aop = newAsmop(0);
8966     //preg = getFreePtr(ic,&aop,FALSE);
8967     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8968     //pic16_emitcode("mov","%s,%s",
8969     //         preg->name,
8970     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
8971     //rname = preg->name ;
8972     //pic16_emitcode("movwf","fsr0");
8973     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
8974     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
8975     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8976     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8977     goto release;
8978
8979   }// else
8980 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
8981
8982   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8983
8984   /* if bitfield then unpack the bits */
8985   if (IS_BITVAR(retype)) {
8986     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8987            "The programmer is obviously confused");
8988 //      genPackBits (retype,right,"BAD",POINTER);
8989     exit(1);
8990   }
8991   else {
8992     /* we have can just get the values */
8993     int size = AOP_SIZE(right);
8994     int offset = 0 ;    
8995
8996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8997     while (size--) {
8998       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
8999       if (*l == '@' ) {
9000         //MOVA(l);
9001         //pic16_emitcode("mov","@%s,a",rname);
9002         pic16_emitcode("movf","indf0,w ;1");
9003       } else {
9004
9005         if (AOP_TYPE(right) == AOP_LIT) {
9006           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9007           if(lit) {
9008             pic16_emitcode("movlw","%s",l);
9009             pic16_emitcode("movwf","indf0 ;2");
9010           } else 
9011             pic16_emitcode("clrf","indf0");
9012         }else {
9013           pic16_emitcode("movf","%s,w",l);
9014           pic16_emitcode("movwf","indf0 ;2");
9015         }
9016         //pic16_emitcode("mov","@%s,%s",rname,l);
9017       }
9018       if (size)
9019         pic16_emitcode("incf","fsr0,f ;3");
9020       //pic16_emitcode("inc","%s",rname);
9021       offset++;
9022     }
9023   }
9024
9025   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9026   /* now some housekeeping stuff */
9027   if (aop) {
9028     /* we had to allocate for this iCode */
9029     pic16_freeAsmop(NULL,aop,ic,TRUE);
9030   } else { 
9031     /* we did not allocate which means left
9032        already in a pointer register, then
9033        if size > 0 && this could be used again
9034        we have to point it back to where it 
9035        belongs */
9036     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9037     if (AOP_SIZE(right) > 1 &&
9038         !OP_SYMBOL(result)->remat &&
9039         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9040           ic->depth )) {
9041       int size = AOP_SIZE(right) - 1;
9042       while (size--)
9043         pic16_emitcode("decf","fsr0,f");
9044       //pic16_emitcode("dec","%s",rname);
9045     }
9046   }
9047
9048   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9049   /* done */
9050  release:
9051   pic16_freeAsmop(right,NULL,ic,TRUE);
9052   pic16_freeAsmop(result,NULL,ic,TRUE);
9053 }
9054
9055 /*-----------------------------------------------------------------*/
9056 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9057 /*-----------------------------------------------------------------*/
9058 static void genPagedPointerSet (operand *right,
9059                                operand *result, 
9060                                iCode *ic)
9061 {
9062     asmop *aop = NULL;
9063     regs *preg = NULL ;
9064     char *rname , *l;
9065     sym_link *retype;
9066        
9067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9068
9069     retype= getSpec(operandType(right));
9070     
9071     pic16_aopOp(result,ic,FALSE);
9072     
9073     /* if the value is already in a pointer register
9074        then don't need anything more */
9075     if (!AOP_INPREG(AOP(result))) {
9076         /* otherwise get a free pointer register */
9077         aop = newAsmop(0);
9078         preg = getFreePtr(ic,&aop,FALSE);
9079         pic16_emitcode("mov","%s,%s",
9080                 preg->name,
9081                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9082         rname = preg->name ;
9083     } else
9084         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9085     
9086     pic16_freeAsmop(result,NULL,ic,TRUE);
9087     pic16_aopOp (right,ic,FALSE);
9088
9089     /* if bitfield then unpack the bits */
9090     if (IS_BITVAR(retype)) 
9091         genPackBits (retype,right,rname,PPOINTER);
9092     else {
9093         /* we have can just get the values */
9094         int size = AOP_SIZE(right);
9095         int offset = 0 ;        
9096         
9097         while (size--) {
9098             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9099             
9100             MOVA(l);
9101             pic16_emitcode("movx","@%s,a",rname);
9102
9103             if (size)
9104                 pic16_emitcode("inc","%s",rname);
9105
9106             offset++;
9107         }
9108     }
9109     
9110     /* now some housekeeping stuff */
9111     if (aop) {
9112         /* we had to allocate for this iCode */
9113         pic16_freeAsmop(NULL,aop,ic,TRUE);
9114     } else { 
9115         /* we did not allocate which means left
9116            already in a pointer register, then
9117            if size > 0 && this could be used again
9118            we have to point it back to where it 
9119            belongs */
9120         if (AOP_SIZE(right) > 1 &&
9121             !OP_SYMBOL(result)->remat &&
9122             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9123               ic->depth )) {
9124             int size = AOP_SIZE(right) - 1;
9125             while (size--)
9126                 pic16_emitcode("dec","%s",rname);
9127         }
9128     }
9129
9130     /* done */
9131     pic16_freeAsmop(right,NULL,ic,TRUE);
9132     
9133         
9134 }
9135
9136 /*-----------------------------------------------------------------*/
9137 /* genFarPointerSet - set value from far space                     */
9138 /*-----------------------------------------------------------------*/
9139 static void genFarPointerSet (operand *right,
9140                               operand *result, iCode *ic)
9141 {
9142     int size, offset ;
9143     sym_link *retype = getSpec(operandType(right));
9144
9145     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9146     pic16_aopOp(result,ic,FALSE);
9147
9148     /* if the operand is already in dptr 
9149     then we do nothing else we move the value to dptr */
9150     if (AOP_TYPE(result) != AOP_STR) {
9151         /* if this is remateriazable */
9152         if (AOP_TYPE(result) == AOP_IMMD)
9153             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9154         else { /* we need to get it byte by byte */
9155             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9156             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9157             if (options.model == MODEL_FLAT24)
9158             {
9159                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9160             }
9161         }
9162     }
9163     /* so dptr know contains the address */
9164     pic16_freeAsmop(result,NULL,ic,TRUE);
9165     pic16_aopOp(right,ic,FALSE);
9166
9167     /* if bit then unpack */
9168     if (IS_BITVAR(retype)) 
9169         genPackBits(retype,right,"dptr",FPOINTER);
9170     else {
9171         size = AOP_SIZE(right);
9172         offset = 0 ;
9173
9174         while (size--) {
9175             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9176             MOVA(l);
9177             pic16_emitcode("movx","@dptr,a");
9178             if (size)
9179                 pic16_emitcode("inc","dptr");
9180         }
9181     }
9182
9183     pic16_freeAsmop(right,NULL,ic,TRUE);
9184 }
9185
9186 /*-----------------------------------------------------------------*/
9187 /* genGenPointerSet - set value from generic pointer space         */
9188 /*-----------------------------------------------------------------*/
9189 static void genGenPointerSet (operand *right,
9190                               operand *result, iCode *ic)
9191 {
9192   int size, offset ;
9193   sym_link *retype = getSpec(operandType(right));
9194
9195   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9196
9197   pic16_aopOp(result,ic,FALSE);
9198   pic16_aopOp(right,ic,FALSE);
9199   size = AOP_SIZE(right);
9200
9201   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9202
9203   /* if the operand is already in dptr 
9204      then we do nothing else we move the value to dptr */
9205   if (AOP_TYPE(result) != AOP_STR) {
9206     /* if this is remateriazable */
9207     if (AOP_TYPE(result) == AOP_IMMD) {
9208       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9209       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9210     }
9211     else { /* we need to get it byte by byte */
9212       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9213       size = AOP_SIZE(right);
9214       offset = 0 ;
9215
9216       /* hack hack! see if this the FSR. If so don't load W */
9217       if(AOP_TYPE(right) != AOP_ACC) {
9218
9219 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(result), pic16_popCopyReg(&pic16_pc_fsr0), 0));
9220
9221         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9222         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9223
9224         if(AOP_SIZE(result) > 1) {
9225           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9226           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9227           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9228
9229         }
9230
9231         //if(size==2)
9232         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9233         //if(size==4) {
9234         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9235         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9236         //}
9237
9238         while(size--) {
9239           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9240           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9241           
9242           if(size)
9243             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9244         }
9245
9246
9247         goto release;
9248       } 
9249
9250       if(aopIdx(AOP(result),0) != 4) {
9251
9252         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9253         goto release;
9254       }
9255
9256       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9257       goto release;
9258
9259     }
9260   }
9261   /* so dptr know contains the address */
9262
9263
9264   /* if bit then unpack */
9265   if (IS_BITVAR(retype)) 
9266     genPackBits(retype,right,"dptr",GPOINTER);
9267   else {
9268     size = AOP_SIZE(right);
9269     offset = 0 ;
9270
9271   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9272
9273     while (size--) {
9274
9275       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9276       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9277
9278       if (AOP_TYPE(right) == AOP_LIT) 
9279         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9280       else
9281         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9282
9283       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9284
9285       offset++;
9286     }
9287   }
9288
9289  release:
9290   pic16_freeAsmop(right,NULL,ic,TRUE);
9291   pic16_freeAsmop(result,NULL,ic,TRUE);
9292 }
9293
9294 /*-----------------------------------------------------------------*/
9295 /* genPointerSet - stores the value into a pointer location        */
9296 /*-----------------------------------------------------------------*/
9297 static void genPointerSet (iCode *ic)
9298 {    
9299     operand *right, *result ;
9300     sym_link *type, *etype;
9301     int p_type;
9302
9303     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9304
9305     right = IC_RIGHT(ic);
9306     result = IC_RESULT(ic) ;
9307
9308     /* depending on the type of pointer we need to
9309     move it to the correct pointer register */
9310     type = operandType(result);
9311     etype = getSpec(type);
9312     /* if left is of type of pointer then it is simple */
9313     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9314         p_type = DCL_TYPE(type);
9315     }
9316     else {
9317         /* we have to go by the storage class */
9318         p_type = PTR_TYPE(SPEC_OCLS(etype));
9319
9320 /*      if (SPEC_OCLS(etype)->codesp ) { */
9321 /*          p_type = CPOINTER ;  */
9322 /*      } */
9323 /*      else */
9324 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9325 /*              p_type = FPOINTER ; */
9326 /*          else */
9327 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9328 /*                  p_type = PPOINTER ; */
9329 /*              else */
9330 /*                  if (SPEC_OCLS(etype) == idata ) */
9331 /*                      p_type = IPOINTER ; */
9332 /*                  else */
9333 /*                      p_type = POINTER ; */
9334     }
9335
9336     /* now that we have the pointer type we assign
9337     the pointer values */
9338     switch (p_type) {
9339
9340     case POINTER:
9341     case IPOINTER:
9342         genNearPointerSet (right,result,ic);
9343         break;
9344
9345     case PPOINTER:
9346         genPagedPointerSet (right,result,ic);
9347         break;
9348
9349     case FPOINTER:
9350         genFarPointerSet (right,result,ic);
9351         break;
9352
9353     case GPOINTER:
9354         genGenPointerSet (right,result,ic);
9355         break;
9356
9357     default:
9358       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9359               "genPointerSet: illegal pointer type");
9360     }
9361 }
9362
9363 /*-----------------------------------------------------------------*/
9364 /* genIfx - generate code for Ifx statement                        */
9365 /*-----------------------------------------------------------------*/
9366 static void genIfx (iCode *ic, iCode *popIc)
9367 {
9368   operand *cond = IC_COND(ic);
9369   int isbit =0;
9370
9371   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9372
9373   pic16_aopOp(cond,ic,FALSE);
9374
9375   /* get the value into acc */
9376   if (AOP_TYPE(cond) != AOP_CRY)
9377     pic16_toBoolean(cond);
9378   else
9379     isbit = 1;
9380   /* the result is now in the accumulator */
9381   pic16_freeAsmop(cond,NULL,ic,TRUE);
9382
9383   /* if there was something to be popped then do it */
9384   if (popIc)
9385     genIpop(popIc);
9386
9387   /* if the condition is  a bit variable */
9388   if (isbit && IS_ITEMP(cond) && 
9389       SPIL_LOC(cond)) {
9390     genIfxJump(ic,SPIL_LOC(cond)->rname);
9391     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9392   }
9393   else {
9394     if (isbit && !IS_ITEMP(cond))
9395       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9396     else
9397       genIfxJump(ic,"a");
9398   }
9399   ic->generated = 1;
9400
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genAddrOf - generates code for address of                       */
9405 /*-----------------------------------------------------------------*/
9406 #if 0
9407 static void genAddrOf (iCode *ic)
9408 {
9409   operand *right, *result, *left;
9410   int size, offset ;
9411
9412   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9413
9414
9415   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9416
9417   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9418   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9419   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9420
9421   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9422
9423   size = AOP_SIZE(IC_RESULT(ic));
9424   offset = 0;
9425
9426
9427   while (size--) {
9428     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9429     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9430     offset++;
9431   }
9432
9433
9434   pic16_freeAsmop(left,NULL,ic,FALSE);
9435   pic16_freeAsmop(result,NULL,ic,TRUE);
9436
9437 }
9438
9439 #else   /* new genAddrOf */
9440
9441 static void genAddrOf (iCode *ic)
9442 {
9443   operand *result, *left;
9444   int size;
9445   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9446   pCodeOp *pcop0, *pcop1, *pcop2;
9447
9448         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9449
9450         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9451         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9452
9453         sym = OP_SYMBOL( left );
9454
9455         size = AOP_SIZE(IC_RESULT(ic));
9456
9457         if(pic16_debug_verbose) {
9458                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9459                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9460         }
9461         
9462         /* Assume that what we want the address of is in data space
9463          * since there is no stack on the PIC, yet! -- VR */
9464         /* low */
9465         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9466
9467         /* high */
9468         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9469         
9470         /* upper */
9471         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9472         
9473
9474         if (size == 3) {
9475                 pic16_emitpcode(POC_MOVLW, pcop0);
9476                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9477                 pic16_emitpcode(POC_MOVLW, pcop1);
9478                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9479                 pic16_emitpcode(POC_MOVLW, pcop2);
9480                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9481         } else
9482         if (size == 2) {
9483                 pic16_emitpcode(POC_MOVLW, pcop0);
9484                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9485                 pic16_emitpcode(POC_MOVLW, pcop1);
9486                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9487         } else {
9488                 pic16_emitpcode(POC_MOVLW, pcop0);
9489                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9490         }
9491
9492         pic16_freeAsmop(result,NULL,ic,TRUE);
9493         pic16_freeAsmop(left, NULL, ic, FALSE);
9494 }
9495
9496 #endif  /* new genAddrOf */
9497
9498 #if 0
9499 /*-----------------------------------------------------------------*/
9500 /* genFarFarAssign - assignment when both are in far space         */
9501 /*-----------------------------------------------------------------*/
9502 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9503 {
9504     int size = AOP_SIZE(right);
9505     int offset = 0;
9506     char *l ;
9507     /* first push the right side on to the stack */
9508     while (size--) {
9509         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9510         MOVA(l);
9511         pic16_emitcode ("push","acc");
9512     }
9513     
9514     pic16_freeAsmop(right,NULL,ic,FALSE);
9515     /* now assign DPTR to result */
9516     pic16_aopOp(result,ic,FALSE);
9517     size = AOP_SIZE(result);
9518     while (size--) {
9519         pic16_emitcode ("pop","acc");
9520         pic16_aopPut(AOP(result),"a",--offset);
9521     }
9522     pic16_freeAsmop(result,NULL,ic,FALSE);
9523         
9524 }
9525 #endif
9526
9527 /*-----------------------------------------------------------------*/
9528 /* genAssign - generate code for assignment                        */
9529 /*-----------------------------------------------------------------*/
9530 static void genAssign (iCode *ic)
9531 {
9532   operand *result, *right;
9533   int size, offset,know_W;
9534   unsigned long lit = 0L;
9535
9536   result = IC_RESULT(ic);
9537   right  = IC_RIGHT(ic) ;
9538
9539   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540   
9541   /* if they are the same */
9542   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9543     return ;
9544
9545   pic16_aopOp(right,ic,FALSE);
9546   pic16_aopOp(result,ic,TRUE);
9547
9548   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9549
9550   /* if they are the same registers */
9551   if (pic16_sameRegs(AOP(right),AOP(result)))
9552     goto release;
9553
9554   /* if the result is a bit */
9555   if (AOP_TYPE(result) == AOP_CRY) {
9556     /* if the right size is a literal then
9557        we know what the value is */
9558     if (AOP_TYPE(right) == AOP_LIT) {
9559           
9560       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9561                   pic16_popGet(AOP(result),0));
9562
9563       if (((int) operandLitValue(right))) 
9564         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9565                        AOP(result)->aopu.aop_dir,
9566                        AOP(result)->aopu.aop_dir);
9567       else
9568         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9569                        AOP(result)->aopu.aop_dir,
9570                        AOP(result)->aopu.aop_dir);
9571       goto release;
9572     }
9573
9574     /* the right is also a bit variable */
9575     if (AOP_TYPE(right) == AOP_CRY) {
9576       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9577       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9578       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9579
9580       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9581                      AOP(result)->aopu.aop_dir,
9582                      AOP(result)->aopu.aop_dir);
9583       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9584                      AOP(right)->aopu.aop_dir,
9585                      AOP(right)->aopu.aop_dir);
9586       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9587                      AOP(result)->aopu.aop_dir,
9588                      AOP(result)->aopu.aop_dir);
9589       goto release ;
9590     }
9591
9592     /* we need to or */
9593     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9594     pic16_toBoolean(right);
9595     emitSKPZ;
9596     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9597     //pic16_aopPut(AOP(result),"a",0);
9598     goto release ;
9599   }
9600
9601   /* bit variables done */
9602   /* general case */
9603   size = AOP_SIZE(result);
9604   offset = 0 ;
9605   if(AOP_TYPE(right) == AOP_LIT)
9606     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9607
9608 /* VR - What is this?! */
9609   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9611     if(aopIdx(AOP(result),0) == 4) {
9612   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9613       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9614       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9615       goto release;
9616     } else
9617       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9618   }
9619
9620   know_W=-1;
9621   while (size--) {
9622   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9623     if(AOP_TYPE(right) == AOP_LIT) {
9624       if(lit&0xff) {
9625         if(know_W != (lit&0xff))
9626           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9627         know_W = lit&0xff;
9628         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9629       } else
9630         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9631
9632       lit >>= 8;
9633
9634     } else if (AOP_TYPE(right) == AOP_CRY) {
9635       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9636       if(offset == 0) {
9637         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9638         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9639       }
9640     } else {
9641   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9642
9643 #if 1
9644         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9645            normally should work, but mind that the W register live range
9646            is not checked, so if the code generator assumes that the W
9647            is already loaded after such a pair, wrong code will be generated.
9648            
9649            Checking the live range is the next step.
9650            This is experimental code yet and has not been fully tested yet.
9651            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9652            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9653            
9654         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9655 #else   
9656         /* This is the old code, which is assumed(?!) that works fine(!?) */
9657
9658         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9659         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9660 #endif
9661     }
9662             
9663     offset++;
9664   }
9665
9666     
9667  release:
9668   pic16_freeAsmop (right,NULL,ic,FALSE);
9669   pic16_freeAsmop (result,NULL,ic,TRUE);
9670 }   
9671
9672 /*-----------------------------------------------------------------*/
9673 /* genJumpTab - generates code for jump table                       */
9674 /*-----------------------------------------------------------------*/
9675 static void genJumpTab (iCode *ic)
9676 {
9677     symbol *jtab;
9678     char *l;
9679
9680     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9681
9682     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9683     /* get the condition into accumulator */
9684     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9685     MOVA(l);
9686     /* multiply by three */
9687     pic16_emitcode("add","a,acc");
9688     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9689
9690     jtab = newiTempLabel(NULL);
9691     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9692     pic16_emitcode("jmp","@a+dptr");
9693     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9694
9695     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9696     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9697     emitSKPNC;
9698     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9699     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9700     pic16_emitpLabel(jtab->key);
9701
9702     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9703
9704     /* now generate the jump labels */
9705     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9706          jtab = setNextItem(IC_JTLABELS(ic))) {
9707         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9708         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9709         
9710     }
9711
9712 }
9713
9714 /*-----------------------------------------------------------------*/
9715 /* genMixedOperation - gen code for operators between mixed types  */
9716 /*-----------------------------------------------------------------*/
9717 /*
9718   TSD - Written for the PIC port - but this unfortunately is buggy.
9719   This routine is good in that it is able to efficiently promote 
9720   types to different (larger) sizes. Unfortunately, the temporary
9721   variables that are optimized out by this routine are sometimes
9722   used in other places. So until I know how to really parse the 
9723   iCode tree, I'm going to not be using this routine :(.
9724 */
9725 static int genMixedOperation (iCode *ic)
9726 {
9727 #if 0
9728   operand *result = IC_RESULT(ic);
9729   sym_link *ctype = operandType(IC_LEFT(ic));
9730   operand *right = IC_RIGHT(ic);
9731   int ret = 0;
9732   int big,small;
9733   int offset;
9734
9735   iCode *nextic;
9736   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9737
9738   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9739
9740   nextic = ic->next;
9741   if(!nextic)
9742     return 0;
9743
9744   nextright = IC_RIGHT(nextic);
9745   nextleft  = IC_LEFT(nextic);
9746   nextresult = IC_RESULT(nextic);
9747
9748   pic16_aopOp(right,ic,FALSE);
9749   pic16_aopOp(result,ic,FALSE);
9750   pic16_aopOp(nextright,  nextic, FALSE);
9751   pic16_aopOp(nextleft,   nextic, FALSE);
9752   pic16_aopOp(nextresult, nextic, FALSE);
9753
9754   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9755
9756     operand *t = right;
9757     right = nextright;
9758     nextright = t; 
9759
9760     pic16_emitcode(";remove right +","");
9761
9762   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9763 /*
9764     operand *t = right;
9765     right = nextleft;
9766     nextleft = t; 
9767 */
9768     pic16_emitcode(";remove left +","");
9769   } else
9770     return 0;
9771
9772   big = AOP_SIZE(nextleft);
9773   small = AOP_SIZE(nextright);
9774
9775   switch(nextic->op) {
9776
9777   case '+':
9778     pic16_emitcode(";optimize a +","");
9779     /* if unsigned or not an integral type */
9780     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9781       pic16_emitcode(";add a bit to something","");
9782     } else {
9783
9784       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9785
9786       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9787         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9788         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9789       } else
9790         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9791
9792       offset = 0;
9793       while(--big) {
9794
9795         offset++;
9796
9797         if(--small) {
9798           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9799             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9800             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9801           }
9802
9803           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9804           emitSKPNC;
9805           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9806                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9807                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9808           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9809           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9810
9811         } else {
9812           pic16_emitcode("rlf","known_zero,w");
9813
9814           /*
9815             if right is signed
9816               btfsc  right,7
9817                addlw ff
9818           */
9819           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9820             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9821             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9822           } else {
9823             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9824           }
9825         }
9826       }
9827       ret = 1;
9828     }
9829   }
9830   ret = 1;
9831
9832 release:
9833   pic16_freeAsmop(right,NULL,ic,TRUE);
9834   pic16_freeAsmop(result,NULL,ic,TRUE);
9835   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9836   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9837   if(ret)
9838     nextic->generated = 1;
9839
9840   return ret;
9841 #else
9842   return 0;
9843 #endif
9844 }
9845 /*-----------------------------------------------------------------*/
9846 /* genCast - gen code for casting                                  */
9847 /*-----------------------------------------------------------------*/
9848 static void genCast (iCode *ic)
9849 {
9850   operand *result = IC_RESULT(ic);
9851   sym_link *ctype = operandType(IC_LEFT(ic));
9852   sym_link *rtype = operandType(IC_RIGHT(ic));
9853   operand *right = IC_RIGHT(ic);
9854   int size, offset ;
9855
9856         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9857         /* if they are equivalent then do nothing */
9858         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9859                 return ;
9860
9861         pic16_aopOp(right,ic,FALSE) ;
9862         pic16_aopOp(result,ic,FALSE);
9863
9864         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9865
9866         /* if the result is a bit */
9867         if (AOP_TYPE(result) == AOP_CRY) {
9868         
9869                 /* if the right size is a literal then
9870                  * we know what the value is */
9871                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9872
9873                 if (AOP_TYPE(right) == AOP_LIT) {
9874                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9875                                 pic16_popGet(AOP(result),0));
9876
9877                         if (((int) operandLitValue(right))) 
9878                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9879                                         AOP(result)->aopu.aop_dir,
9880                                         AOP(result)->aopu.aop_dir);
9881                         else
9882                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9883                                         AOP(result)->aopu.aop_dir,
9884                                         AOP(result)->aopu.aop_dir);
9885                         goto release;
9886                 }
9887
9888                 /* the right is also a bit variable */
9889                 if (AOP_TYPE(right) == AOP_CRY) {
9890                         emitCLRC;
9891                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9892
9893                         pic16_emitcode("clrc","");
9894                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9895                                 AOP(right)->aopu.aop_dir,
9896                                 AOP(right)->aopu.aop_dir);
9897                         pic16_aopPut(AOP(result),"c",0);
9898                         goto release ;
9899                 }
9900
9901                 /* we need to or */
9902                 if (AOP_TYPE(right) == AOP_REG) {
9903                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9904                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9905                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9906                 }
9907                 pic16_toBoolean(right);
9908                 pic16_aopPut(AOP(result),"a",0);
9909                 goto release ;
9910         }
9911
9912         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9913           int offset = 1;
9914
9915                 size = AOP_SIZE(result);
9916
9917                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9918
9919                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9920                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9921                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9922
9923                 while (size--)
9924                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9925
9926                 goto release;
9927         }
9928
9929         /* if they are the same size : or less */
9930         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9931
9932                 /* if they are in the same place */
9933                 if (pic16_sameRegs(AOP(right),AOP(result)))
9934                         goto release;
9935
9936                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9937 #if 0
9938                 if (IS_PTR_CONST(rtype))
9939 #else
9940                 if (IS_CODEPTR(rtype))
9941 #endif
9942                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9943
9944 #if 0
9945                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9946 #else
9947                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9948 #endif
9949                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9950
9951 #if 0
9952                 if(AOP_TYPE(right) == AOP_IMMD) {
9953                   pCodeOp *pcop0, *pcop1, *pcop2;
9954                   symbol *sym = OP_SYMBOL( right );
9955
9956                         size = AOP_SIZE(result);
9957                         /* low */
9958                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9959                         /* high */
9960                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9961                         /* upper */
9962                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9963         
9964                         if (size == 3) {
9965                                 pic16_emitpcode(POC_MOVLW, pcop0);
9966                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9967                                 pic16_emitpcode(POC_MOVLW, pcop1);
9968                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9969                                 pic16_emitpcode(POC_MOVLW, pcop2);
9970                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9971                         } else
9972                         if (size == 2) {
9973                                 pic16_emitpcode(POC_MOVLW, pcop0);
9974                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9975                                 pic16_emitpcode(POC_MOVLW, pcop1);
9976                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9977                         } else {
9978                                 pic16_emitpcode(POC_MOVLW, pcop0);
9979                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9980                         }
9981                 } else
9982 #endif
9983                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9984                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9985                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9986                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9987                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9988                         if(AOP_SIZE(result) <2)
9989                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9990                 } else {
9991                         /* if they in different places then copy */
9992                         size = AOP_SIZE(result);
9993                         offset = 0 ;
9994                         while (size--) {
9995                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9996                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9997                                 offset++;
9998                         }
9999                 }
10000                 goto release;
10001         }
10002
10003         /* if the result is of type pointer */
10004         if (IS_PTR(ctype)) {
10005           int p_type;
10006           sym_link *type = operandType(right);
10007           sym_link *etype = getSpec(type);
10008
10009                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10010
10011                 /* pointer to generic pointer */
10012                 if (IS_GENPTR(ctype)) {
10013                   char *l = zero;
10014             
10015                         if (IS_PTR(type)) 
10016                                 p_type = DCL_TYPE(type);
10017                         else {
10018                 /* we have to go by the storage class */
10019                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10020
10021 /*              if (SPEC_OCLS(etype)->codesp )  */
10022 /*                  p_type = CPOINTER ;  */
10023 /*              else */
10024 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10025 /*                      p_type = FPOINTER ; */
10026 /*                  else */
10027 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10028 /*                          p_type = PPOINTER; */
10029 /*                      else */
10030 /*                          if (SPEC_OCLS(etype) == idata ) */
10031 /*                              p_type = IPOINTER ; */
10032 /*                          else */
10033 /*                              p_type = POINTER ; */
10034             }
10035                 
10036             /* the first two bytes are known */
10037       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10038             size = GPTRSIZE - 1; 
10039             offset = 0 ;
10040             while (size--) {
10041               if(offset < AOP_SIZE(right)) {
10042       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10043                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10044                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10045                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10046                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10047                 } else { 
10048                   pic16_aopPut(AOP(result),
10049                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10050                          offset);
10051                 }
10052               } else 
10053                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10054               offset++;
10055             }
10056             /* the last byte depending on type */
10057             switch (p_type) {
10058             case IPOINTER:
10059             case POINTER:
10060                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10061                 break;
10062             case FPOINTER:
10063               pic16_emitcode(";BUG!? ","%d",__LINE__);
10064                 l = one;
10065                 break;
10066             case CPOINTER:
10067               pic16_emitcode(";BUG!? ","%d",__LINE__);
10068                 l = "#0x02";
10069                 break;                          
10070             case PPOINTER:
10071               pic16_emitcode(";BUG!? ","%d",__LINE__);
10072                 l = "#0x03";
10073                 break;
10074                 
10075             default:
10076                 /* this should never happen */
10077                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10078                        "got unknown pointer type");
10079                 exit(1);
10080             }
10081             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10082             goto release ;
10083         }
10084         
10085         /* just copy the pointers */
10086         size = AOP_SIZE(result);
10087         offset = 0 ;
10088         while (size--) {
10089             pic16_aopPut(AOP(result),
10090                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10091                    offset);
10092             offset++;
10093         }
10094         goto release ;
10095     }
10096     
10097
10098
10099     /* so we now know that the size of destination is greater
10100     than the size of the source.
10101     Now, if the next iCode is an operator then we might be
10102     able to optimize the operation without performing a cast.
10103     */
10104     if(genMixedOperation(ic))
10105       goto release;
10106
10107     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10108     
10109     /* we move to result for the size of source */
10110     size = AOP_SIZE(right);
10111     offset = 0 ;
10112     while (size--) {
10113       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10114       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10115       offset++;
10116     }
10117
10118     /* now depending on the sign of the destination */
10119     size = AOP_SIZE(result) - AOP_SIZE(right);
10120     /* if unsigned or not an integral type */
10121     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10122       while (size--)
10123         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10124     } else {
10125       /* we need to extend the sign :( */
10126
10127       if(size == 1) {
10128         /* Save one instruction of casting char to int */
10129         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10130         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10131         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10132       } else {
10133         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10134
10135         if(offset)
10136           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10137         else
10138           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10139         
10140         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10141
10142         while (size--)
10143           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10144       }
10145     }
10146
10147 release:
10148     pic16_freeAsmop(right,NULL,ic,TRUE);
10149     pic16_freeAsmop(result,NULL,ic,TRUE);
10150
10151 }
10152
10153 /*-----------------------------------------------------------------*/
10154 /* genDjnz - generate decrement & jump if not zero instrucion      */
10155 /*-----------------------------------------------------------------*/
10156 static int genDjnz (iCode *ic, iCode *ifx)
10157 {
10158     symbol *lbl, *lbl1;
10159     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10160
10161     if (!ifx)
10162         return 0;
10163     
10164     /* if the if condition has a false label
10165        then we cannot save */
10166     if (IC_FALSE(ifx))
10167         return 0;
10168
10169     /* if the minus is not of the form 
10170        a = a - 1 */
10171     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10172         !IS_OP_LITERAL(IC_RIGHT(ic)))
10173         return 0;
10174
10175     if (operandLitValue(IC_RIGHT(ic)) != 1)
10176         return 0;
10177
10178     /* if the size of this greater than one then no
10179        saving */
10180     if (getSize(operandType(IC_RESULT(ic))) > 1)
10181         return 0;
10182
10183     /* otherwise we can save BIG */
10184     lbl = newiTempLabel(NULL);
10185     lbl1= newiTempLabel(NULL);
10186
10187     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10188     
10189     if (IS_AOP_PREG(IC_RESULT(ic))) {
10190         pic16_emitcode("dec","%s",
10191                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10192         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10193         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10194     } else {    
10195
10196
10197       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10198       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10199
10200       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10201       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10202
10203     }
10204 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10205 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10206 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10207 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10208
10209     
10210     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10211     ifx->generated = 1;
10212     return 1;
10213 }
10214
10215 /*-----------------------------------------------------------------*/
10216 /* genReceive - generate code for a receive iCode                  */
10217 /*-----------------------------------------------------------------*/
10218 static void genReceive (iCode *ic)
10219 {    
10220         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10221
10222         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10223                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10224                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10225
10226           int size = getSize(operandType(IC_RESULT(ic)));
10227           int offset =  pic16_fReturnSizePic - size;
10228
10229                 while (size--) {
10230                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10231                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10232                         offset++;
10233                 }
10234
10235                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10236
10237                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10238                 size = AOP_SIZE(IC_RESULT(ic));
10239                 offset = 0;
10240                 while (size--) {
10241                         pic16_emitcode ("pop","acc");
10242                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10243                 }
10244         } else {
10245                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10246
10247                 _G.accInUse++;
10248                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10249                 _G.accInUse--;
10250                 assignResultValue(IC_RESULT(ic));       
10251         }
10252
10253         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10254 }
10255
10256 /*-----------------------------------------------------------------*/
10257 /* genDummyRead - generate code for dummy read of volatiles        */
10258 /*-----------------------------------------------------------------*/
10259 static void
10260 genDummyRead (iCode * ic)
10261 {
10262   pic16_emitcode ("; genDummyRead","");
10263   pic16_emitcode ("; not implemented","");
10264
10265   ic = ic;
10266 }
10267
10268 /*-----------------------------------------------------------------*/
10269 /* genpic16Code - generate code for pic16 based controllers        */
10270 /*-----------------------------------------------------------------*/
10271 /*
10272  * At this point, ralloc.c has gone through the iCode and attempted
10273  * to optimize in a way suitable for a PIC. Now we've got to generate
10274  * PIC instructions that correspond to the iCode.
10275  *
10276  * Once the instructions are generated, we'll pass through both the
10277  * peep hole optimizer and the pCode optimizer.
10278  *-----------------------------------------------------------------*/
10279
10280 void genpic16Code (iCode *lic)
10281 {
10282     iCode *ic;
10283     int cln = 0;
10284
10285     lineHead = lineCurr = NULL;
10286
10287     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10288     pic16_addpBlock(pb);
10289
10290 #if 0
10291     /* if debug information required */
10292     if (options.debug && currFunc) {
10293       if (currFunc) {
10294         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10295         _G.debugLine = 1;
10296         if (IS_STATIC(currFunc->etype)) {
10297           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10298           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10299         } else {
10300           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10301           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10302         }
10303         _G.debugLine = 0;
10304       }
10305     }
10306 #endif
10307
10308 //    dumpiCode(lic);
10309
10310     for (ic = lic ; ic ; ic = ic->next ) {
10311
10312 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10313 //      DEBUGpic16_emitcode("; VR", "");
10314       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10315         if ( cln != ic->lineno ) {
10316             if ( options.debug ) {
10317                 _G.debugLine = 1;
10318                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10319                          FileBaseName(ic->filename),ic->lineno,
10320                          ic->level,ic->block);
10321                 _G.debugLine = 0;
10322             }
10323             
10324             if(!options.noCcodeInAsm) {
10325                 pic16_addpCode2pBlock(pb,
10326                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10327                                 printCLine(ic->filename, ic->lineno)));
10328             }
10329
10330             cln = ic->lineno ;
10331         }
10332         
10333         if(options.iCodeInAsm) {
10334                 /* insert here code to print iCode as comment */
10335         }
10336         
10337         /* if the result is marked as
10338            spilt and rematerializable or code for
10339            this has already been generated then
10340            do nothing */
10341         if (resultRemat(ic) || ic->generated ) 
10342             continue ;
10343         
10344         /* depending on the operation */
10345         switch (ic->op) {
10346         case '!' :
10347             pic16_genNot(ic);
10348             break;
10349             
10350         case '~' :
10351             pic16_genCpl(ic);
10352             break;
10353             
10354         case UNARYMINUS:
10355             genUminus (ic);
10356             break;
10357             
10358         case IPUSH:
10359             genIpush (ic);
10360             break;
10361             
10362         case IPOP:
10363             /* IPOP happens only when trying to restore a 
10364                spilt live range, if there is an ifx statement
10365                following this pop then the if statement might
10366                be using some of the registers being popped which
10367                would destroy the contents of the register so
10368                we need to check for this condition and handle it */
10369             if (ic->next            && 
10370                 ic->next->op == IFX &&
10371                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10372                 genIfx (ic->next,ic);
10373             else
10374                 genIpop (ic);
10375             break; 
10376             
10377         case CALL:
10378             genCall (ic);
10379             break;
10380             
10381         case PCALL:
10382             genPcall (ic);
10383             break;
10384             
10385         case FUNCTION:
10386             genFunction (ic);
10387             break;
10388             
10389         case ENDFUNCTION:
10390             genEndFunction (ic);
10391             break;
10392             
10393         case RETURN:
10394             genRet (ic);
10395             break;
10396             
10397         case LABEL:
10398             genLabel (ic);
10399             break;
10400             
10401         case GOTO:
10402             genGoto (ic);
10403             break;
10404             
10405         case '+' :
10406             pic16_genPlus (ic) ;
10407             break;
10408             
10409         case '-' :
10410             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10411                 pic16_genMinus (ic);
10412             break;
10413             
10414         case '*' :
10415             genMult (ic);
10416             break;
10417             
10418         case '/' :
10419             genDiv (ic) ;
10420             break;
10421             
10422         case '%' :
10423             genMod (ic);
10424             break;
10425             
10426         case '>' :
10427             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10428             break;
10429             
10430         case '<' :
10431             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10432             break;
10433             
10434         case LE_OP:
10435         case GE_OP:
10436         case NE_OP:
10437             
10438             /* note these two are xlated by algebraic equivalence
10439                during parsing SDCC.y */
10440             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10441                    "got '>=' or '<=' shouldn't have come here");
10442             break;      
10443             
10444         case EQ_OP:
10445             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10446             break;          
10447             
10448         case AND_OP:
10449             genAndOp (ic);
10450             break;
10451             
10452         case OR_OP:
10453             genOrOp (ic);
10454             break;
10455             
10456         case '^' :
10457             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10458             break;
10459             
10460         case '|' :
10461                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10462             break;
10463             
10464         case BITWISEAND:
10465             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10466             break;
10467             
10468         case INLINEASM:
10469             genInline (ic);
10470             break;
10471             
10472         case RRC:
10473             genRRC (ic);
10474             break;
10475             
10476         case RLC:
10477             genRLC (ic);
10478             break;
10479             
10480         case GETHBIT:
10481             genGetHbit (ic);
10482             break;
10483             
10484         case LEFT_OP:
10485             genLeftShift (ic);
10486             break;
10487             
10488         case RIGHT_OP:
10489             genRightShift (ic);
10490             break;
10491             
10492         case GET_VALUE_AT_ADDRESS:
10493             genPointerGet(ic);
10494             break;
10495             
10496         case '=' :
10497             if (POINTER_SET(ic))
10498                 genPointerSet(ic);
10499             else
10500                 genAssign(ic);
10501             break;
10502             
10503         case IFX:
10504             genIfx (ic,NULL);
10505             break;
10506             
10507         case ADDRESS_OF:
10508             genAddrOf (ic);
10509             break;
10510             
10511         case JUMPTABLE:
10512             genJumpTab (ic);
10513             break;
10514             
10515         case CAST:
10516             genCast (ic);
10517             break;
10518             
10519         case RECEIVE:
10520             genReceive(ic);
10521             break;
10522             
10523         case SEND:
10524             addSet(&_G.sendSet,ic);
10525             break;
10526
10527         case DUMMY_READ_VOLATILE:
10528           genDummyRead (ic);
10529           break;
10530
10531         default :
10532             ic = ic;
10533         }
10534     }
10535
10536
10537     /* now we are ready to call the
10538        peep hole optimizer */
10539     if (!options.nopeep) {
10540       peepHole (&lineHead);
10541     }
10542     /* now do the actual printing */
10543     printLine (lineHead,codeOutFile);
10544
10545 #ifdef PCODE_DEBUG
10546     DFPRINTF((stderr,"printing pBlock\n\n"));
10547     pic16_printpBlock(stdout,pb);
10548 #endif
10549
10550     return;
10551 }
10552