* device/lib/Makefile.in: fixed bug in target objects-pic16,
[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              -  Vangelis Rokas vrokas@otenet.gr (2003)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
62
63 int pic16_labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
66 /*
67   hack hack
68
69 */
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic16aopLiteral (value *val, int offset);
80 const char *pic16_AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
82
83 void pic16_pushpCodeOp(pCodeOp *pcop);
84 void pic16_poppCodeOp(pCodeOp *pcop);
85
86 static bool is_LitOp(operand *op);
87 static bool is_LitAOp(asmop *aop);
88
89
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
91
92 /* this is the down and dirty file with all kinds of 
93    kludgy & hacky stuff. This is what it is all about
94    CODE GENERATION for a specific MCU . some of the
95    routines may be reusable, will have to see */
96
97 static char *zero = "#0x00";
98 static char *one  = "#0x01";
99 static char *spname = "sp";
100
101
102 /*
103  * Function return value policy (MSB-->LSB):
104  *  8 bits      -> WREG
105  * 16 bits      -> PRODL:WREG
106  * 24 bits      -> PRODH:PRODL:WREG
107  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
108  * >32 bits     -> on stack, and FSR0 points to the beginning
109  *
110  */
111  
112
113 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
114 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
115 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
116 static char **fReturn = fReturnpic16;
117
118 static char *accUse[] = {"WREG"};
119
120 //static short rbank = -1;
121
122 static struct {
123     short r0Pushed;
124     short r1Pushed;
125     short accInUse;
126     short inLine;
127     short debugLine;
128     short nRegsSaved;
129     set *sendSet;
130     int interruptvector;
131 } _G;
132
133 /* Resolved ifx structure. This structure stores information
134    about an iCode ifx that makes it easier to generate code.
135 */
136 typedef struct resolvedIfx {
137   symbol *lbl;     /* pointer to a label */
138   int condition;   /* true or false ifx */
139   int generated;   /* set true when the code associated with the ifx
140                     * is generated */
141 } resolvedIfx;
142
143 extern int pic16_ptrRegReq ;
144 extern int pic16_nRegs;
145 extern FILE *codeOutFile;
146 static void saverbank (int, iCode *,bool);
147
148 static lineNode *lineHead = NULL;
149 static lineNode *lineCurr = NULL;
150
151 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
152 0xE0, 0xC0, 0x80, 0x00};
153 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
154 0x07, 0x03, 0x01, 0x00};
155
156 static  pBlock *pb;
157
158 /*-----------------------------------------------------------------*/
159 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
160 /*                 exponent of 2 is returned, otherwise -1 is      */
161 /*                 returned.                                       */
162 /* note that this is similar to the function `powof2' in SDCCsymt  */
163 /* if(n == 2^y)                                                    */
164 /*   return y;                                                     */
165 /* return -1;                                                      */
166 /*-----------------------------------------------------------------*/
167 static int my_powof2 (unsigned long num)
168 {
169   if(num) {
170     if( (num & (num-1)) == 0) {
171       int nshifts = -1;
172       while(num) {
173         num>>=1;
174         nshifts++;
175       }
176       return nshifts;
177     }
178   }
179
180   return -1;
181 }
182
183 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
184 {
185   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
186                        line_no,
187                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
188                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
189                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
190                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
191                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
192                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
193                        ((result) ? AOP_SIZE(result) : 0));
194 }
195
196 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
197 {
198
199   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
200                        line_no,
201                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
202                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
203                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
204                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
205                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
206                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
207
208 }
209
210 void pic16_emitpcomment (char *fmt, ...)
211 {
212     va_list ap;
213     char lb[INITIAL_INLINEASM];  
214     char *lbp = lb;
215
216     va_start(ap,fmt);   
217
218     lb[0] = ';';
219     vsprintf(lb+1,fmt,ap);
220
221     while (isspace(*lbp)) lbp++;
222
223     if (lbp && *lbp) 
224         lineCurr = (lineCurr ?
225                     connectLine(lineCurr,newLineNode(lb)) :
226                     (lineHead = newLineNode(lb)));
227     lineCurr->isInline = _G.inLine;
228     lineCurr->isDebug  = _G.debugLine;
229
230     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
231     va_end(ap);
232
233 //      fprintf(stderr, "%s\n", lb);
234 }
235
236 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
237 {
238     va_list ap;
239     char lb[INITIAL_INLINEASM];  
240     char *lbp = lb;
241
242     if(!pic16_debug_verbose)
243       return;
244
245     va_start(ap,fmt);   
246
247     if (inst && *inst) {
248         if (fmt && *fmt)
249             sprintf(lb,"%s\t",inst);
250         else
251             sprintf(lb,"%s",inst);
252         vsprintf(lb+(strlen(lb)),fmt,ap);
253     }  else
254         vsprintf(lb,fmt,ap);
255
256     while (isspace(*lbp)) lbp++;
257
258     if (lbp && *lbp) 
259         lineCurr = (lineCurr ?
260                     connectLine(lineCurr,newLineNode(lb)) :
261                     (lineHead = newLineNode(lb)));
262     lineCurr->isInline = _G.inLine;
263     lineCurr->isDebug  = _G.debugLine;
264
265     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
266     va_end(ap);
267
268 //      fprintf(stderr, "%s\n", lb);
269 }
270
271 void pic16_emitpLabel(int key)
272 {
273   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
274 }
275
276 void pic16_emitpLabelFORCE(int key)
277 {
278   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
279 }
280
281 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
282 {
283
284   if(pcop)
285     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
286   else
287     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
288     
289 //    fprintf(stderr, "%s\n", pcop->name);
290 }
291
292 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
293 {
294
295   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
296
297 }
298
299
300 #if 1
301 #define pic16_emitcode  DEBUGpic16_emitcode
302 #else
303 /*-----------------------------------------------------------------*/
304 /* pic16_emitcode - writes the code into a file : for now it is simple    */
305 /*-----------------------------------------------------------------*/
306 void pic16_emitcode (char *inst,char *fmt, ...)
307 {
308     va_list ap;
309     char lb[INITIAL_INLINEASM];  
310     char *lbp = lb;
311
312     va_start(ap,fmt);   
313
314     if (inst && *inst) {
315         if (fmt && *fmt)
316             sprintf(lb,"%s\t",inst);
317         else
318             sprintf(lb,"%s",inst);
319         vsprintf(lb+(strlen(lb)),fmt,ap);
320     }  else
321         vsprintf(lb,fmt,ap);
322
323     while (isspace(*lbp)) lbp++;
324
325     if (lbp && *lbp) 
326         lineCurr = (lineCurr ?
327                     connectLine(lineCurr,newLineNode(lb)) :
328                     (lineHead = newLineNode(lb)));
329     lineCurr->isInline = _G.inLine;
330     lineCurr->isDebug  = _G.debugLine;
331
332 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
333
334 //    if(pic16_debug_verbose)
335 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
336
337     va_end(ap);
338 }
339 #endif
340
341
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitDebuggerSymbol - associate the current code location  */
344 /*   with a debugger symbol                                        */
345 /*-----------------------------------------------------------------*/
346 void
347 pic16_emitDebuggerSymbol (char * debugSym)
348 {
349   _G.debugLine = 1;
350   pic16_emitcode (";", "%s ==.", debugSym);
351   _G.debugLine = 0;
352 }
353
354
355 /*-----------------------------------------------------------------*/
356 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
357 /*-----------------------------------------------------------------*/
358 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
359 {
360     bool r0iu = FALSE , r1iu = FALSE;
361     bool r0ou = FALSE , r1ou = FALSE;
362
363         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
364
365     /* the logic: if r0 & r1 used in the instruction
366     then we are in trouble otherwise */
367
368     /* first check if r0 & r1 are used by this
369     instruction, in which case we are in trouble */
370     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
371         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
372     {
373         goto endOfWorld;      
374     }
375
376     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
377     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
378
379     /* if no usage of r0 then return it */
380     if (!r0iu && !r0ou) {
381         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
382         (*aopp)->type = AOP_R0;
383         
384         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
385     }
386
387     /* if no usage of r1 then return it */
388     if (!r1iu && !r1ou) {
389         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
390         (*aopp)->type = AOP_R1;
391
392         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
393     }    
394
395     /* now we know they both have usage */
396     /* if r0 not used in this instruction */
397     if (!r0iu) {
398         /* push it if not already pushed */
399         if (!_G.r0Pushed) {
400           //pic16_emitcode ("push","%s",
401           //          pic16_regWithIdx(R0_IDX)->dname);
402             _G.r0Pushed++ ;
403         }
404         
405         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
406         (*aopp)->type = AOP_R0;
407
408         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
409     }
410
411     /* if r1 not used then */
412
413     if (!r1iu) {
414         /* push it if not already pushed */
415         if (!_G.r1Pushed) {
416           //pic16_emitcode ("push","%s",
417           //          pic16_regWithIdx(R1_IDX)->dname);
418             _G.r1Pushed++ ;
419         }
420         
421         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
422         (*aopp)->type = AOP_R1;
423         return pic16_regWithIdx(R1_IDX);
424     }
425
426 endOfWorld :
427     /* I said end of world but not quite end of world yet */
428     /* if this is a result then we can push it on the stack*/
429     if (result) {
430         (*aopp)->type = AOP_STK;    
431         return NULL;
432     }
433
434     /* other wise this is true end of the world */
435     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
436            "getFreePtr should never reach here");
437     exit(0);
438 }
439
440 /*-----------------------------------------------------------------*/
441 /* newAsmop - creates a new asmOp                                  */
442 /*-----------------------------------------------------------------*/
443 static asmop *newAsmop (short type)
444 {
445     asmop *aop;
446
447     aop = Safe_calloc(1,sizeof(asmop));
448     aop->type = type;
449     return aop;
450 }
451
452 static void genSetDPTR(int n)
453 {
454     if (!n)
455     {
456         pic16_emitcode(";", "Select standard DPTR");
457         pic16_emitcode("mov", "dps, #0x00");
458     }
459     else
460     {
461         pic16_emitcode(";", "Select alternate DPTR");
462         pic16_emitcode("mov", "dps, #0x01");
463     }
464 }
465
466 /*-----------------------------------------------------------------*/
467 /* resolveIfx - converts an iCode ifx into a form more useful for  */
468 /*              generating code                                    */
469 /*-----------------------------------------------------------------*/
470 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
471 {
472
473   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
474
475   if(!resIfx) 
476     return;
477
478
479   resIfx->condition = 1;    /* assume that the ifx is true */
480   resIfx->generated = 0;    /* indicate that the ifx has not been used */
481
482   if(!ifx) {
483     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
484
485 #if 1
486     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
487                         __FUNCTION__,__LINE__,resIfx->lbl->key);
488 #endif
489
490   } else {
491     if(IC_TRUE(ifx)) {
492       resIfx->lbl = IC_TRUE(ifx);
493     } else {
494       resIfx->lbl = IC_FALSE(ifx);
495       resIfx->condition = 0;
496     }
497
498 #if 1
499     if(IC_TRUE(ifx)) 
500       DEBUGpic16_emitcode("; ***","ifx true is non-null");
501     if(IC_FALSE(ifx)) 
502       DEBUGpic16_emitcode("; ***","ifx false is non-null");
503 #endif
504   }
505
506   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
507
508 }
509 #if 0
510 /*-----------------------------------------------------------------*/
511 /* pointerCode - returns the code for a pointer type               */
512 /*-----------------------------------------------------------------*/
513 static int pointerCode (sym_link *etype)
514 {
515
516     return PTR_TYPE(SPEC_OCLS(etype));
517
518 }
519 #endif
520
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol                                   */
523 /*-----------------------------------------------------------------*/
524 static asmop *aopForSym (iCode *ic, operand *op, bool result)
525 {
526     symbol *sym=OP_SYMBOL(op);
527     asmop *aop;
528     memmap *space= SPEC_OCLS(sym->etype);
529
530     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
531
532 //    sym = OP_SYMBOL(op);
533
534     /* if already has one */
535     if (sym->aop) {
536             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
537         return sym->aop;
538     }
539
540     /* if symbol was initially placed onStack then we must re-place it
541      * to direct memory, since pic16 does not have a specific stack */
542     if(sym->onStack) {
543 //      sym->onStack = 0;
544         SPEC_OCLS( sym->etype ) = data;
545         space = data;
546     }
547     
548
549 #if 1
550     /* assign depending on the storage class */
551     /* if it is on the stack or indirectly addressable */
552     /* space we need to assign either r0 or r1 to it   */    
553     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
554
555         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
556                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
557         
558         sym->aop = aop = newAsmop(0);
559         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
560         aop->size = getSize(sym->type);
561
562         /* now assign the address of the variable to 
563         the pointer register */
564         if (aop->type != AOP_STK) {
565
566             if (sym->onStack) {
567                     if ( _G.accInUse )
568                         pic16_emitcode("push","acc");
569
570                     pic16_emitcode("mov","a,_bp");
571                     pic16_emitcode("add","a,#0x%02x",
572                              ((sym->stack < 0) ?
573                               ((char)(sym->stack - _G.nRegsSaved )) :
574                               ((char)sym->stack)) & 0xff);
575                     pic16_emitcode("mov","%s,a",
576                              aop->aopu.aop_ptr->name);
577
578                     if ( _G.accInUse )
579                         pic16_emitcode("pop","acc");
580             } else
581                 pic16_emitcode("mov","%s,#%s",
582                          aop->aopu.aop_ptr->name,
583                          sym->rname);
584             aop->paged = space->paged;
585         } else
586             aop->aopu.aop_stk = sym->stack;
587         return aop;
588     }
589 #endif
590
591     if (sym->onStack && options.stack10bit)
592     {
593         /* It's on the 10 bit stack, which is located in
594          * far data space.
595          */
596          
597       //DEBUGpic16_emitcode(";","%d",__LINE__);
598
599         if ( _G.accInUse )
600                 pic16_emitcode("push","acc");
601
602         pic16_emitcode("mov","a,_bp");
603         pic16_emitcode("add","a,#0x%02x",
604                  ((sym->stack < 0) ?
605                    ((char)(sym->stack - _G.nRegsSaved )) :
606                    ((char)sym->stack)) & 0xff);
607         
608         genSetDPTR(1);
609         pic16_emitcode ("mov","dpx1,#0x40");
610         pic16_emitcode ("mov","dph1,#0x00");
611         pic16_emitcode ("mov","dpl1, a");
612         genSetDPTR(0);
613         
614         if ( _G.accInUse )
615             pic16_emitcode("pop","acc");
616             
617         sym->aop = aop = newAsmop(AOP_DPTR2);
618         aop->size = getSize(sym->type); 
619         return aop;
620     }
621
622     //DEBUGpic16_emitcode(";","%d",__LINE__);
623     /* if in bit space */
624     if (IN_BITSPACE(space)) {
625         sym->aop = aop = newAsmop (AOP_CRY);
626         aop->aopu.aop_dir = sym->rname ;
627         aop->size = getSize(sym->type);
628         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
629         return aop;
630     }
631     /* if it is in direct space */
632     if (IN_DIRSPACE(space)) {
633         sym->aop = aop = newAsmop (AOP_DIR);
634         aop->aopu.aop_dir = sym->rname ;
635         aop->size = getSize(sym->type);
636         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
637         pic16_allocDirReg( IC_LEFT(ic) );
638         return aop;
639     }
640
641 #if 0                                                                                           // patch 14
642     /* special case for a function */
643     if (IS_FUNC(sym->type)) {   
644         sym->aop = aop = newAsmop(AOP_IMMD);    
645         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
646         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
647         strcpy(aop->aopu.aop_immd,sym->rname);
648         aop->size = FPTRSIZE; 
649         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
650         return aop;
651     }
652 #endif                                                                                          // patch 14
653
654
655     /* only remaining is far space */
656     /* in which case DPTR gets the address */
657     sym->aop = aop = newAsmop(AOP_PCODE);
658
659 /* change the next if to 1 to revert to good old immediate code */
660         if(IN_CODESPACE(space)) {
661                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
662                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
663                 PCOI(aop->aopu.pcop)->index = 0;
664         } else {
665                 /* try to allocate via direct register */
666                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
667 //              aop->size = getSize( sym->type );
668         }
669
670         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
671                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
672
673 #if 0
674         if(!pic16_allocDirReg (IC_LEFT(ic)))
675                 return NULL;
676 #endif
677
678         if(IN_DIRSPACE( space ))
679                 aop->size = PTRSIZE;
680         else if(IN_CODESPACE( space ))
681                 aop->size = FPTRSIZE;
682         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
683         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
684         else {
685                 assert( 0 );
686         }
687
688     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
689
690     /* if it is in code space */
691     if (IN_CODESPACE(space))
692         aop->code = 1;
693
694     return aop;     
695 }
696
697 /*-----------------------------------------------------------------*/
698 /* aopForRemat - rematerialzes an object                           */
699 /*-----------------------------------------------------------------*/
700 static asmop *aopForRemat (operand *op) // x symbol *sym)
701 {
702   symbol *sym = OP_SYMBOL(op);
703   iCode *ic = NULL, *oldic;
704   asmop *aop = newAsmop(AOP_PCODE);
705   int val = 0;
706   int offset = 0;
707   int viaimmd=0;
708
709
710         ic = sym->rematiCode;
711
712         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
713         
714         if(IS_OP_POINTER(op)) {
715                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
716         }
717
718         for (;;) {
719                 oldic = ic;
720
721 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
722         
723                 if (ic->op == '+') {
724                         val += (int) operandLitValue(IC_RIGHT(ic));
725                 } else if (ic->op == '-') {
726                         val -= (int) operandLitValue(IC_RIGHT(ic));
727                 } else
728                         break;
729                 
730                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
731         }
732
733         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
734
735         if(!op->isaddr)viaimmd++; else viaimmd=0;
736                 
737 /* set the following if to 1 to revert to good old immediate code */
738         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
739                 || viaimmd) {
740
741                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
742
743                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
744
745 #if 0
746                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
747 #else
748                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
749 #endif
750
751                 PCOI(aop->aopu.pcop)->index = val;
752         } else {
753                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
754
755                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
756                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
757 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
758         }
759
760
761         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
762                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
763 #if 0
764                 val, IS_PTR_CONST(operandType(op)));
765 #else
766                 val, IS_CODEPTR(operandType(op)));
767 #endif
768
769 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
770
771         pic16_allocDirReg (IC_LEFT(ic));
772
773         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
774                 aop->code = 1;
775
776   return aop;        
777 }
778
779 static int aopIdx (asmop *aop, int offset)
780 {
781   if(!aop)
782     return -1;
783
784   if(aop->type !=  AOP_REG)
785     return -2;
786         
787   return aop->aopu.aop_reg[offset]->rIdx;
788
789 }
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common       */
792 /*-----------------------------------------------------------------*/
793 static bool regsInCommon (operand *op1, operand *op2)
794 {
795     symbol *sym1, *sym2;
796     int i;
797
798     /* if they have registers in common */
799     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
800         return FALSE ;
801
802     sym1 = OP_SYMBOL(op1);
803     sym2 = OP_SYMBOL(op2);
804
805     if (sym1->nRegs == 0 || sym2->nRegs == 0)
806         return FALSE ;
807
808     for (i = 0 ; i < sym1->nRegs ; i++) {
809         int j;
810         if (!sym1->regs[i])
811             continue ;
812
813         for (j = 0 ; j < sym2->nRegs ;j++ ) {
814             if (!sym2->regs[j])
815                 continue ;
816
817             if (sym2->regs[j] == sym1->regs[i])
818                 return TRUE ;
819         }
820     }
821
822     return FALSE ;
823 }
824
825 /*-----------------------------------------------------------------*/
826 /* operandsEqu - equivalent                                        */
827 /*-----------------------------------------------------------------*/
828 static bool operandsEqu ( operand *op1, operand *op2)
829 {
830     symbol *sym1, *sym2;
831
832     /* if they not symbols */
833     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
834         return FALSE;
835
836     sym1 = OP_SYMBOL(op1);
837     sym2 = OP_SYMBOL(op2);
838
839     /* if both are itemps & one is spilt
840        and the other is not then false */
841     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
842         sym1->isspilt != sym2->isspilt )
843         return FALSE ;
844
845     /* if they are the same */
846     if (sym1 == sym2)
847         return TRUE ;
848
849     if (sym1->rname[0] && sym2->rname[0]
850         && strcmp (sym1->rname, sym2->rname) == 0)
851         return TRUE;
852
853
854     /* if left is a tmp & right is not */
855     if (IS_ITEMP(op1)  && 
856         !IS_ITEMP(op2) &&
857         sym1->isspilt  &&
858         (sym1->usl.spillLoc == sym2))
859         return TRUE;
860
861     if (IS_ITEMP(op2)  && 
862         !IS_ITEMP(op1) &&
863         sym2->isspilt  &&
864         sym1->level > 0 &&
865         (sym2->usl.spillLoc == sym1))
866         return TRUE ;
867
868     return FALSE ;
869 }
870
871 /*-----------------------------------------------------------------*/
872 /* pic16_sameRegs - two asmops have the same registers                   */
873 /*-----------------------------------------------------------------*/
874 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
875 {
876     int i;
877
878     if (aop1 == aop2)
879         return TRUE ;
880
881     if (aop1->type != AOP_REG ||
882         aop2->type != AOP_REG )
883         return FALSE ;
884
885     if (aop1->size != aop2->size )
886         return FALSE ;
887
888     for (i = 0 ; i < aop1->size ; i++ )
889         if (aop1->aopu.aop_reg[i] !=
890             aop2->aopu.aop_reg[i] )
891             return FALSE ;
892
893     return TRUE ;
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* pic16_aopOp - allocates an asmop for an operand  :                    */
898 /*-----------------------------------------------------------------*/
899 void pic16_aopOp (operand *op, iCode *ic, bool result)
900 {
901     asmop *aop;
902     symbol *sym;
903     int i;
904
905     if (!op)
906         return ;
907
908 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
909
910     /* if this a literal */
911     if (IS_OP_LITERAL(op)) {
912         op->aop = aop = newAsmop(AOP_LIT);
913         aop->aopu.aop_lit = op->operand.valOperand;
914         aop->size = getSize(operandType(op));
915         return;
916     }
917
918     {
919       sym_link *type = operandType(op);
920 #if 0
921       if(IS_PTR_CONST(type))
922 #else
923       if(IS_CODEPTR(type))
924 #endif
925         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
926     }
927
928     /* if already has a asmop then continue */
929     if (op->aop)
930         return ;
931
932     /* if the underlying symbol has a aop */
933     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
934       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
935         op->aop = OP_SYMBOL(op)->aop;
936         return;
937     }
938
939     /* if this is a true symbol */
940     if (IS_TRUE_SYMOP(op)) {    
941         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
942       op->aop = aopForSym(ic, op, result);
943       return ;
944     }
945
946     /* this is a temporary : this has
947     only four choices :
948     a) register
949     b) spillocation
950     c) rematerialize 
951     d) conditional   
952     e) can be a return use only */
953
954     sym = OP_SYMBOL(op);
955
956         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
957     /* if the type is a conditional */
958     if (sym->regType == REG_CND) {
959         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
960         aop->size = 0;
961         return;
962     }
963
964     /* if it is spilt then two situations
965     a) is rematerialize 
966     b) has a spill location */
967     if (sym->isspilt || sym->nRegs == 0) {
968
969       DEBUGpic16_emitcode(";","%d",__LINE__);
970         /* rematerialize it NOW */
971         if (sym->remat) {
972
973             sym->aop = op->aop = aop =
974                                       aopForRemat (op);
975             aop->size = getSize(sym->type);
976             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
977             return;
978         }
979
980 #if 1
981         if (sym->accuse) {
982             int i;
983             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
984             aop->size = getSize(sym->type);
985             for ( i = 0 ; i < 1 ; i++ ) {
986                 aop->aopu.aop_str[i] = accUse[i];
987 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
988             }
989             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
990             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
991             return;  
992         }
993 #endif
994
995 #if 1
996         if (sym->ruonly ) {
997           /*
998           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
999           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1000           //pic16_allocDirReg (IC_LEFT(ic));
1001           aop->size = getSize(sym->type);
1002           */
1003
1004           unsigned i;
1005
1006           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1007           aop->size = getSize(sym->type);
1008           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1009             aop->aopu.aop_str[i] = fReturn[i];
1010
1011           DEBUGpic16_emitcode(";","%d",__LINE__);
1012           return;
1013         }
1014 #endif
1015         /* else spill location  */
1016         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1017             /* force a new aop if sizes differ */
1018             sym->usl.spillLoc->aop = NULL;
1019         }
1020         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1021                             __FUNCTION__,__LINE__,
1022                             sym->usl.spillLoc->rname,
1023                             sym->rname, sym->usl.spillLoc->offset);
1024
1025         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1026         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1027         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1028                                           getSize(sym->type), 
1029                                           sym->usl.spillLoc->offset, op);
1030         aop->size = getSize(sym->type);
1031
1032         return;
1033     }
1034
1035     {
1036       sym_link *type = operandType(op);
1037 #if 0
1038       if(IS_PTR_CONST(type)) 
1039 #else
1040       if(IS_CODEPTR(type)) 
1041 #endif
1042         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1043     }
1044
1045     /* must be in a register */
1046     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1047     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1048     aop->size = sym->nRegs;
1049     for ( i = 0 ; i < sym->nRegs ;i++)
1050         aop->aopu.aop_reg[i] = sym->regs[i];
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_freeAsmop - free up the asmop given to an operand               */
1055 /*----------------------------------------------------------------*/
1056 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1057 {   
1058     asmop *aop ;
1059
1060     if (!op)
1061         aop = aaop;
1062     else 
1063         aop = op->aop;
1064
1065     if (!aop)
1066         return ;
1067
1068     if (aop->freed)
1069         goto dealloc; 
1070
1071     aop->freed = 1;
1072
1073     /* depending on the asmop type only three cases need work AOP_RO
1074        , AOP_R1 && AOP_STK */
1075 #if 0
1076     switch (aop->type) {
1077         case AOP_R0 :
1078             if (_G.r0Pushed ) {
1079                 if (pop) {
1080                     pic16_emitcode ("pop","ar0");     
1081                     _G.r0Pushed--;
1082                 }
1083             }
1084             bitVectUnSetBit(ic->rUsed,R0_IDX);
1085             break;
1086
1087         case AOP_R1 :
1088             if (_G.r1Pushed ) {
1089                 if (pop) {
1090                     pic16_emitcode ("pop","ar1");
1091                     _G.r1Pushed--;
1092                 }
1093             }
1094             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1095             break;
1096
1097         case AOP_STK :
1098         {
1099             int sz = aop->size;    
1100             int stk = aop->aopu.aop_stk + aop->size;
1101             bitVectUnSetBit(ic->rUsed,R0_IDX);
1102             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1103
1104             getFreePtr(ic,&aop,FALSE);
1105             
1106             if (options.stack10bit)
1107             {
1108                 /* I'm not sure what to do here yet... */
1109                 /* #STUB */
1110                 fprintf(stderr, 
1111                         "*** Warning: probably generating bad code for "
1112                         "10 bit stack mode.\n");
1113             }
1114             
1115             if (stk) {
1116                 pic16_emitcode ("mov","a,_bp");
1117                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1118                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1119             } else {
1120                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1121             }
1122
1123             while (sz--) {
1124                 pic16_emitcode("pop","acc");
1125                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1126                 if (!sz) break;
1127                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1128             }
1129             op->aop = aop;
1130             pic16_freeAsmop(op,NULL,ic,TRUE);
1131             if (_G.r0Pushed) {
1132                 pic16_emitcode("pop","ar0");
1133                 _G.r0Pushed--;
1134             }
1135
1136             if (_G.r1Pushed) {
1137                 pic16_emitcode("pop","ar1");
1138                 _G.r1Pushed--;
1139             }       
1140         }
1141     }
1142 #endif
1143
1144 dealloc:
1145     /* all other cases just dealloc */
1146     if (op ) {
1147         op->aop = NULL;
1148         if (IS_SYMOP(op)) {
1149             OP_SYMBOL(op)->aop = NULL;    
1150             /* if the symbol has a spill */
1151             if (SPIL_LOC(op))
1152                 SPIL_LOC(op)->aop = NULL;
1153         }
1154     }
1155 }
1156
1157 /*-----------------------------------------------------------------*/
1158 /* pic16_aopGet - for fetching value of the aop                          */
1159 /*-----------------------------------------------------------------*/
1160 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1161 {
1162     char *s = buffer ;
1163     char *rs;
1164
1165     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1166
1167     /* offset is greater than size then zero */
1168     if (offset > (aop->size - 1) &&
1169         aop->type != AOP_LIT)
1170         return zero;
1171
1172     /* depending on type */
1173     switch (aop->type) {
1174         
1175     case AOP_IMMD:
1176         if (bit16) 
1177             sprintf (s,"%s",aop->aopu.aop_immd);
1178         else
1179             if (offset) 
1180                 sprintf(s,"(%s >> %d)",
1181                         aop->aopu.aop_immd,
1182                         offset*8);
1183             else
1184                 sprintf(s,"%s",
1185                         aop->aopu.aop_immd);
1186         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1187         rs = Safe_calloc(1,strlen(s)+1);
1188         strcpy(rs,s);   
1189         return rs;
1190         
1191     case AOP_DIR:
1192       if (offset) {
1193         sprintf(s,"(%s + %d)",
1194                 aop->aopu.aop_dir,
1195                 offset);
1196         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1197       } else
1198             sprintf(s,"%s",aop->aopu.aop_dir);
1199         rs = Safe_calloc(1,strlen(s)+1);
1200         strcpy(rs,s);   
1201         return rs;
1202         
1203     case AOP_REG:
1204       //if (dname) 
1205       //    return aop->aopu.aop_reg[offset]->dname;
1206       //else
1207             return aop->aopu.aop_reg[offset]->name;
1208         
1209     case AOP_CRY:
1210       //pic16_emitcode(";","%d",__LINE__);
1211       return aop->aopu.aop_dir;
1212         
1213     case AOP_ACC:
1214         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1215 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1216 //        assert( 0 );
1217         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1218
1219     case AOP_LIT:
1220         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1221         rs = Safe_calloc(1,strlen(s)+1);
1222         strcpy(rs,s);   
1223         return rs;
1224         
1225     case AOP_STR:
1226         aop->coff = offset ;
1227         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1228             dname)
1229             return "acc";
1230         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1231         
1232         return aop->aopu.aop_str[offset];
1233         
1234     case AOP_PCODE:
1235       {
1236         pCodeOp *pcop = aop->aopu.pcop;
1237         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1238         if(pcop->name) {
1239           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1240           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1241           sprintf(s,"%s", pcop->name);
1242         } else
1243           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1244
1245       }
1246       rs = Safe_calloc(1,strlen(s)+1);
1247       strcpy(rs,s);   
1248       return rs;
1249
1250     }
1251
1252     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1253            "aopget got unsupported aop->type");
1254     exit(0);
1255 }
1256
1257
1258 /*-----------------------------------------------------------------*/
1259 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *pic16_popGetTempReg(void)
1262 {
1263   pCodeOp *pcop;
1264   symbol *cfunc;
1265
1266 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1267
1268         cfunc = currFunc;
1269         currFunc = NULL;
1270
1271         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1272         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1273                 PCOR(pcop)->r->wasUsed=1;
1274                 PCOR(pcop)->r->isFree=0;
1275
1276                 /* push value on stack */
1277                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1278         }
1279
1280         currFunc = cfunc;
1281
1282   return pcop;
1283 }
1284
1285 /*-----------------------------------------------------------------*/
1286 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1287 /*-----------------------------------------------------------------*/
1288 void pic16_popReleaseTempReg(pCodeOp *pcop)
1289 {
1290         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1291
1292         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1293                 PCOR(pcop)->r->isFree = 1;
1294                 
1295                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1296         }
1297 }
1298 /*-----------------------------------------------------------------*/
1299 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *pic16_popGetLabel(unsigned int key)
1302 {
1303
1304   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1305
1306   if(key>max_key)
1307     max_key = key;
1308
1309   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1310 }
1311
1312 /*-----------------------------------------------------------------*/
1313 /* pic16_popCopyReg - copy a pcode operator                              */
1314 /*-----------------------------------------------------------------*/
1315 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1316 {
1317   pCodeOpReg *pcor;
1318
1319   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1320   pcor->pcop.type = pc->pcop.type;
1321   if(pc->pcop.name) {
1322     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1323       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1324   } else
1325     pcor->pcop.name = NULL;
1326
1327   pcor->r = pc->r;
1328   pcor->rIdx = pc->rIdx;
1329   pcor->r->wasUsed=1;
1330
1331 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1332
1333   return PCOP(pcor);
1334 }
1335
1336 /*-----------------------------------------------------------------*/
1337 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1338 /*-----------------------------------------------------------------*/
1339 pCodeOp *pic16_popGetLit(unsigned int lit)
1340 {
1341   return pic16_newpCodeOpLit(lit);
1342 }
1343
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1346 /*-----------------------------------------------------------------*/
1347 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1348 {
1349   return pic16_newpCodeOpLit2(lit, arg2);
1350 }
1351
1352
1353 /*-----------------------------------------------------------------*/
1354 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1357 {
1358   return pic16_newpCodeOpImmd(name, offset,index, 0);
1359 }
1360
1361
1362 /*-----------------------------------------------------------------*/
1363 /* pic16_popGet - asm operator to pcode operator conversion              */
1364 /*-----------------------------------------------------------------*/
1365 pCodeOp *pic16_popGetWithString(char *str)
1366 {
1367   pCodeOp *pcop;
1368
1369
1370   if(!str) {
1371     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1372     exit (1);
1373   }
1374
1375   pcop = pic16_newpCodeOp(str,PO_STR);
1376
1377   return pcop;
1378 }
1379
1380 /*-----------------------------------------------------------------*/
1381 /* pic16_popRegFromString -                                        */
1382 /*-----------------------------------------------------------------*/
1383 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1384 {
1385
1386   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1387   pcop->type = PO_DIR;
1388
1389   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1390   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1391
1392   if(!str)
1393     str = "BAD_STRING";
1394
1395   pcop->name = Safe_calloc(1,strlen(str)+1);
1396   strcpy(pcop->name,str);
1397
1398   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1399
1400   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1401   if(PCOR(pcop)->r == NULL) {
1402 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1403 //              __FUNCTION__, __LINE__, str, size, offset);
1404     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1405
1406         //fprintf(stderr, "allocating new register -> %s\n", str);
1407
1408 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1409   } else {
1410 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1411   }
1412   PCOR(pcop)->instance = offset;
1413
1414   return pcop;
1415 }
1416
1417 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1418 {
1419   pCodeOp *pcop;
1420
1421 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1422
1423         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1424         PCOR(pcop)->rIdx = rIdx;
1425         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1426         PCOR(pcop)->r->isFree = 0;
1427         PCOR(pcop)->r->wasUsed = 1;
1428
1429         pcop->type = PCOR(pcop)->r->pc_type;
1430
1431   return pcop;
1432 }
1433
1434 /*---------------------------------------------------------------------------------*/
1435 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1436 /*                 VR 030601                                                       */
1437 /*---------------------------------------------------------------------------------*/
1438 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1439 {
1440   pCodeOpReg2 *pcop2;
1441   pCodeOp *temp;
1442   
1443         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1444
1445         /* comment the following check, so errors to throw up */
1446 //      if(!pcop2)return NULL;
1447
1448         temp = pic16_popGet(aop_dst, offset);
1449         pcop2->pcop2 = temp;
1450         
1451   return PCOP(pcop2);
1452 }
1453
1454
1455
1456 /*--------------------------------------------------------------------------------.-*/
1457 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1458 /*                  VR 030601 , adapted by Hans Dorn                                */
1459 /*--------------------------------------------------------------------------------.-*/
1460 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1461 {
1462   pCodeOpReg2 *pcop2;
1463  
1464         pcop2 = (pCodeOpReg2 *)src;
1465         pcop2->pcop2 = dst;
1466         
1467         return PCOP(pcop2);
1468 }
1469
1470
1471
1472 /*---------------------------------------------------------------------------------*/
1473 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1474 /*                     movff instruction                                           */
1475 /*---------------------------------------------------------------------------------*/
1476 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1477 {
1478   pCodeOpReg2 *pcop2;
1479
1480         if(!noalloc) {
1481                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1482                 pcop2->pcop2 = pic16_popCopyReg(dst);
1483         } else {
1484                 /* the pCodeOp may be already allocated */
1485                 pcop2 = (pCodeOpReg2 *)(src);
1486                 pcop2->pcop2 = (pCodeOp *)(dst);
1487         }
1488
1489   return PCOP(pcop2);
1490 }
1491
1492
1493 /*-----------------------------------------------------------------*/
1494 /* pic16_popGet - asm operator to pcode operator conversion              */
1495 /*-----------------------------------------------------------------*/
1496 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1497 {
1498   //char *s = buffer ;
1499   char *rs;
1500   pCodeOp *pcop;
1501
1502     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1503     /* offset is greater than
1504     size then zero */
1505
1506 //    if (offset > (aop->size - 1) &&
1507 //        aop->type != AOP_LIT)
1508 //      return NULL;  //zero;
1509
1510     /* depending on type */
1511     switch (aop->type) {
1512         
1513     case AOP_R0:
1514     case AOP_R1:
1515     case AOP_DPTR:
1516     case AOP_DPTR2:
1517         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1518         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1519         assert( 0 );
1520         return NULL;
1521
1522
1523
1524     case AOP_IMMD:
1525       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1526       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1527
1528     case AOP_ACC:
1529       {
1530         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1531
1532         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1533
1534         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1535         
1536         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1537         PCOR(pcop)->rIdx = rIdx;
1538         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1539         PCOR(pcop)->r->wasUsed=1;
1540         PCOR(pcop)->r->isFree=0;
1541
1542         PCOR(pcop)->instance = offset;
1543         pcop->type = PCOR(pcop)->r->pc_type;
1544 //      rs = aop->aopu.aop_reg[offset]->name;
1545 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1546         return pcop;
1547
1548
1549 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1550 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1551
1552 //      assert( 0 );
1553       }
1554         
1555     case AOP_DIR:
1556       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1557       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1558         
1559     case AOP_REG:
1560       {
1561         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1562
1563         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1564         
1565         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1566         PCOR(pcop)->rIdx = rIdx;
1567         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1568         PCOR(pcop)->r->wasUsed=1;
1569         PCOR(pcop)->r->isFree=0;
1570
1571         PCOR(pcop)->instance = offset;
1572         pcop->type = PCOR(pcop)->r->pc_type;
1573         rs = aop->aopu.aop_reg[offset]->name;
1574         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1575         return pcop;
1576       }
1577
1578     case AOP_CRY:
1579         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1580
1581       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1582       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1583       //if(PCOR(pcop)->r == NULL)
1584       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1585       return pcop;
1586         
1587     case AOP_LIT:
1588         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1589       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1590
1591     case AOP_STR:
1592       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1593       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1594
1595       /*
1596       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1597       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1598       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1599       pcop->type = PCOR(pcop)->r->pc_type;
1600       pcop->name = PCOR(pcop)->r->name;
1601
1602       return pcop;
1603       */
1604
1605     case AOP_PCODE:
1606       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1607                           __LINE__, 
1608                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1609       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1610 #if 1
1611         switch( aop->aopu.pcop->type ) {
1612                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1613                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1614                 default:
1615                         assert( 0 );    /* should never reach here */;
1616         }
1617 #else
1618       PCOI(pcop)->offset = offset;
1619 #endif
1620       return pcop;
1621     }
1622
1623     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1624            "pic16_popGet got unsupported aop->type");
1625     exit(0);
1626 }
1627 /*-----------------------------------------------------------------*/
1628 /* pic16_aopPut - puts a string for a aop                                */
1629 /*-----------------------------------------------------------------*/
1630 void pic16_aopPut (asmop *aop, char *s, int offset)
1631 {
1632     char *d = buffer ;
1633     symbol *lbl ;
1634
1635     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1636
1637     if (aop->size && offset > ( aop->size - 1)) {
1638         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1639                "pic16_aopPut got offset > aop->size");
1640         exit(0);
1641     }
1642
1643     /* will assign value to value */
1644     /* depending on where it is ofcourse */
1645     switch (aop->type) {
1646     case AOP_DIR:
1647       if (offset) {
1648         sprintf(d,"(%s + %d)",
1649                 aop->aopu.aop_dir,offset);
1650         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1651
1652       } else
1653             sprintf(d,"%s",aop->aopu.aop_dir);
1654         
1655         if (strcmp(d,s)) {
1656           DEBUGpic16_emitcode(";","%d",__LINE__);
1657           if(strcmp(s,"W"))
1658             pic16_emitcode("movf","%s,w",s);
1659           pic16_emitcode("movwf","%s",d);
1660
1661           if(strcmp(s,"W")) {
1662             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1663             if(offset >= aop->size) {
1664               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1665               break;
1666             } else
1667               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1668           }
1669
1670           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1671
1672
1673         }
1674         break;
1675         
1676     case AOP_REG:
1677       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1678         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1679           /*
1680             if (*s == '@'           ||
1681                 strcmp(s,"r0") == 0 ||
1682                 strcmp(s,"r1") == 0 ||
1683                 strcmp(s,"r2") == 0 ||
1684                 strcmp(s,"r3") == 0 ||
1685                 strcmp(s,"r4") == 0 ||
1686                 strcmp(s,"r5") == 0 ||
1687                 strcmp(s,"r6") == 0 || 
1688                 strcmp(s,"r7") == 0 )
1689                 pic16_emitcode("mov","%s,%s  ; %d",
1690                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1691             else
1692           */
1693
1694           if(strcmp(s,"W")==0 )
1695             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1696
1697           pic16_emitcode("movwf","%s",
1698                    aop->aopu.aop_reg[offset]->name);
1699
1700           if(strcmp(s,zero)==0) {
1701             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1702
1703           } else if(strcmp(s,"W")==0) {
1704             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1705             pcop->type = PO_GPR_REGISTER;
1706
1707             PCOR(pcop)->rIdx = -1;
1708             PCOR(pcop)->r = NULL;
1709
1710             DEBUGpic16_emitcode(";","%d",__LINE__);
1711             pcop->name = Safe_strdup(s);
1712             pic16_emitpcode(POC_MOVFW,pcop);
1713             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1714           } else if(strcmp(s,one)==0) {
1715             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1716             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1717           } else {
1718             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1719           }
1720         }
1721         break;
1722         
1723     case AOP_DPTR:
1724     case AOP_DPTR2:
1725     
1726     if (aop->type == AOP_DPTR2)
1727     {
1728         genSetDPTR(1);
1729     }
1730     
1731         if (aop->code) {
1732             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1733                    "pic16_aopPut writting to code space");
1734             exit(0);
1735         }
1736         
1737         while (offset > aop->coff) {
1738             aop->coff++;
1739             pic16_emitcode ("inc","dptr");
1740         }
1741         
1742         while (offset < aop->coff) {
1743             aop->coff-- ;
1744             pic16_emitcode("lcall","__decdptr");
1745         }
1746         
1747         aop->coff = offset;
1748         
1749         /* if not in accumulater */
1750         MOVA(s);        
1751         
1752         pic16_emitcode ("movx","@dptr,a");
1753         
1754     if (aop->type == AOP_DPTR2)
1755     {
1756         genSetDPTR(0);
1757     }
1758         break;
1759         
1760     case AOP_R0:
1761     case AOP_R1:
1762         while (offset > aop->coff) {
1763             aop->coff++;
1764             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1765         }
1766         while (offset < aop->coff) {
1767             aop->coff-- ;
1768             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1769         }
1770         aop->coff = offset;
1771         
1772         if (aop->paged) {
1773             MOVA(s);           
1774             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1775             
1776         } else
1777             if (*s == '@') {
1778                 MOVA(s);
1779                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1780             } else
1781                 if (strcmp(s,"r0") == 0 ||
1782                     strcmp(s,"r1") == 0 ||
1783                     strcmp(s,"r2") == 0 ||
1784                     strcmp(s,"r3") == 0 ||
1785                     strcmp(s,"r4") == 0 ||
1786                     strcmp(s,"r5") == 0 ||
1787                     strcmp(s,"r6") == 0 || 
1788                     strcmp(s,"r7") == 0 ) {
1789                     char buffer[10];
1790                     sprintf(buffer,"a%s",s);
1791                     pic16_emitcode("mov","@%s,%s",
1792                              aop->aopu.aop_ptr->name,buffer);
1793                 } else
1794                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1795         
1796         break;
1797         
1798     case AOP_STK:
1799         if (strcmp(s,"a") == 0)
1800             pic16_emitcode("push","acc");
1801         else
1802             pic16_emitcode("push","%s",s);
1803         
1804         break;
1805         
1806     case AOP_CRY:
1807         /* if bit variable */
1808         if (!aop->aopu.aop_dir) {
1809             pic16_emitcode("clr","a");
1810             pic16_emitcode("rlc","a");
1811         } else {
1812             if (s == zero) 
1813                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1814             else
1815                 if (s == one)
1816                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1817                 else
1818                     if (!strcmp(s,"c"))
1819                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1820                     else {
1821                         lbl = newiTempLabel(NULL);
1822                         
1823                         if (strcmp(s,"a")) {
1824                             MOVA(s);
1825                         }
1826                         pic16_emitcode("clr","c");
1827                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1828                         pic16_emitcode("cpl","c");
1829                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1830                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1831                     }
1832         }
1833         break;
1834         
1835     case AOP_STR:
1836         aop->coff = offset;
1837         if (strcmp(aop->aopu.aop_str[offset],s))
1838             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1839         break;
1840         
1841     case AOP_ACC:
1842         aop->coff = offset;
1843         if (!offset && (strcmp(s,"acc") == 0))
1844             break;
1845         
1846         if (strcmp(aop->aopu.aop_str[offset],s))
1847             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1848         break;
1849
1850     default :
1851         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1852                "pic16_aopPut got unsupported aop->type");
1853         exit(0);    
1854     }    
1855
1856 }
1857
1858 /*-----------------------------------------------------------------*/
1859 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1860 /*-----------------------------------------------------------------*/
1861 static void mov2w (asmop *aop, int offset)
1862 {
1863
1864 //  if(!aop)
1865 //    return;
1866
1867         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1868
1869         if(is_LitAOp(aop))
1870                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1871         else
1872                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1873
1874 }
1875
1876
1877 /* push pcop into stack */
1878 void pic16_pushpCodeOp(pCodeOp *pcop)
1879 {
1880 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1881         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1882 }
1883
1884 /* pop pcop from stack */
1885 void pic16_poppCodeOp(pCodeOp *pcop)
1886 {
1887         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1888 }
1889
1890
1891 /*-----------------------------------------------------------------*/
1892 /* pushw - pushes wreg to stack                                    */
1893 /*-----------------------------------------------------------------*/
1894 void pushw(void)
1895 {
1896         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1897         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1898 }
1899
1900                 
1901 /*-----------------------------------------------------------------*/
1902 /* pushaop - pushes aop to stack                                   */
1903 /*-----------------------------------------------------------------*/
1904 void pushaop(asmop *aop, int offset)
1905 {
1906         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1907         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1908 }
1909
1910 /*-----------------------------------------------------------------*/
1911 /* popaop - pops aop from stack                                    */
1912 /*-----------------------------------------------------------------*/
1913 void popaop(asmop *aop, int offset)
1914 {
1915         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1916         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1917 }
1918
1919 void popaopidx(asmop *aop, int offset, int index)
1920 {
1921   int ofs=1;
1922
1923         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1924
1925         if(STACK_MODEL_LARGE)ofs++;
1926
1927         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1928         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1929 }
1930
1931 /*-----------------------------------------------------------------*/
1932 /* reAdjustPreg - points a register back to where it should        */
1933 /*-----------------------------------------------------------------*/
1934 static void reAdjustPreg (asmop *aop)
1935 {
1936     int size ;
1937
1938     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1939     aop->coff = 0;
1940     if ((size = aop->size) <= 1)
1941         return ;
1942     size-- ;
1943     switch (aop->type) {
1944         case AOP_R0 :
1945         case AOP_R1 :
1946             while (size--)
1947                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1948             break;          
1949         case AOP_DPTR :
1950         case AOP_DPTR2:
1951             if (aop->type == AOP_DPTR2)
1952             {
1953                 genSetDPTR(1);
1954             } 
1955             while (size--)
1956             {
1957                 pic16_emitcode("lcall","__decdptr");
1958             }
1959                 
1960             if (aop->type == AOP_DPTR2)
1961             {
1962                 genSetDPTR(0);
1963             }                
1964             break;  
1965
1966     }   
1967
1968 }
1969
1970
1971 #if 0
1972 /*-----------------------------------------------------------------*/
1973 /* opIsGptr: returns non-zero if the passed operand is             */   
1974 /* a generic pointer type.                                         */
1975 /*-----------------------------------------------------------------*/ 
1976 static int opIsGptr(operand *op)
1977 {
1978     sym_link *type = operandType(op);
1979     
1980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1981     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1982     {
1983         return 1;
1984     }
1985     return 0;        
1986 }
1987 #endif
1988
1989 /*-----------------------------------------------------------------*/
1990 /* pic16_getDataSize - get the operand data size                         */
1991 /*-----------------------------------------------------------------*/
1992 int pic16_getDataSize(operand *op)
1993 {
1994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1995
1996
1997     return AOP_SIZE(op);
1998
1999     // tsd- in the pic port, the genptr size is 1, so this code here
2000     // fails. ( in the 8051 port, the size was 4).
2001 #if 0
2002     int size;
2003     size = AOP_SIZE(op);
2004     if (size == GPTRSIZE)
2005     {
2006         sym_link *type = operandType(op);
2007         if (IS_GENPTR(type))
2008         {
2009             /* generic pointer; arithmetic operations
2010              * should ignore the high byte (pointer type).
2011              */
2012             size--;
2013     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2014         }
2015     }
2016     return size;
2017 #endif
2018 }
2019
2020 /*-----------------------------------------------------------------*/
2021 /* pic16_outAcc - output Acc                                             */
2022 /*-----------------------------------------------------------------*/
2023 void pic16_outAcc(operand *result)
2024 {
2025   int size,offset;
2026   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2027   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2028
2029
2030   size = pic16_getDataSize(result);
2031   if(size){
2032     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2033     size--;
2034     offset = 1;
2035     /* unsigned or positive */
2036     while(size--)
2037       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2038   }
2039
2040 }
2041
2042 /*-----------------------------------------------------------------*/
2043 /* pic16_outBitC - output a bit C                                  */
2044 /*                 Move to result the value of Carry flag -- VR    */
2045 /*-----------------------------------------------------------------*/
2046 void pic16_outBitC(operand *result)
2047 {
2048   int i;
2049
2050     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2051     /* if the result is bit */
2052     if (AOP_TYPE(result) == AOP_CRY) {
2053         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2054         pic16_aopPut(AOP(result),"c",0);
2055     } else {
2056
2057         i = AOP_SIZE(result);
2058         while(i--) {
2059                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2060         }
2061         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2062         
2063 /*
2064         pic16_emitcode("clr","a  ; %d", __LINE__);
2065         pic16_emitcode("rlc","a");
2066         pic16_outAcc(result);
2067 */
2068     }
2069 }
2070
2071 /*-----------------------------------------------------------------*/
2072 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2073 /*-----------------------------------------------------------------*/
2074 void pic16_toBoolean(operand *oper)
2075 {
2076     int size = AOP_SIZE(oper) - 1;
2077     int offset = 1;
2078
2079     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2080
2081     if ( AOP_TYPE(oper) != AOP_ACC) {
2082       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2083     }
2084     while (size--) {
2085       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2086     }
2087 }
2088
2089
2090 #if !defined(GEN_Not)
2091 /*-----------------------------------------------------------------*/
2092 /* genNot - generate code for ! operation                          */
2093 /*-----------------------------------------------------------------*/
2094 static void pic16_genNot (iCode *ic)
2095 {
2096   symbol *tlbl;
2097   int size;
2098
2099   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2100   /* assign asmOps to operand & result */
2101   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2102   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2103
2104   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2105   /* if in bit space then a special case */
2106   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2107     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2108       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2109       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2110     } else {
2111       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2112       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2113       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2114     }
2115     goto release;
2116   }
2117
2118   size = AOP_SIZE(IC_LEFT(ic));
2119   if(size == 1) {
2120     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2121     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2122     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2123     goto release;
2124   }
2125   pic16_toBoolean(IC_LEFT(ic));
2126
2127   tlbl = newiTempLabel(NULL);
2128   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2129   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2130   pic16_outBitC(IC_RESULT(ic));
2131
2132  release:    
2133   /* release the aops */
2134   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2135   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2136 }
2137 #endif
2138
2139
2140 #if !defined(GEN_Cpl)
2141 /*-----------------------------------------------------------------*/
2142 /* genCpl - generate code for complement                           */
2143 /*-----------------------------------------------------------------*/
2144 static void pic16_genCpl (iCode *ic)
2145 {
2146     int offset = 0;
2147     int size ;
2148
2149
2150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2151     /* assign asmOps to operand & result */
2152     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2153     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2154
2155     /* if both are in bit space then 
2156     a special case */
2157     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2158         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2159
2160         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2161         pic16_emitcode("cpl","c"); 
2162         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2163         goto release; 
2164     } 
2165
2166     size = AOP_SIZE(IC_RESULT(ic));
2167     while (size--) {
2168 /*
2169         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2170         MOVA(l);       
2171         pic16_emitcode("cpl","a");
2172         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2173 */
2174         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2175               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2176         } else {
2177                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2178                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2179         }
2180         offset++;
2181
2182     }
2183
2184
2185 release:
2186     /* release the aops */
2187     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2188     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2189 }
2190 #endif
2191
2192 /*-----------------------------------------------------------------*/
2193 /* genUminusFloat - unary minus for floating points                */
2194 /*-----------------------------------------------------------------*/
2195 static void genUminusFloat(operand *op,operand *result)
2196 {
2197     int size ,offset =0 ;
2198     char *l;
2199
2200     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2201     /* for this we just need to flip the 
2202     first it then copy the rest in place */
2203     size = AOP_SIZE(op) - 1;
2204     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2205
2206     MOVA(l);    
2207
2208     pic16_emitcode("cpl","acc.7");
2209     pic16_aopPut(AOP(result),"a",3);    
2210
2211     while(size--) {
2212         pic16_aopPut(AOP(result),
2213                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2214                offset);
2215         offset++;
2216     }          
2217 }
2218
2219 /*-----------------------------------------------------------------*/
2220 /* genUminus - unary minus code generation                         */
2221 /*-----------------------------------------------------------------*/
2222 static void genUminus (iCode *ic)
2223 {
2224   int size, i;
2225   sym_link *optype, *rtype;
2226
2227         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2228         
2229         /* assign asmops */
2230         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2231         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2232
2233         /* if both in bit space then special case */
2234         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2235                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2236
2237                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2238                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2239                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2240                 
2241                 goto release; 
2242         } 
2243
2244         optype = operandType(IC_LEFT(ic));
2245         rtype = operandType(IC_RESULT(ic));
2246
2247         /* if float then do float stuff */
2248         if (IS_FLOAT(optype)) {
2249                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2250                 goto release;
2251         }
2252
2253         /* otherwise subtract from zero by taking the 2's complement */
2254         size = AOP_SIZE(IC_LEFT(ic));
2255
2256         for(i=0; i<size; i++) {
2257                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2258                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2259                 else {
2260                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2261                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2262                 }
2263         }
2264
2265         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2266         for(i=1; i<size; i++) {
2267                 emitSKPNZ;
2268                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2269         }
2270
2271 release:
2272         /* release the aops */
2273         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2274         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* saveRegisters - will look for a call and save the registers     */
2279 /*-----------------------------------------------------------------*/
2280 static void saveRegisters(iCode *lic) 
2281 {
2282     int i;
2283     iCode *ic;
2284     bitVect *rsave;
2285     sym_link *dtype;
2286
2287     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2288     /* look for call */
2289     for (ic = lic ; ic ; ic = ic->next) 
2290         if (ic->op == CALL || ic->op == PCALL)
2291             break;
2292
2293     if (!ic) {
2294         fprintf(stderr,"found parameter push with no function call\n");
2295         return ;
2296     }
2297
2298     /* if the registers have been saved already then
2299     do nothing */
2300     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2301         return ;
2302
2303     /* find the registers in use at this time 
2304     and push them away to safety */
2305     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2306                           ic->rUsed);
2307
2308     ic->regsSaved = 1;
2309     if (options.useXstack) {
2310         if (bitVectBitValue(rsave,R0_IDX))
2311             pic16_emitcode("mov","b,r0");
2312         pic16_emitcode("mov","r0,%s",spname);
2313         for (i = 0 ; i < pic16_nRegs ; i++) {
2314             if (bitVectBitValue(rsave,i)) {
2315                 if (i == R0_IDX)
2316                     pic16_emitcode("mov","a,b");
2317                 else
2318                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2319                 pic16_emitcode("movx","@r0,a");
2320                 pic16_emitcode("inc","r0");
2321             }
2322         }
2323         pic16_emitcode("mov","%s,r0",spname);
2324         if (bitVectBitValue(rsave,R0_IDX))
2325             pic16_emitcode("mov","r0,b");           
2326     }// else
2327     //for (i = 0 ; i < pic16_nRegs ; i++) {
2328     //    if (bitVectBitValue(rsave,i))
2329     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2330     //}
2331
2332     dtype = operandType(IC_LEFT(ic));
2333     if (currFunc && dtype && 
2334         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2335         IFFUNC_ISISR(currFunc->type) &&
2336         !ic->bankSaved) 
2337
2338         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2339
2340 }
2341 /*-----------------------------------------------------------------*/
2342 /* unsaveRegisters - pop the pushed registers                      */
2343 /*-----------------------------------------------------------------*/
2344 static void unsaveRegisters (iCode *ic)
2345 {
2346     int i;
2347     bitVect *rsave;
2348
2349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2350     /* find the registers in use at this time 
2351     and push them away to safety */
2352     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2353                           ic->rUsed);
2354     
2355     if (options.useXstack) {
2356         pic16_emitcode("mov","r0,%s",spname);   
2357         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2358             if (bitVectBitValue(rsave,i)) {
2359                 pic16_emitcode("dec","r0");
2360                 pic16_emitcode("movx","a,@r0");
2361                 if (i == R0_IDX)
2362                     pic16_emitcode("mov","b,a");
2363                 else
2364                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2365             }       
2366
2367         }
2368         pic16_emitcode("mov","%s,r0",spname);
2369         if (bitVectBitValue(rsave,R0_IDX))
2370             pic16_emitcode("mov","r0,b");
2371     } //else
2372     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2373     //    if (bitVectBitValue(rsave,i))
2374     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2375     //}
2376
2377 }  
2378
2379 #if 0  // patch 14
2380 /*-----------------------------------------------------------------*/
2381 /* pushSide -                                                      */
2382 /*-----------------------------------------------------------------*/
2383 static void pushSide(operand * oper, int size)
2384 {
2385         int offset = 0;
2386     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2387         while (size--) {
2388                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2389                 if (AOP_TYPE(oper) != AOP_REG &&
2390                     AOP_TYPE(oper) != AOP_DIR &&
2391                     strcmp(l,"a") ) {
2392                         pic16_emitcode("mov","a,%s",l);
2393                         pic16_emitcode("push","acc");
2394                 } else
2395                         pic16_emitcode("push","%s",l);
2396         }
2397 }
2398 #endif // patch 14
2399
2400 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2401 {
2402 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2403
2404         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2405                 pic16_emitpcode(POC_MOVFW, src);
2406                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2407         } else {
2408                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2409                         src, pic16_popGet(AOP(op), offset)));
2410         }
2411 }
2412
2413
2414 /*-----------------------------------------------------------------*/
2415 /* assignResultValue - assign results to oper, rescall==1 is       */
2416 /*                     called from genCall() or genPCall()         */
2417 /*-----------------------------------------------------------------*/
2418 static void assignResultValue(operand * oper, int rescall)
2419 {
2420   int size = AOP_SIZE(oper);
2421
2422         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2423         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2424
2425         if(rescall) {
2426                 /* assign result from a call/pcall function() */
2427                 
2428                 /* function results are stored in a special order,
2429                  * see top of file with Function return policy, or manual */
2430
2431                 if(size <= 4) {
2432                         /* 8-bits, result in WREG */
2433                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2434                         
2435                         if(size>1) {
2436                                 /* 16-bits, result in PRODL:WREG */
2437                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2438                         }
2439                         
2440                         if(size>2) {
2441                                 /* 24-bits, result in PRODH:PRODL:WREG */
2442                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2443                         }
2444                         
2445                         if(size>3) {
2446                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2447                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2448                         }
2449                 } else {
2450                         /* >32-bits, result on stack, and FSR0 points to beginning.
2451                          * Fix stack when done */
2452                          /* FIXME FIXME */
2453                         while (size--) {
2454 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2455 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2456                 
2457                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2458                                 GpsuedoStkPtr++;
2459                         }
2460                         
2461                         /* fix stack */
2462                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2463                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2464                         if(STACK_MODEL_LARGE) {
2465                                 emitSKPNC;
2466                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2467                         }
2468                 }                       
2469         } else {        
2470                 if(!GpsuedoStkPtr) {
2471 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2472                         /* The last byte in the assignment is in W */
2473                         size--;
2474                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2475                         GpsuedoStkPtr++;
2476                 }
2477
2478                 while (size--) {
2479 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2480 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2481                 
2482                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2483                         GpsuedoStkPtr++;
2484
2485 #if 0
2486 #if STACK_SUPPORT
2487                 if(!USE_STACK)
2488                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2489 #else
2490                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2491 #endif
2492 #endif
2493
2494                 }
2495         }
2496                 
2497 }
2498
2499
2500 /*-----------------------------------------------------------------*/
2501 /* genIpush - genrate code for pushing this gets a little complex  */
2502 /*-----------------------------------------------------------------*/
2503 static void genIpush (iCode *ic)
2504 {
2505
2506   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2507 #if 0
2508     int size, offset = 0 ;
2509     char *l;
2510
2511
2512     /* if this is not a parm push : ie. it is spill push 
2513     and spill push is always done on the local stack */
2514     if (!ic->parmPush) {
2515
2516         /* and the item is spilt then do nothing */
2517         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2518             return ;
2519
2520         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2521         size = AOP_SIZE(IC_LEFT(ic));
2522         /* push it on the stack */
2523         while(size--) {
2524             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2525             if (*l == '#') {
2526                 MOVA(l);
2527                 l = "acc";
2528             }
2529             pic16_emitcode("push","%s",l);
2530         }
2531         return ;        
2532     }
2533
2534     /* this is a paramter push: in this case we call
2535     the routine to find the call and save those
2536     registers that need to be saved */   
2537     saveRegisters(ic);
2538
2539     /* then do the push */
2540     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2541
2542
2543         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2544     size = AOP_SIZE(IC_LEFT(ic));
2545
2546     while (size--) {
2547         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2548         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2549             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2550             strcmp(l,"a") ) {
2551             pic16_emitcode("mov","a,%s",l);
2552             pic16_emitcode("push","acc");
2553         } else
2554             pic16_emitcode("push","%s",l);
2555     }       
2556
2557     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2558 #endif
2559 }
2560
2561 /*-----------------------------------------------------------------*/
2562 /* genIpop - recover the registers: can happen only for spilling   */
2563 /*-----------------------------------------------------------------*/
2564 static void genIpop (iCode *ic)
2565 {
2566   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2567 #if 0
2568     int size,offset ;
2569
2570
2571     /* if the temp was not pushed then */
2572     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2573         return ;
2574
2575     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2576     size = AOP_SIZE(IC_LEFT(ic));
2577     offset = (size-1);
2578     while (size--) 
2579         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2580                                    FALSE,TRUE));
2581
2582     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2583 #endif
2584 }
2585
2586 /*-----------------------------------------------------------------*/
2587 /* unsaverbank - restores the resgister bank from stack            */
2588 /*-----------------------------------------------------------------*/
2589 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2590 {
2591   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2592 #if 0
2593     int i;
2594     asmop *aop ;
2595     regs *r = NULL;
2596
2597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2598     if (popPsw) {
2599         if (options.useXstack) {
2600             aop = newAsmop(0);
2601             r = getFreePtr(ic,&aop,FALSE);
2602             
2603             
2604             pic16_emitcode("mov","%s,_spx",r->name);
2605             pic16_emitcode("movx","a,@%s",r->name);
2606             pic16_emitcode("mov","psw,a");
2607             pic16_emitcode("dec","%s",r->name);
2608             
2609         }else
2610             pic16_emitcode ("pop","psw");
2611     }
2612
2613     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2614         if (options.useXstack) {       
2615             pic16_emitcode("movx","a,@%s",r->name);
2616             //pic16_emitcode("mov","(%s+%d),a",
2617             //       regspic16[i].base,8*bank+regspic16[i].offset);
2618             pic16_emitcode("dec","%s",r->name);
2619
2620         } else 
2621           pic16_emitcode("pop",""); //"(%s+%d)",
2622         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2623     }
2624
2625     if (options.useXstack) {
2626
2627         pic16_emitcode("mov","_spx,%s",r->name);
2628         pic16_freeAsmop(NULL,aop,ic,TRUE);
2629
2630     }
2631 #endif 
2632 }
2633
2634 /*-----------------------------------------------------------------*/
2635 /* saverbank - saves an entire register bank on the stack          */
2636 /*-----------------------------------------------------------------*/
2637 static void saverbank (int bank, iCode *ic, bool pushPsw)
2638 {
2639   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2640 #if 0
2641     int i;
2642     asmop *aop ;
2643     regs *r = NULL;
2644
2645     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2646     if (options.useXstack) {
2647
2648         aop = newAsmop(0);
2649         r = getFreePtr(ic,&aop,FALSE);  
2650         pic16_emitcode("mov","%s,_spx",r->name);
2651
2652     }
2653
2654     for (i = 0 ; i < pic16_nRegs ;i++) {
2655         if (options.useXstack) {
2656             pic16_emitcode("inc","%s",r->name);
2657             //pic16_emitcode("mov","a,(%s+%d)",
2658             //         regspic16[i].base,8*bank+regspic16[i].offset);
2659             pic16_emitcode("movx","@%s,a",r->name);           
2660         } else 
2661           pic16_emitcode("push","");// "(%s+%d)",
2662                      //regspic16[i].base,8*bank+regspic16[i].offset);
2663     }
2664     
2665     if (pushPsw) {
2666         if (options.useXstack) {
2667             pic16_emitcode("mov","a,psw");
2668             pic16_emitcode("movx","@%s,a",r->name);     
2669             pic16_emitcode("inc","%s",r->name);
2670             pic16_emitcode("mov","_spx,%s",r->name);       
2671             pic16_freeAsmop (NULL,aop,ic,TRUE);
2672             
2673         } else
2674             pic16_emitcode("push","psw");
2675         
2676         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2677     }
2678     ic->bankSaved = 1;
2679 #endif
2680 }
2681
2682
2683
2684 /*-----------------------------------------------------------------*/
2685 /* genCall - generates a call statement                            */
2686 /*-----------------------------------------------------------------*/
2687 static void genCall (iCode *ic)
2688 {
2689   sym_link *dtype;   
2690   int stackParms=0;
2691   
2692         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2693
2694         /* if caller saves & we have not saved then */
2695         if (!ic->regsSaved)
2696                 saveRegisters(ic);
2697
2698         /* if we are calling a function that is not using
2699          * the same register bank then we need to save the
2700          * destination registers on the stack */
2701         dtype = operandType(IC_LEFT(ic));
2702         if (currFunc && dtype && 
2703                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2704                 IFFUNC_ISISR(currFunc->type) &&
2705                 !ic->bankSaved) 
2706
2707                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2708
2709         /* if send set is not empty the assign */
2710         if (_G.sendSet) {
2711           iCode *sic;
2712
2713                 /* For the Pic port, there is no data stack.
2714                  * So parameters passed to functions are stored
2715                  * in registers. (The pCode optimizer will get
2716                  * rid of most of these :). */
2717
2718           int psuedoStkPtr=-1; 
2719           int firstTimeThruLoop = 1;
2720
2721                 _G.sendSet = reverseSet(_G.sendSet);
2722
2723                 /* First figure how many parameters are getting passed */
2724                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2725                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2726                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2727                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2728                 }
2729
2730                 stackParms = psuedoStkPtr;
2731
2732                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2733                   int size, offset = 0;
2734
2735                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2736                         size = AOP_SIZE(IC_LEFT(sic));
2737
2738                         while (size--) {
2739                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2740                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2741                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2742
2743                                 if(!firstTimeThruLoop) {
2744                                         /* If this is not the first time we've been through the loop
2745                                          * then we need to save the parameter in a temporary
2746                                          * register. The last byte of the last parameter is
2747                                          * passed in W. */
2748
2749                                         pushw();
2750                                         --psuedoStkPtr;         // sanity check
2751                                 }
2752                         
2753                                 firstTimeThruLoop=0;
2754
2755                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2756                                 offset++;
2757                         }
2758                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2759                 }
2760                 _G.sendSet = NULL;
2761         }
2762
2763         /* make the call */
2764         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2765                         OP_SYMBOL(IC_LEFT(ic))->rname :
2766                         OP_SYMBOL(IC_LEFT(ic))->name));
2767
2768         GpsuedoStkPtr=0;
2769         /* if we need assign a result value */
2770         if ((IS_ITEMP(IC_RESULT(ic)) && 
2771                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2772                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2773                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2774
2775                 _G.accInUse++;
2776                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2777                 _G.accInUse--;
2778
2779                 assignResultValue(IC_RESULT(ic), 1);
2780
2781                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2782                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2783                 
2784                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2785         }
2786
2787         if(stackParms>0) {
2788                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2789                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2790                 if(STACK_MODEL_LARGE) {
2791                         emitSKPNC;
2792                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2793                 }
2794         }
2795
2796         /* adjust the stack for parameters if required */
2797 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2798
2799         if (ic->parmBytes) {
2800           int i;
2801
2802                 if (ic->parmBytes > 3) {
2803                         pic16_emitcode("mov","a,%s",spname);
2804                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2805                         pic16_emitcode("mov","%s,a",spname);
2806                 } else 
2807                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2808                                 pic16_emitcode("dec","%s",spname);
2809         }
2810
2811 #if 0
2812         /* if register bank was saved then pop them */
2813         if (ic->bankSaved)
2814                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2815
2816         /* if we hade saved some registers then unsave them */
2817         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2818                 unsaveRegisters (ic);
2819 #endif
2820 }
2821
2822
2823
2824 /*-----------------------------------------------------------------*/   // patch 14
2825 /* genPcall - generates a call by pointer statement                */
2826 /*-----------------------------------------------------------------*/
2827
2828 // new version, created from genCall
2829
2830 static void genPcall (iCode *ic)
2831 {
2832   sym_link *dtype;   
2833   int stackParms=0;
2834   symbol *retlbl = newiTempLabel(NULL);
2835   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2836   
2837         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2838
2839         /* if caller saves & we have not saved then */
2840         if (!ic->regsSaved)
2841                 saveRegisters(ic);
2842
2843         /* if we are calling a function that is not using
2844          * the same register bank then we need to save the
2845          * destination registers on the stack */
2846         dtype = operandType(IC_LEFT(ic));
2847         if (currFunc && dtype && 
2848                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2849                 IFFUNC_ISISR(currFunc->type) &&
2850                 !ic->bankSaved) 
2851
2852                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2853
2854         /* if send set is not empty the assign */
2855         if (_G.sendSet) {
2856           iCode *sic;
2857
2858                 /* For the Pic port, there is no data stack.
2859                  * So parameters passed to functions are stored
2860                  * in registers. (The pCode optimizer will get
2861                  * rid of most of these :). */
2862
2863           int psuedoStkPtr=-1; 
2864           int firstTimeThruLoop = 1;
2865
2866                 _G.sendSet = reverseSet(_G.sendSet);
2867
2868                 /* First figure how many parameters are getting passed */
2869                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2870                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2871                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2872                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2873                 }
2874
2875                 stackParms = psuedoStkPtr;
2876
2877                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2878                   int size, offset = 0;
2879
2880                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2881                         size = AOP_SIZE(IC_LEFT(sic));
2882
2883                         while (size--) {
2884                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2885                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2886                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2887
2888                                 if(!firstTimeThruLoop) {
2889                                         /* If this is not the first time we've been through the loop
2890                                          * then we need to save the parameter in a temporary
2891                                          * register. The last byte of the last parameter is
2892                                          * passed in W. */
2893
2894                                         pushw();
2895                                         --psuedoStkPtr;         // sanity check
2896                                 }
2897                         
2898                                 firstTimeThruLoop=0;
2899
2900                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2901                                 offset++;
2902                         }
2903                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2904                 }
2905                 _G.sendSet = NULL;
2906         }
2907
2908         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2909
2910         // push return address
2911         // push $ on return stack, then replace with retlbl
2912
2913         pic16_emitpcodeNULLop(POC_PUSH);
2914
2915         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2916         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2917         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2918         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2919         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2920         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2921
2922         /* make the call by writing the pointer into pc */
2923         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2924         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2925
2926         // note: MOVFF to PCL not allowed
2927         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2928         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2929
2930
2931 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2932 //      pic16_emitpcodeNULLop(POC_NOP);
2933 //      pic16_emitpcodeNULLop(POC_NOP);
2934
2935         /* return address is here: (X) */
2936         pic16_emitpLabelFORCE(retlbl->key);
2937
2938 //      pic16_emitpcodeNULLop(POC_NOP);
2939
2940         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2941
2942         GpsuedoStkPtr=0;
2943         /* if we need assign a result value */
2944         if ((IS_ITEMP(IC_RESULT(ic)) && 
2945                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2946                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2947                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2948
2949                 _G.accInUse++;
2950                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2951                 _G.accInUse--;
2952
2953                 assignResultValue(IC_RESULT(ic), 1);
2954
2955                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2956                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2957                 
2958                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2959         }
2960
2961         if(stackParms>0) {
2962                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2963                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2964                 if(STACK_MODEL_LARGE) {
2965                         emitSKPNC;
2966                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2967                 }
2968         }
2969
2970         /* adjust the stack for parameters if required */
2971 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2972
2973         if (ic->parmBytes) {
2974           int i;
2975
2976                 if (ic->parmBytes > 3) {
2977                         pic16_emitcode("mov","a,%s",spname);
2978                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2979                         pic16_emitcode("mov","%s,a",spname);
2980                 } else 
2981                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2982                                 pic16_emitcode("dec","%s",spname);
2983         }
2984
2985         /* if register bank was saved then pop them */
2986         if (ic->bankSaved)
2987                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2988
2989         /* if we hade saved some registers then unsave them */
2990         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2991                 unsaveRegisters (ic);
2992 }
2993
2994
2995 #if 0                                                                           // patch 14
2996 // old version, kept for reference
2997
2998 /*-----------------------------------------------------------------*/
2999 /* genPcall - generates a call by pointer statement                */
3000 /*-----------------------------------------------------------------*/
3001 static void genPcall (iCode *ic)
3002 {
3003     sym_link *dtype;
3004     symbol *rlbl = newiTempLabel(NULL);
3005
3006
3007     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3008     /* if caller saves & we have not saved then */
3009     if (!ic->regsSaved)
3010         saveRegisters(ic);
3011
3012     /* if we are calling a function that is not using
3013     the same register bank then we need to save the
3014     destination registers on the stack */
3015     dtype = operandType(IC_LEFT(ic));
3016     if (currFunc && dtype && 
3017         IFFUNC_ISISR(currFunc->type) &&
3018         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3019         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3020
3021
3022     /* push the return address on to the stack */
3023     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3024     pic16_emitcode("push","acc");    
3025     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3026     pic16_emitcode("push","acc");
3027     
3028     if (options.model == MODEL_FLAT24)
3029     {
3030         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3031         pic16_emitcode("push","acc");    
3032     }
3033
3034     /* now push the calling address */
3035     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3036
3037     pushSide(IC_LEFT(ic), FPTRSIZE);
3038
3039     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3040
3041     /* if send set is not empty the assign */
3042     if (_G.sendSet) {
3043         iCode *sic ;
3044
3045         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3046              sic = setNextItem(_G.sendSet)) {
3047             int size, offset = 0;
3048             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3049             size = AOP_SIZE(IC_LEFT(sic));
3050             while (size--) {
3051                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3052                                 FALSE,FALSE);
3053                 if (strcmp(l,fReturn[offset]))
3054                     pic16_emitcode("mov","%s,%s",
3055                              fReturn[offset],
3056                              l);
3057                 offset++;
3058             }
3059             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3060         }
3061         _G.sendSet = NULL;
3062     }
3063
3064     pic16_emitcode("ret","");
3065     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3066
3067
3068     /* if we need assign a result value */
3069     if ((IS_ITEMP(IC_RESULT(ic)) &&
3070          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3071           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3072         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3073
3074         _G.accInUse++;
3075         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3076         _G.accInUse--;
3077         
3078         assignResultValue(IC_RESULT(ic), 1);
3079
3080         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3081     }
3082
3083     /* adjust the stack for parameters if 
3084     required */
3085     if (ic->parmBytes) {
3086         int i;
3087         if (ic->parmBytes > 3) {
3088             pic16_emitcode("mov","a,%s",spname);
3089             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3090             pic16_emitcode("mov","%s,a",spname);
3091         } else 
3092             for ( i = 0 ; i <  ic->parmBytes ;i++)
3093                 pic16_emitcode("dec","%s",spname);
3094
3095     }
3096
3097     /* if register bank was saved then unsave them */
3098     if (currFunc && dtype && 
3099         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3100         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3101
3102     /* if we hade saved some registers then
3103     unsave them */
3104     if (ic->regsSaved)
3105         unsaveRegisters (ic);
3106
3107 }
3108 #endif                                                                          // patch 14
3109
3110
3111 /*-----------------------------------------------------------------*/
3112 /* resultRemat - result  is rematerializable                       */
3113 /*-----------------------------------------------------------------*/
3114 static int resultRemat (iCode *ic)
3115 {
3116   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3117   if (SKIP_IC(ic) || ic->op == IFX)
3118     return 0;
3119
3120   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3121     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3122     if (sym->remat && !POINTER_SET(ic)) 
3123       return 1;
3124   }
3125
3126   return 0;
3127 }
3128
3129 #if defined(__BORLANDC__) || defined(_MSC_VER)
3130 #define STRCASECMP stricmp
3131 #else
3132 #define STRCASECMP strcasecmp
3133 #endif
3134
3135 #if 0
3136 /*-----------------------------------------------------------------*/
3137 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3138 /*-----------------------------------------------------------------*/
3139 static bool inExcludeList(char *s)
3140 {
3141   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3142     int i =0;
3143     
3144     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3145     if (options.excludeRegs[i] &&
3146     STRCASECMP(options.excludeRegs[i],"none") == 0)
3147         return FALSE ;
3148
3149     for ( i = 0 ; options.excludeRegs[i]; i++) {
3150         if (options.excludeRegs[i] &&
3151         STRCASECMP(s,options.excludeRegs[i]) == 0)
3152             return TRUE;
3153     }
3154     return FALSE ;
3155 }
3156 #endif
3157
3158 /*-----------------------------------------------------------------*/
3159 /* genFunction - generated code for function entry                 */
3160 /*-----------------------------------------------------------------*/
3161 static void genFunction (iCode *ic)
3162 {
3163   symbol *sym;
3164   sym_link *ftype;
3165   
3166         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3167
3168         pic16_labelOffset += (max_key+4);
3169         max_key=0;
3170         GpsuedoStkPtr=0;
3171         _G.nRegsSaved = 0;
3172
3173         ftype = operandType(IC_LEFT(ic));
3174         sym = OP_SYMBOL(IC_LEFT(ic));
3175
3176         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3177                 /* create an absolute section at the interrupt vector:
3178                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3179           symbol *asym;
3180           char asymname[128];
3181           pBlock *apb;
3182
3183                 {
3184                   int i, found=-1;
3185
3186                         sym = OP_SYMBOL( IC_LEFT(ic));
3187                         for(i=0;i<=2;i++) {
3188                                 if(interrupts[i]->name
3189                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3190                                         found = i;
3191                                         break;
3192                                 }
3193                         }
3194                         
3195                         if(found == -1) {
3196                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3197                                         __FILE__, __LINE__, sym->name);
3198                                 assert( 0 );
3199                         }
3200                         _G.interruptvector = found;
3201                 }
3202
3203                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3204                 asym = newSymbol(asymname, 0);
3205
3206                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3207                 pic16_addpBlock( apb );
3208
3209                 pic16_addpCode2pBlock(apb,
3210                         pic16_newpCodeCharP(";-----------------------------------------"));
3211
3212
3213                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3214
3215                 pic16_addpCode2pBlock(apb,
3216                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3217                 
3218                 /* mark the end of this tiny function */
3219                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3220
3221                 {
3222                   absSym *abSym;
3223
3224                         abSym = Safe_calloc(1, sizeof(absSym));
3225                         abSym->name = Safe_strdup( asymname );
3226
3227                         switch( _G.interruptvector ) {
3228                                 case 0: abSym->address = 0x000000; break;
3229                                 case 1: abSym->address = 0x000008; break;
3230                                 case 2: abSym->address = 0x000018; break;
3231                         }
3232
3233                         /* relocate interrupt vectors if needed */
3234                         abSym->address += pic16_options.ivt_loc;
3235
3236                         addSet(&absSymSet, abSym);
3237                 }
3238         }
3239
3240
3241         /* create the function header */
3242         pic16_emitcode(";","-----------------------------------------");
3243         pic16_emitcode(";"," function %s",sym->name);
3244         pic16_emitcode(";","-----------------------------------------");
3245
3246         pic16_emitcode("","%s:",sym->rname);
3247         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3248
3249
3250         {
3251           absSym *ab;
3252
3253                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3254                         if(!strcmp(ab->name, sym->name)) {
3255                                 pic16_pBlockConvert2Absolute(pb);
3256                                 break;
3257                         }
3258
3259         }
3260
3261
3262         if(IFFUNC_ISNAKED(ftype)) {
3263                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3264                 return;
3265         }
3266         
3267         /* if critical function then turn interrupts off */
3268         if (IFFUNC_ISCRITICAL(ftype))
3269                 pic16_emitcode("clr","ea");
3270
3271         /* if this is an interrupt service routine then
3272          * save acc, b, dpl, dph  */
3273         if (IFFUNC_ISISR(sym->type)) {
3274           int i;
3275                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3276                 if(!(_G.interruptvector == 1)) {
3277
3278                         /* do not save WREG,STATUS,BSR for high priority interrupts
3279                          * because they are stored in the hardware shadow registers already */
3280                          
3281                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3282                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3283                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3284                 }
3285
3286                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3287                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3288                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3289                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3290
3291 //                pic16_pBlockConvert2ISR(pb);
3292                 
3293                 /* if any registers used */
3294                 if (sym->regsUsed) {
3295                         /* save the registers used */
3296                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3297                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3298                                 if (bitVectBitValue(sym->regsUsed,i)) {
3299 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3300 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3301 //                                                      pic16_regWithIdx(i)->name);
3302
3303                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3304                                         _G.nRegsSaved++;
3305                                 }
3306                         }
3307                 }
3308         } else {
3309                 /* emit code to setup stack frame if user enabled,
3310                  * and function is not main() */
3311          
3312 //              fprintf(stderr, "function name: %s\n", sym->name);
3313                 if(strcmp(sym->name, "main")) {
3314                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3315                         /* setup the stack frame */
3316                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3317                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3318                                 if(STACK_MODEL_LARGE)
3319                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3320                         }
3321                 }
3322
3323                 /* if callee-save to be used for this function
3324                 * then save the registers being used in this function */
3325 //              if (IFFUNC_CALLEESAVES(sym->type))
3326                 {
3327                   int i;
3328
3329 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3330
3331 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3332
3333                         /* if any registers used */
3334                         if (sym->regsUsed) {
3335                                 /* save the registers used */
3336                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3337                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3338                                         if (bitVectBitValue(sym->regsUsed,i)) {
3339
3340 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3341 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3342 //                                                              pic16_regWithIdx(i)->name);
3343
3344                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3345
3346 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3347 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3348 //                                                      &pic16_pc_postdec1, 0));
3349
3350                                                 _G.nRegsSaved++;
3351                                         }
3352                                 }
3353                         }
3354                 }
3355         }
3356
3357
3358         
3359 #if 0
3360         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3361
3362                 if (options.useXstack) {
3363                         pic16_emitcode("mov","r0,%s",spname);
3364                         pic16_emitcode("mov","a,_bp");
3365                         pic16_emitcode("movx","@r0,a");
3366                         pic16_emitcode("inc","%s",spname);
3367                 } else {
3368                         /* set up the stack */
3369                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3370                 }
3371                 pic16_emitcode ("mov","_bp,%s",spname);
3372         }
3373 #endif
3374         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3375
3376         /* adjust the stack for the function */
3377         if (sym->stack) {
3378           int i = sym->stack;
3379
3380                 if (i > 127 ) 
3381                         werror(W_STACK_OVERFLOW,sym->name);
3382
3383                 if (i > 3 && sym->recvSize < 4) {              
3384                         pic16_emitcode ("mov","a,sp");
3385                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3386                         pic16_emitcode ("mov","sp,a");
3387                 } else
3388                         while(i--)
3389                                 pic16_emitcode("inc","sp");
3390         }
3391
3392         if (sym->xstack) {
3393                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3394
3395                 pic16_emitcode ("mov","a,_spx");
3396                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3397                 pic16_emitcode ("mov","_spx,a");
3398         }
3399     
3400 }
3401
3402 /*-----------------------------------------------------------------*/
3403 /* genEndFunction - generates epilogue for functions               */
3404 /*-----------------------------------------------------------------*/
3405 static void genEndFunction (iCode *ic)
3406 {
3407     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3408
3409     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3410
3411     if(IFFUNC_ISNAKED(sym->type)) {
3412         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3413         return;
3414     }
3415
3416 #if 0
3417     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3418     {
3419         pic16_emitcode ("mov","%s,_bp",spname);
3420     }
3421 #endif
3422
3423     /* if use external stack but some variables were
3424     added to the local stack then decrement the
3425     local stack */
3426     if (options.useXstack && sym->stack) {      
3427         pic16_emitcode("mov","a,sp");
3428         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3429         pic16_emitcode("mov","sp,a");
3430     }
3431
3432
3433 #if 0
3434     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3435         if (options.useXstack) {
3436             pic16_emitcode("mov","r0,%s",spname);
3437             pic16_emitcode("movx","a,@r0");
3438             pic16_emitcode("mov","_bp,a");
3439             pic16_emitcode("dec","%s",spname);
3440         }
3441         else
3442         {
3443             pic16_emitcode ("pop","_bp");
3444         }
3445     }
3446 #endif
3447
3448         if (IFFUNC_ISISR(sym->type)) {
3449                 /* now we need to restore the registers */
3450                 /* if any registers used */
3451                 if (sym->regsUsed) {
3452                   int i;
3453
3454                         /* restore registers used */
3455                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3456                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3457                                 if (bitVectBitValue(sym->regsUsed,i)) {
3458
3459 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3460 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3461 //                                                      pic16_regWithIdx(i)->name);
3462
3463                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3464
3465 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3466 //                                                      &pic16_pc_preinc1,
3467 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3468
3469                                 }
3470                         }
3471                 }
3472         
3473                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3474                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3475                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3476                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3477
3478                 if(!(_G.interruptvector == 1)) {
3479                         /* do not restore interrupt vector for WREG,STATUS,BSR
3480                          * for high priority interrupt, see genFunction */
3481                          
3482                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3483                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3484                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3485                 }
3486         
3487                 _G.interruptvector = 0;         /* sanity check */
3488
3489 //              pic16_pBlockConvert2ISR(pb);
3490
3491
3492                 /* if debug then send end of function */
3493 /*      if (options.debug && currFunc)  */
3494                 if (currFunc) {
3495                         debugFile->writeEndFunction (currFunc, ic, 1);
3496                 }
3497         
3498                 pic16_emitpcodeNULLop(POC_RETFIE);
3499         } else {
3500                 if (IFFUNC_ISCRITICAL(sym->type))
3501                         pic16_emitcode("setb","ea");
3502         
3503
3504 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3505
3506                 /* if any registers used */
3507                 if (sym->regsUsed) {
3508                   int i;
3509                         /* save the registers used */
3510                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3511                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3512                                 if (bitVectBitValue(sym->regsUsed,i)) {
3513         
3514 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3515 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3516 //                                                      pic16_regWithIdx(i)->name);
3517         
3518                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3519                                         
3520 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3521 //                                              &pic16_pc_preinc1,
3522 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3523
3524                                         _G.nRegsSaved--;
3525                                 }
3526                         }
3527                 }
3528         
3529 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3530                 /* if debug then send end of function */
3531                 if (currFunc) {
3532                         debugFile->writeEndFunction (currFunc, ic, 1);
3533                 }
3534
3535                 /* insert code to restore stack frame, if user enabled it
3536                  * and function is not main() */
3537          
3538
3539                 if(strcmp(sym->name, "main")) {
3540                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3541                                 /* restore stack frame */
3542                                 if(STACK_MODEL_LARGE)
3543                                         pic16_emitpcode(POC_MOVFF,
3544                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3545                                 pic16_emitpcode(POC_MOVFF,
3546                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3547                         }
3548                 }
3549
3550                 pic16_emitcode ("return","");
3551                 pic16_emitpcodeNULLop(POC_RETURN);
3552
3553                 /* Mark the end of a function */
3554                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3555         }
3556
3557 }
3558
3559
3560 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3561 {
3562
3563         if(is_LitOp(op)) {
3564                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3565
3566                 if(dest->type != PO_WREG)
3567                         pic16_emitpcode(POC_MOVWF, dest);
3568         } else {
3569                 if(dest->type == PO_WREG && (offset == 0)) {
3570                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3571                         return;
3572                 }
3573                 
3574                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3575                         pic16_popGet(AOP(op), offset), dest));
3576         }
3577 }
3578
3579 /*-----------------------------------------------------------------*/
3580 /* genRet - generate code for return statement                     */
3581 /*-----------------------------------------------------------------*/
3582 static void genRet (iCode *ic)
3583 {
3584   int size;
3585   operand *left;
3586
3587         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3588         /* if we have no return value then
3589          * just generate the "ret" */
3590         
3591         if (!IC_LEFT(ic)) 
3592                 goto jumpret;       
3593     
3594         /* we have something to return then
3595          * move the return value into place */
3596         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3597         size = AOP_SIZE(IC_LEFT(ic));
3598
3599         if(size <= 4) {
3600                 if(size>3) {
3601                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3602 //                      pic16_emitpcode(POC_MOVFF,
3603 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3604                 }
3605                 if(size>2) {
3606                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3607 //                      pic16_emitpcode(POC_MOVFF,
3608 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3609                 }
3610                 if(size>1) {
3611                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3612 //                      pic16_emitpcode(POC_MOVFF,
3613 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3614                 }
3615
3616 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3617
3618                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3619 //              pic16_emitpcode(POC_MOVFF,
3620 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3621
3622         } else {
3623                 /* >32-bits, setup stack and FSR0 */
3624                 while (size--) {
3625 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3626 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3627
3628                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3629
3630 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3631                         GpsuedoStkPtr++;
3632                 }
3633                         
3634                 /* setup FSR0 */
3635                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3636                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3637
3638                 if(STACK_MODEL_LARGE) {
3639                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3640                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3641                 } else {
3642                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3643                 }
3644         }
3645                                 
3646 #if 0
3647         /* old code, left here for reference -- VR */    
3648         while (size--) {
3649           char *l ;
3650
3651                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3652                         /* #NOCHANGE */
3653                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3654                         pic16_emitpcomment("push %s",l);
3655                         pushed++;
3656                 } else {
3657                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3658                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3659                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3660                         
3661                         if (strcmp(fReturn[offset],l)) {
3662                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3663                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3664                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3665                                 } else {
3666                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3667                                 }
3668                                 
3669                                 if(size) {
3670                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3671                                 }
3672                                 offset++;
3673                         }
3674                 }
3675         }    
3676
3677         if (pushed) {
3678                 while(pushed) {
3679                         pushed--;
3680                         if (strcmp(fReturn[pushed],"a"))
3681                                 pic16_emitcode("pop",fReturn[pushed]);
3682                         else
3683                                 pic16_emitcode("pop","acc");
3684                 }
3685         }
3686 #endif
3687
3688
3689         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3690     
3691 jumpret:
3692         /* generate a jump to the return label
3693          * if the next is not the return statement */
3694         if (!(ic->next && ic->next->op == LABEL
3695                 && IC_LABEL(ic->next) == returnLabel)) {
3696         
3697                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3698                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3699         }
3700 }
3701
3702 /*-----------------------------------------------------------------*/
3703 /* genLabel - generates a label                                    */
3704 /*-----------------------------------------------------------------*/
3705 static void genLabel (iCode *ic)
3706 {
3707
3708
3709     /* special case never generate */
3710     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3711     if (IC_LABEL(ic) == entryLabel)
3712         return ;
3713
3714     pic16_emitpLabel(IC_LABEL(ic)->key);
3715     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3716 }
3717
3718 /*-----------------------------------------------------------------*/
3719 /* genGoto - generates a goto                                      */
3720 /*-----------------------------------------------------------------*/
3721 //tsd
3722 static void genGoto (iCode *ic)
3723 {
3724   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3725   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3726 }
3727
3728
3729 /*-----------------------------------------------------------------*/
3730 /* genMultbits :- multiplication of bits                           */
3731 /*-----------------------------------------------------------------*/
3732 static void genMultbits (operand *left, 
3733                          operand *right, 
3734                          operand *result)
3735 {
3736   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3737
3738   if(!pic16_sameRegs(AOP(result),AOP(right)))
3739     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3740
3741   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3742   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3743   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3744
3745 }
3746
3747
3748 /*-----------------------------------------------------------------*/
3749 /* genMultOneByte : 8 bit multiplication & division                */
3750 /*-----------------------------------------------------------------*/
3751 static void genMultOneByte (operand *left,
3752                             operand *right,
3753                             operand *result)
3754 {
3755
3756   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3757   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3758   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3759
3760   /* (if two literals, the value is computed before) */
3761   /* if one literal, literal on the right */
3762   if (AOP_TYPE(left) == AOP_LIT){
3763     operand *t = right;
3764     right = left;
3765     left = t;
3766   }
3767
3768         /* size is already checked in genMult == 1 */
3769 //      size = AOP_SIZE(result);
3770
3771         if (AOP_TYPE(right) == AOP_LIT){
3772                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3773                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3774                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3775                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3776         } else {
3777                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3778                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3779                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3780                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3781         }
3782         
3783         pic16_genMult8X8_8 (left, right,result);
3784 }
3785
3786 /*-----------------------------------------------------------------*/
3787 /* genMultOneWord : 16 bit multiplication                          */
3788 /*-----------------------------------------------------------------*/
3789 static void genMultOneWord (operand *left,
3790                             operand *right,
3791                             operand *result)
3792 {
3793
3794         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3795         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3796         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3797
3798         /* (if two literals, the value is computed before)
3799          * if one literal, literal on the right */
3800         if (AOP_TYPE(left) == AOP_LIT){
3801           operand *t = right;
3802                 right = left;
3803                 left = t;
3804         }
3805
3806         /* size is checked already == 2 */
3807 //      size = AOP_SIZE(result);
3808
3809         if (AOP_TYPE(right) == AOP_LIT) {
3810                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3811                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3812                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3813                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3814         } else {
3815                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3816                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3817                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3818                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3819         }
3820         
3821         pic16_genMult16X16_16(left, right,result);
3822 }
3823
3824 /*-----------------------------------------------------------------*/
3825 /* genMultOneLong : 32 bit multiplication                          */
3826 /*-----------------------------------------------------------------*/
3827 static void genMultOneLong (operand *left,
3828                             operand *right,
3829                             operand *result)
3830 {
3831
3832         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3833         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3834         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3835
3836         /* (if two literals, the value is computed before)
3837          * if one literal, literal on the right */
3838         if (AOP_TYPE(left) == AOP_LIT){
3839           operand *t = right;
3840                 right = left;
3841                 left = t;
3842         }
3843
3844         /* size is checked already == 4 */
3845 //      size = AOP_SIZE(result);
3846
3847         if (AOP_TYPE(right) == AOP_LIT) {
3848                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3849                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3850                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3851                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3852         } else {
3853                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3854                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3855                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3856                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3857         }
3858         
3859         pic16_genMult32X32_32(left, right,result);
3860 }
3861
3862
3863
3864 /*-----------------------------------------------------------------*/
3865 /* genMult - generates code for multiplication                     */
3866 /*-----------------------------------------------------------------*/
3867 static void genMult (iCode *ic)
3868 {
3869   operand *left = IC_LEFT(ic);
3870   operand *right = IC_RIGHT(ic);
3871   operand *result= IC_RESULT(ic);   
3872
3873         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3874         /* assign the amsops */
3875         pic16_aopOp (left,ic,FALSE);
3876         pic16_aopOp (right,ic,FALSE);
3877         pic16_aopOp (result,ic,TRUE);
3878
3879         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3880
3881         /* special cases first *
3882         * both are bits */
3883         if (AOP_TYPE(left) == AOP_CRY
3884                 && AOP_TYPE(right)== AOP_CRY) {
3885                 genMultbits(left,right,result);
3886           goto release ;
3887         }
3888
3889         /* if both are of size == 1 */
3890         if(AOP_SIZE(left) == 1
3891                 && AOP_SIZE(right) == 1) {
3892                 genMultOneByte(left,right,result);
3893           goto release ;
3894         }
3895
3896         /* if both are of size == 2 */
3897         if(AOP_SIZE(left) == 2
3898                 && AOP_SIZE(right) == 2) {
3899                 genMultOneWord(left, right, result);
3900           goto release;
3901         }
3902         
3903         /* if both are of size == 4 */
3904         if(AOP_SIZE(left) == 4
3905                 && AOP_SIZE(right) == 4) {
3906                 genMultOneLong(left, right, result);
3907           goto release;
3908         }
3909         
3910         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3911
3912
3913         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3914         /* should have been converted to function call */
3915         assert(0) ;
3916
3917 release :
3918         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3919         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3920         pic16_freeAsmop(result,NULL,ic,TRUE); 
3921 }
3922
3923 /*-----------------------------------------------------------------*/
3924 /* genDivbits :- division of bits                                  */
3925 /*-----------------------------------------------------------------*/
3926 static void genDivbits (operand *left, 
3927                         operand *right, 
3928                         operand *result)
3929 {
3930
3931     char *l;
3932
3933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3934     /* the result must be bit */    
3935     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3936     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3937
3938     MOVA(l);    
3939
3940     pic16_emitcode("div","ab");
3941     pic16_emitcode("rrc","a");
3942     pic16_aopPut(AOP(result),"c",0);
3943 }
3944
3945 /*-----------------------------------------------------------------*/
3946 /* genDivOneByte : 8 bit division                                  */
3947 /*-----------------------------------------------------------------*/
3948 static void genDivOneByte (operand *left,
3949                            operand *right,
3950                            operand *result)
3951 {
3952     sym_link *opetype = operandType(result);
3953     char *l ;
3954     symbol *lbl ;
3955     int size,offset;
3956
3957         /* result = divident / divisor
3958          * - divident may be a register or a literal,
3959          * - divisor may be a register or a literal,
3960          * so there are 3 cases (literal / literal is optimized
3961          * by the front-end) to handle.
3962          * In addition we must handle signed and unsigned, which
3963          * result in 6 final different cases -- VR */
3964
3965     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3966     size = AOP_SIZE(result) - 1;
3967     offset = 1;
3968     /* signed or unsigned */
3969     if (SPEC_USIGN(opetype)) {
3970       pCodeOp *pct1,    /* count */
3971                 *pct2,  /* reste */
3972                 *pct3;  /* temp */
3973       symbol *label1, *label2, *label3;;
3974
3975
3976         /* unsigned is easy */
3977
3978         pct1 = pic16_popGetTempReg();
3979         pct2 = pic16_popGetTempReg();
3980         pct3 = pic16_popGetTempReg();
3981         
3982         label1 = newiTempLabel(NULL);
3983         label2 = newiTempLabel(NULL);
3984         label3 = newiTempLabel(NULL);
3985
3986         /* the following algorithm is extracted from divuint.c */
3987
3988         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3989         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3990         
3991         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3992
3993         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3994         
3995         pic16_emitpLabel(label1->key);
3996         
3997         emitCLRC;
3998         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3999
4000
4001         emitCLRC;
4002         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4003         
4004
4005         emitSKPNC;
4006         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4007         
4008         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4009         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4010         
4011         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4012         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4013         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4014         
4015         pic16_emitpLabel( label3->key );
4016         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4017         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4018         
4019         
4020
4021         pic16_emitpLabel(label2->key);
4022         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4023         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4024         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4025         
4026         /* result is in wreg */
4027         if(AOP_TYPE(result) != AOP_ACC)
4028                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4029
4030         pic16_popReleaseTempReg( pct3 );
4031         pic16_popReleaseTempReg( pct2 );
4032         pic16_popReleaseTempReg( pct1 );
4033
4034         return ;
4035     }
4036
4037     /* signed is a little bit more difficult */
4038
4039     /* save the signs of the operands */
4040     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4041     MOVA(l);    
4042     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4043     pic16_emitcode("push","acc"); /* save it on the stack */
4044
4045     /* now sign adjust for both left & right */
4046     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4047     MOVA(l);       
4048     lbl = newiTempLabel(NULL);
4049     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4050     pic16_emitcode("cpl","a");   
4051     pic16_emitcode("inc","a");
4052     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4053     pic16_emitcode("mov","b,a");
4054
4055     /* sign adjust left side */
4056     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4057     MOVA(l);
4058
4059     lbl = newiTempLabel(NULL);
4060     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4061     pic16_emitcode("cpl","a");
4062     pic16_emitcode("inc","a");
4063     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4064
4065     /* now the division */
4066     pic16_emitcode("div","ab");
4067     /* we are interested in the lower order
4068     only */
4069     pic16_emitcode("mov","b,a");
4070     lbl = newiTempLabel(NULL);
4071     pic16_emitcode("pop","acc");   
4072     /* if there was an over flow we don't 
4073     adjust the sign of the result */
4074     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4075     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4076     CLRC;
4077     pic16_emitcode("clr","a");
4078     pic16_emitcode("subb","a,b");
4079     pic16_emitcode("mov","b,a");
4080     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4081
4082     /* now we are done */
4083     pic16_aopPut(AOP(result),"b",0);
4084     if(size > 0){
4085         pic16_emitcode("mov","c,b.7");
4086         pic16_emitcode("subb","a,acc");   
4087     }
4088     while (size--)
4089         pic16_aopPut(AOP(result),"a",offset++);
4090
4091 }
4092
4093 /*-----------------------------------------------------------------*/
4094 /* genDiv - generates code for division                            */
4095 /*-----------------------------------------------------------------*/
4096 static void genDiv (iCode *ic)
4097 {
4098     operand *left = IC_LEFT(ic);
4099     operand *right = IC_RIGHT(ic);
4100     operand *result= IC_RESULT(ic);   
4101
4102
4103         /* Division is a very lengthy algorithm, so it is better
4104          * to call support routines than inlining algorithm.
4105          * Division functions written here just in case someone
4106          * wants to inline and not use the support libraries -- VR */
4107
4108     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4109     /* assign the amsops */
4110     pic16_aopOp (left,ic,FALSE);
4111     pic16_aopOp (right,ic,FALSE);
4112     pic16_aopOp (result,ic,TRUE);
4113
4114     /* special cases first */
4115     /* both are bits */
4116     if (AOP_TYPE(left) == AOP_CRY &&
4117         AOP_TYPE(right)== AOP_CRY) {
4118         genDivbits(left,right,result);
4119         goto release ;
4120     }
4121
4122     /* if both are of size == 1 */
4123     if (AOP_SIZE(left) == 1 &&
4124         AOP_SIZE(right) == 1 ) {
4125         genDivOneByte(left,right,result);
4126         goto release ;
4127     }
4128
4129     /* should have been converted to function call */
4130     assert(0);
4131 release :
4132     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4133     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4134     pic16_freeAsmop(result,NULL,ic,TRUE); 
4135 }
4136
4137 /*-----------------------------------------------------------------*/
4138 /* genModbits :- modulus of bits                                   */
4139 /*-----------------------------------------------------------------*/
4140 static void genModbits (operand *left, 
4141                         operand *right, 
4142                         operand *result)
4143 {
4144
4145     char *l;
4146
4147     /* the result must be bit */    
4148     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4149     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4150
4151     MOVA(l);       
4152
4153     pic16_emitcode("div","ab");
4154     pic16_emitcode("mov","a,b");
4155     pic16_emitcode("rrc","a");
4156     pic16_aopPut(AOP(result),"c",0);
4157 }
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genModOneByte : 8 bit modulus                                   */
4161 /*-----------------------------------------------------------------*/
4162 static void genModOneByte (operand *left,
4163                            operand *right,
4164                            operand *result)
4165 {
4166     sym_link *opetype = operandType(result);
4167     char *l ;
4168     symbol *lbl ;
4169
4170     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4171     /* signed or unsigned */
4172     if (SPEC_USIGN(opetype)) {
4173         /* unsigned is easy */
4174         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4175         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4176         MOVA(l);    
4177         pic16_emitcode("div","ab");
4178         pic16_aopPut(AOP(result),"b",0);
4179         return ;
4180     }
4181
4182     /* signed is a little bit more difficult */
4183
4184     /* save the signs of the operands */
4185     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4186     MOVA(l);
4187
4188     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4189     pic16_emitcode("push","acc"); /* save it on the stack */
4190
4191     /* now sign adjust for both left & right */
4192     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4193     MOVA(l);
4194
4195     lbl = newiTempLabel(NULL);
4196     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4197     pic16_emitcode("cpl","a");   
4198     pic16_emitcode("inc","a");
4199     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4200     pic16_emitcode("mov","b,a"); 
4201
4202     /* sign adjust left side */
4203     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4204     MOVA(l);
4205
4206     lbl = newiTempLabel(NULL);
4207     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4208     pic16_emitcode("cpl","a");   
4209     pic16_emitcode("inc","a");
4210     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4211
4212     /* now the multiplication */
4213     pic16_emitcode("div","ab");
4214     /* we are interested in the lower order
4215     only */
4216     lbl = newiTempLabel(NULL);
4217     pic16_emitcode("pop","acc");   
4218     /* if there was an over flow we don't 
4219     adjust the sign of the result */
4220     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4221     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4222     CLRC ;
4223     pic16_emitcode("clr","a");
4224     pic16_emitcode("subb","a,b");
4225     pic16_emitcode("mov","b,a");
4226     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4227
4228     /* now we are done */
4229     pic16_aopPut(AOP(result),"b",0);
4230
4231 }
4232
4233 /*-----------------------------------------------------------------*/
4234 /* genMod - generates code for division                            */
4235 /*-----------------------------------------------------------------*/
4236 static void genMod (iCode *ic)
4237 {
4238     operand *left = IC_LEFT(ic);
4239     operand *right = IC_RIGHT(ic);
4240     operand *result= IC_RESULT(ic);  
4241
4242     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4243     /* assign the amsops */
4244     pic16_aopOp (left,ic,FALSE);
4245     pic16_aopOp (right,ic,FALSE);
4246     pic16_aopOp (result,ic,TRUE);
4247
4248     /* special cases first */
4249     /* both are bits */
4250     if (AOP_TYPE(left) == AOP_CRY &&
4251         AOP_TYPE(right)== AOP_CRY) {
4252         genModbits(left,right,result);
4253         goto release ;
4254     }
4255
4256     /* if both are of size == 1 */
4257     if (AOP_SIZE(left) == 1 &&
4258         AOP_SIZE(right) == 1 ) {
4259         genModOneByte(left,right,result);
4260         goto release ;
4261     }
4262
4263     /* should have been converted to function call */
4264     assert(0);
4265
4266 release :
4267     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4268     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4269     pic16_freeAsmop(result,NULL,ic,TRUE); 
4270 }
4271
4272 /*-----------------------------------------------------------------*/
4273 /* genIfxJump :- will create a jump depending on the ifx           */
4274 /*-----------------------------------------------------------------*/
4275 /*
4276   note: May need to add parameter to indicate when a variable is in bit space.
4277 */
4278 static void genIfxJump (iCode *ic, char *jval)
4279 {
4280
4281     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4282     /* if true label then we jump if condition
4283     supplied is true */
4284     if ( IC_TRUE(ic) ) {
4285
4286         if(strcmp(jval,"a") == 0)
4287           emitSKPZ;
4288         else if (strcmp(jval,"c") == 0)
4289           emitSKPC;
4290         else {
4291           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4292           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4293         }
4294
4295         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4296         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4297
4298     }
4299     else {
4300         /* false label is present */
4301         if(strcmp(jval,"a") == 0)
4302           emitSKPNZ;
4303         else if (strcmp(jval,"c") == 0)
4304           emitSKPNC;
4305         else {
4306           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4307           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4308         }
4309
4310         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4311         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4312
4313     }
4314
4315
4316     /* mark the icode as generated */
4317     ic->generated = 1;
4318 }
4319
4320 #if 0
4321 // not needed ATM
4322
4323 /*-----------------------------------------------------------------*/
4324 /* genSkip                                                         */
4325 /*-----------------------------------------------------------------*/
4326 static void genSkip(iCode *ifx,int status_bit)
4327 {
4328   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4329   if(!ifx)
4330     return;
4331
4332   if ( IC_TRUE(ifx) ) {
4333     switch(status_bit) {
4334     case 'z':
4335       emitSKPNZ;
4336       break;
4337
4338     case 'c':
4339       emitSKPNC;
4340       break;
4341
4342     case 'd':
4343       emitSKPDC;
4344       break;
4345
4346     }
4347
4348     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4349     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4350
4351   } else {
4352
4353     switch(status_bit) {
4354
4355     case 'z':
4356       emitSKPZ;
4357       break;
4358
4359     case 'c':
4360       emitSKPC;
4361       break;
4362
4363     case 'd':
4364       emitSKPDC;
4365       break;
4366     }
4367     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4368     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4369
4370   }
4371
4372 }
4373 #endif
4374
4375 /*-----------------------------------------------------------------*/
4376 /* genSkipc                                                        */
4377 /*-----------------------------------------------------------------*/
4378 static void genSkipc(resolvedIfx *rifx)
4379 {
4380   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4381   
4382   if(!rifx)
4383     return;
4384
4385   if(rifx->condition)
4386     emitSKPC;
4387   else
4388     emitSKPNC;
4389
4390   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4391   rifx->generated = 1;
4392 }
4393
4394 /*-----------------------------------------------------------------*/
4395 /* genSkipz2                                                       */
4396 /*-----------------------------------------------------------------*/
4397 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4398 {
4399   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4400   
4401   if(!rifx)
4402     return;
4403
4404   if( (rifx->condition ^ invert_condition) & 1)
4405     emitSKPZ;
4406   else
4407     emitSKPNZ;
4408
4409   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4410   rifx->generated = 1;
4411 }
4412
4413 #if 0
4414 /*-----------------------------------------------------------------*/
4415 /* genSkipz                                                        */
4416 /*-----------------------------------------------------------------*/
4417 static void genSkipz(iCode *ifx, int condition)
4418 {
4419   if(!ifx)
4420     return;
4421
4422   if(condition)
4423     emitSKPNZ;
4424   else
4425     emitSKPZ;
4426
4427   if ( IC_TRUE(ifx) )
4428     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4429   else
4430     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4431
4432   if ( IC_TRUE(ifx) )
4433     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4434   else
4435     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4436
4437 }
4438 #endif
4439
4440 /*-----------------------------------------------------------------*/
4441 /* genSkipCond                                                     */
4442 /*-----------------------------------------------------------------*/
4443 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4444 {
4445   if(!rifx)
4446     return;
4447
4448   if(rifx->condition)
4449     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4450   else
4451     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4452
4453
4454   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4455   rifx->generated = 1;
4456 }
4457
4458 #if 0
4459 /*-----------------------------------------------------------------*/
4460 /* genChkZeroes :- greater or less than comparison                 */
4461 /*     For each byte in a literal that is zero, inclusive or the   */
4462 /*     the corresponding byte in the operand with W                */
4463 /*     returns true if any of the bytes are zero                   */
4464 /*-----------------------------------------------------------------*/
4465 static int genChkZeroes(operand *op, int lit,  int size)
4466 {
4467
4468   int i;
4469   int flag =1;
4470
4471   while(size--) {
4472     i = (lit >> (size*8)) & 0xff;
4473
4474     if(i==0) {
4475       if(flag) 
4476         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4477       else
4478         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4479       flag = 0;
4480     }
4481   }
4482
4483   return (flag==0);
4484 }
4485 #endif
4486
4487 /*-----------------------------------------------------------------*/
4488 /* genCmp :- greater or less than comparison                       */
4489 /*-----------------------------------------------------------------*/
4490 static void genCmp (operand *left,operand *right,
4491                     operand *result, iCode *ifx, int sign)
4492 {
4493   int size; //, offset = 0 ;
4494   unsigned long lit = 0L,i = 0;
4495   resolvedIfx rFalseIfx;
4496   //  resolvedIfx rTrueIfx;
4497   symbol *truelbl;
4498   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4499 /*
4500   if(ifx) {
4501     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4502     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4503   }
4504 */
4505
4506   resolveIfx(&rFalseIfx,ifx);
4507   truelbl  = newiTempLabel(NULL);
4508   size = max(AOP_SIZE(left),AOP_SIZE(right));
4509
4510   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4511
4512 #define _swapp
4513
4514   /* if literal is on the right then swap with left */
4515   if ((AOP_TYPE(right) == AOP_LIT)) {
4516     operand *tmp = right ;
4517     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4518     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4519 #ifdef _swapp
4520
4521     lit = (lit - 1) & mask;
4522     right = left;
4523     left = tmp;
4524     rFalseIfx.condition ^= 1;
4525 #endif
4526
4527   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4528     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4529   }
4530
4531
4532   //if(IC_TRUE(ifx) == NULL)
4533   /* if left & right are bit variables */
4534   if (AOP_TYPE(left) == AOP_CRY &&
4535       AOP_TYPE(right) == AOP_CRY ) {
4536     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4537     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4538   } else {
4539     /* subtract right from left if at the
4540        end the carry flag is set then we know that
4541        left is greater than right */
4542
4543     symbol *lbl  = newiTempLabel(NULL);
4544
4545 #if 0
4546         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4547                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4548 #endif
4549
4550 #ifndef _swapp
4551     if(AOP_TYPE(right) == AOP_LIT) {
4552
4553       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4554
4555       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4556
4557       /* special cases */
4558
4559       if(lit == 0) {
4560
4561         if(sign != 0) 
4562           genSkipCond(&rFalseIfx,left,size-1,7);
4563         else 
4564           /* no need to compare to 0...*/
4565           /* NOTE: this is a de-generate compare that most certainly 
4566            *       creates some dead code. */
4567           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4568
4569         if(ifx) ifx->generated = 1;
4570         return;
4571
4572       }
4573       size--;
4574
4575       if(size == 0) {
4576         //i = (lit >> (size*8)) & 0xff;
4577         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4578         
4579         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4580
4581         i = ((0-lit) & 0xff);
4582         if(sign) {
4583           if( i == 0x81) { 
4584             /* lit is 0x7f, all signed chars are less than
4585              * this except for 0x7f itself */
4586             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4587             genSkipz2(&rFalseIfx,0);
4588           } else {
4589             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4590             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4591             genSkipc(&rFalseIfx);
4592           }
4593
4594         } else {
4595           if(lit == 1) {
4596             genSkipz2(&rFalseIfx,1);
4597           } else {
4598             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4599             genSkipc(&rFalseIfx);
4600           }
4601         }
4602
4603         if(ifx) ifx->generated = 1;
4604         return;
4605       }
4606
4607       /* chars are out of the way. now do ints and longs */
4608
4609
4610       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4611         
4612       /* special cases */
4613
4614       if(sign) {
4615
4616         if(lit == 0) {
4617           genSkipCond(&rFalseIfx,left,size,7);
4618           if(ifx) ifx->generated = 1;
4619           return;
4620         }
4621
4622         if(lit <0x100) {
4623           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4624
4625           //rFalseIfx.condition ^= 1;
4626           //genSkipCond(&rFalseIfx,left,size,7);
4627           //rFalseIfx.condition ^= 1;
4628
4629           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4630           if(rFalseIfx.condition)
4631             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4632           else
4633             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4634
4635           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4636           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4637           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4638
4639           while(size > 1)
4640             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4641
4642           if(rFalseIfx.condition) {
4643             emitSKPZ;
4644             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4645
4646           } else {
4647             emitSKPNZ;
4648           }
4649
4650           genSkipc(&rFalseIfx);
4651           pic16_emitpLabel(truelbl->key);
4652           if(ifx) ifx->generated = 1;
4653           return;
4654
4655         }
4656
4657         if(size == 1) {
4658
4659           if( (lit & 0xff) == 0) {
4660             /* lower byte is zero */
4661             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4662             i = ((lit >> 8) & 0xff) ^0x80;
4663             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4664             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4665             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4666             genSkipc(&rFalseIfx);
4667
4668
4669             if(ifx) ifx->generated = 1;
4670             return;
4671
4672           }
4673         } else {
4674           /* Special cases for signed longs */
4675           if( (lit & 0xffffff) == 0) {
4676             /* lower byte is zero */
4677             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4678             i = ((lit >> 8*3) & 0xff) ^0x80;
4679             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4680             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4681             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4682             genSkipc(&rFalseIfx);
4683
4684
4685             if(ifx) ifx->generated = 1;
4686             return;
4687
4688           }
4689
4690         }
4691
4692
4693         if(lit & (0x80 << (size*8))) {
4694           /* lit is negative */
4695           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4696
4697           //genSkipCond(&rFalseIfx,left,size,7);
4698
4699           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4700
4701           if(rFalseIfx.condition)
4702             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4703           else
4704             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4705
4706
4707         } else {
4708           /* lit is positive */
4709           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4710           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4711           if(rFalseIfx.condition)
4712             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4713           else
4714             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4715
4716         }
4717
4718         /*
4719           This works, but is only good for ints.
4720           It also requires a "known zero" register.
4721           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4722           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4723           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4724           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4725           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4726           genSkipc(&rFalseIfx);
4727
4728           pic16_emitpLabel(truelbl->key);
4729           if(ifx) ifx->generated = 1;
4730           return;
4731         **/
4732           
4733         /* There are no more special cases, so perform a general compare */
4734   
4735         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4736         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4737
4738         while(size--) {
4739
4740           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4741           emitSKPNZ;
4742           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4743         }
4744         //rFalseIfx.condition ^= 1;
4745         genSkipc(&rFalseIfx);
4746
4747         pic16_emitpLabel(truelbl->key);
4748
4749         if(ifx) ifx->generated = 1;
4750         return;
4751
4752
4753       }
4754
4755
4756       /* sign is out of the way. So now do an unsigned compare */
4757       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4758
4759
4760       /* General case - compare to an unsigned literal on the right.*/
4761
4762       i = (lit >> (size*8)) & 0xff;
4763       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4764       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4765       while(size--) {
4766         i = (lit >> (size*8)) & 0xff;
4767
4768         if(i) {
4769           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4770           emitSKPNZ;
4771           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4772         } else {
4773           /* this byte of the lit is zero, 
4774            *if it's not the last then OR in the variable */
4775           if(size)
4776             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4777         }
4778       }
4779
4780
4781       pic16_emitpLabel(lbl->key);
4782 //      pic16_emitpLabel(truelbl->key);
4783       //if(emitFinalCheck)
4784       genSkipc(&rFalseIfx);
4785       if(sign)
4786         pic16_emitpLabel(truelbl->key);
4787
4788       if(ifx) ifx->generated = 1;
4789       return;
4790
4791
4792     }
4793 #endif  // _swapp
4794
4795     if(AOP_TYPE(left) == AOP_LIT) {
4796       //symbol *lbl = newiTempLabel(NULL);
4797
4798       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4799
4800
4801       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4802
4803       /* Special cases */
4804       if((lit == 0) && (sign == 0)){
4805
4806         size--;
4807         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4808         while(size) 
4809           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4810
4811         genSkipz2(&rFalseIfx,0);
4812         if(ifx) ifx->generated = 1;
4813         return;
4814       }
4815
4816       if(size==1) {
4817         /* Special cases */
4818         lit &= 0xff;
4819         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4820           /* degenerate compare can never be true */
4821           if(rFalseIfx.condition == 0)
4822             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4823
4824           if(ifx) ifx->generated = 1;
4825           return;
4826         }
4827
4828         if(sign) {
4829           /* signed comparisons to a literal byte */
4830
4831           int lp1 = (lit+1) & 0xff;
4832
4833           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4834           switch (lp1) {
4835           case 0:
4836             rFalseIfx.condition ^= 1;
4837             genSkipCond(&rFalseIfx,right,0,7);
4838             break;
4839           case 0x7f:
4840             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4841             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4842             genSkipz2(&rFalseIfx,1);
4843             break;
4844           default:
4845             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4846             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4847             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4848             rFalseIfx.condition ^= 1;
4849             genSkipc(&rFalseIfx);
4850             break;
4851           }
4852         } else {
4853           /* unsigned comparisons to a literal byte */
4854
4855           switch(lit & 0xff ) {
4856           case 0:
4857             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4858             genSkipz2(&rFalseIfx,0);
4859             break;
4860           case 0x7f:
4861             rFalseIfx.condition ^= 1;
4862             genSkipCond(&rFalseIfx,right,0,7);
4863             break;
4864
4865           default:
4866             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4867             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4868             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4869             rFalseIfx.condition ^= 1;
4870             if (AOP_TYPE(result) == AOP_CRY)
4871               genSkipc(&rFalseIfx);
4872             else {
4873               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4874               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4875             }         
4876             break;
4877           }
4878         }
4879
4880         if(ifx) ifx->generated = 1;
4881         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4882                 goto check_carry;
4883         return;
4884
4885       } else {
4886
4887         /* Size is greater than 1 */
4888
4889         if(sign) {
4890           int lp1 = lit+1;
4891
4892           size--;
4893
4894           if(lp1 == 0) {
4895             /* this means lit = 0xffffffff, or -1 */
4896
4897
4898             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4899             rFalseIfx.condition ^= 1;
4900             genSkipCond(&rFalseIfx,right,size,7);
4901             if(ifx) ifx->generated = 1;
4902             return;
4903           }
4904
4905           if(lit == 0) {
4906             int s = size;
4907
4908             if(rFalseIfx.condition) {
4909               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4910               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4911             }
4912
4913             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4914             while(size--)
4915               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4916
4917
4918             emitSKPZ;
4919             if(rFalseIfx.condition) {
4920               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4921               pic16_emitpLabel(truelbl->key);
4922             }else {
4923               rFalseIfx.condition ^= 1;
4924               genSkipCond(&rFalseIfx,right,s,7);
4925             }
4926
4927             if(ifx) ifx->generated = 1;
4928             return;
4929           }
4930
4931           if((size == 1) &&  (0 == (lp1&0xff))) {
4932             /* lower byte of signed word is zero */
4933             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4934             i = ((lp1 >> 8) & 0xff) ^0x80;
4935             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4936             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4937             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4938             rFalseIfx.condition ^= 1;
4939             genSkipc(&rFalseIfx);
4940
4941
4942             if(ifx) ifx->generated = 1;
4943             return;
4944           }
4945
4946           if(lit & (0x80 << (size*8))) {
4947             /* Lit is less than zero */
4948             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4949             //rFalseIfx.condition ^= 1;
4950             //genSkipCond(&rFalseIfx,left,size,7);
4951             //rFalseIfx.condition ^= 1;
4952             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4953             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4954
4955             if(rFalseIfx.condition)
4956               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4957             else
4958               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4959
4960
4961           } else {
4962             /* Lit is greater than or equal to zero */
4963             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4964             //rFalseIfx.condition ^= 1;
4965             //genSkipCond(&rFalseIfx,right,size,7);
4966             //rFalseIfx.condition ^= 1;
4967
4968             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4969             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4970
4971             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4972             if(rFalseIfx.condition)
4973               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4974             else
4975               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4976
4977           }
4978
4979
4980           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4981           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4982
4983           while(size--) {
4984
4985             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4986             emitSKPNZ;
4987             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4988           }
4989           rFalseIfx.condition ^= 1;
4990           //rFalseIfx.condition = 1;
4991           genSkipc(&rFalseIfx);
4992
4993           pic16_emitpLabel(truelbl->key);
4994
4995           if(ifx) ifx->generated = 1;
4996           return;
4997           // end of if (sign)
4998         } else {
4999
5000           /* compare word or long to an unsigned literal on the right.*/
5001
5002
5003           size--;
5004           if(lit < 0xff) {
5005             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5006             switch (lit) {
5007             case 0:
5008               break; /* handled above */
5009 /*
5010             case 0xff:
5011               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5012               while(size--)
5013                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5014               genSkipz2(&rFalseIfx,0);
5015               break;
5016 */
5017             default:
5018               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5019               while(--size)
5020                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5021
5022               emitSKPZ;
5023               if(rFalseIfx.condition)
5024                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5025               else
5026                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5027
5028
5029               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5030               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5031
5032               rFalseIfx.condition ^= 1;
5033               genSkipc(&rFalseIfx);
5034             }
5035
5036             pic16_emitpLabel(truelbl->key);
5037
5038             if(ifx) ifx->generated = 1;
5039             return;
5040           }
5041
5042
5043           lit++;
5044           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5045           i = (lit >> (size*8)) & 0xff;
5046
5047           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5048           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5049
5050           while(size--) {
5051             i = (lit >> (size*8)) & 0xff;
5052
5053             if(i) {
5054               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5055               emitSKPNZ;
5056               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5057             } else {
5058               /* this byte of the lit is zero, 
5059                * if it's not the last then OR in the variable */
5060               if(size)
5061                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5062             }
5063           }
5064
5065
5066           pic16_emitpLabel(lbl->key);
5067
5068           rFalseIfx.condition ^= 1;
5069
5070           genSkipc(&rFalseIfx);
5071         }
5072
5073         if(sign)
5074           pic16_emitpLabel(truelbl->key);
5075         if(ifx) ifx->generated = 1;
5076         return;
5077       }
5078     }
5079     /* Compare two variables */
5080
5081     DEBUGpic16_emitcode(";sign","%d",sign);
5082
5083     size--;
5084     if(sign) {
5085       /* Sigh. thus sucks... */
5086       if(size) {
5087         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5088         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5089         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5090         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5091         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5092         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5093       } else {
5094         /* Signed char comparison */
5095         /* Special thanks to Nikolai Golovchenko for this snippet */
5096         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5097         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5098         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5099         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5100         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5101         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5102
5103         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5104         genSkipc(&rFalseIfx);
5105           
5106         if(ifx) ifx->generated = 1;
5107         return;
5108       }
5109
5110     } else {
5111
5112       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5113       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5114     }
5115
5116
5117     /* The rest of the bytes of a multi-byte compare */
5118     while (size) {
5119
5120       emitSKPZ;
5121       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5122       size--;
5123
5124       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5125       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5126
5127
5128     }
5129
5130     pic16_emitpLabel(lbl->key);
5131
5132     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5133     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5134         (AOP_TYPE(result) == AOP_REG)) {
5135       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5136       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5137     } else {
5138       genSkipc(&rFalseIfx);
5139     }         
5140     //genSkipc(&rFalseIfx);
5141     if(ifx) ifx->generated = 1;
5142
5143     return;
5144
5145   }
5146
5147 check_carry:
5148   if ((AOP_TYPE(result) != AOP_CRY) 
5149         && AOP_SIZE(result)) {
5150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5151 //    pic16_emitpLabel( rFalseIfx.lbl->key );
5152
5153     pic16_outBitC(result);
5154   } else {
5155     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5156     /* if the result is used in the next
5157        ifx conditional branch then generate
5158        code a little differently */
5159     if (ifx )
5160       genIfxJump (ifx,"c");
5161     else
5162       pic16_outBitC(result);
5163     /* leave the result in acc */
5164   }
5165
5166 }
5167
5168 /*-----------------------------------------------------------------*/
5169 /* genCmpGt :- greater than comparison                             */
5170 /*-----------------------------------------------------------------*/
5171 static void genCmpGt (iCode *ic, iCode *ifx)
5172 {
5173     operand *left, *right, *result;
5174     sym_link *letype , *retype;
5175     int sign ;
5176
5177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5178     left = IC_LEFT(ic);
5179     right= IC_RIGHT(ic);
5180     result = IC_RESULT(ic);
5181
5182     letype = getSpec(operandType(left));
5183     retype =getSpec(operandType(right));
5184     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5185     /* assign the amsops */
5186     pic16_aopOp (left,ic,FALSE);
5187     pic16_aopOp (right,ic,FALSE);
5188     pic16_aopOp (result,ic,TRUE);
5189
5190     genCmp(right, left, result, ifx, sign);
5191
5192     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5193     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5194     pic16_freeAsmop(result,NULL,ic,TRUE); 
5195 }
5196
5197 /*-----------------------------------------------------------------*/
5198 /* genCmpLt - less than comparisons                                */
5199 /*-----------------------------------------------------------------*/
5200 static void genCmpLt (iCode *ic, iCode *ifx)
5201 {
5202     operand *left, *right, *result;
5203     sym_link *letype , *retype;
5204     int sign ;
5205
5206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5207     left = IC_LEFT(ic);
5208     right= IC_RIGHT(ic);
5209     result = IC_RESULT(ic);
5210
5211     letype = getSpec(operandType(left));
5212     retype =getSpec(operandType(right));
5213     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5214
5215     /* assign the amsops */
5216     pic16_aopOp (left,ic,FALSE);
5217     pic16_aopOp (right,ic,FALSE);
5218     pic16_aopOp (result,ic,TRUE);
5219
5220     genCmp(left, right, result, ifx, sign);
5221
5222     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5223     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5224     pic16_freeAsmop(result,NULL,ic,TRUE); 
5225 }
5226
5227 #if 0
5228 // not needed ATM
5229 // FIXME reenable literal optimisation when the pic16 port is stable
5230
5231 /*-----------------------------------------------------------------*/
5232 /* genc16bit2lit - compare a 16 bit value to a literal             */
5233 /*-----------------------------------------------------------------*/
5234 static void genc16bit2lit(operand *op, int lit, int offset)
5235 {
5236   int i;
5237
5238   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5239   if( (lit&0xff) == 0) 
5240     i=1;
5241   else
5242     i=0;
5243
5244   switch( BYTEofLONG(lit,i)) { 
5245   case 0:
5246     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5247     break;
5248   case 1:
5249     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5250     break;
5251   case 0xff:
5252     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5253     break;
5254   default:
5255     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5256     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5257   }
5258
5259   i ^= 1;
5260
5261   switch( BYTEofLONG(lit,i)) { 
5262   case 0:
5263     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5264     break;
5265   case 1:
5266     emitSKPNZ;
5267     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5268     break;
5269   case 0xff:
5270     emitSKPNZ;
5271     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5272     break;
5273   default:
5274     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5275     emitSKPNZ;
5276     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5277
5278   }
5279
5280 }
5281 #endif
5282
5283 #if 0
5284 // not needed ATM
5285 /*-----------------------------------------------------------------*/
5286 /* gencjneshort - compare and jump if not equal                    */
5287 /*-----------------------------------------------------------------*/
5288 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5289 {
5290   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5291   int offset = 0;
5292   int res_offset = 0;  /* the result may be a different size then left or right */
5293   int res_size = AOP_SIZE(result);
5294   resolvedIfx rIfx;
5295   symbol *lbl, *lbl_done;
5296
5297   unsigned long lit = 0L;
5298   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5299
5300   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5301   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5302   if(result)
5303     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5304   resolveIfx(&rIfx,ifx);
5305   lbl =  newiTempLabel(NULL);
5306   lbl_done =  newiTempLabel(NULL);
5307
5308
5309   /* if the left side is a literal or 
5310      if the right is in a pointer register and left 
5311      is not */
5312   if ((AOP_TYPE(left) == AOP_LIT) || 
5313       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5314     operand *t = right;
5315     right = left;
5316     left = t;
5317   }
5318   if(AOP_TYPE(right) == AOP_LIT)
5319     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5320
5321   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5322     preserve_result = 1;
5323
5324   if(result && !preserve_result)
5325     {
5326       int i;
5327       for(i = 0; i < AOP_SIZE(result); i++)
5328         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5329     }
5330
5331
5332   /* if the right side is a literal then anything goes */
5333   if (AOP_TYPE(right) == AOP_LIT &&
5334       AOP_TYPE(left) != AOP_DIR ) {
5335     switch(size) {
5336     case 2:
5337       genc16bit2lit(left, lit, 0);
5338       emitSKPZ;
5339       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5340       break;
5341     default:
5342       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5343       while (size--) {
5344         if(lit & 0xff) {
5345           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5346           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5347         } else {
5348           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5349         }
5350
5351         emitSKPZ;
5352         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5353         offset++;
5354         if(res_offset < res_size-1)
5355           res_offset++;
5356         lit >>= 8;
5357       }
5358       break;
5359     }
5360   }
5361
5362   /* if the right side is in a register or in direct space or
5363      if the left is a pointer register & right is not */    
5364   else if (AOP_TYPE(right) == AOP_REG ||
5365            AOP_TYPE(right) == AOP_DIR || 
5366            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5367            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5368     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5369     int lbl_key = lbl->key;
5370
5371     if(result) {
5372       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5373       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5374     }else {
5375       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5376       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5377               __FUNCTION__,__LINE__);
5378       return;
5379     }
5380    
5381 /*     switch(size) { */
5382 /*     case 2: */
5383 /*       genc16bit2lit(left, lit, 0); */
5384 /*       emitSKPNZ; */
5385 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5386 /*       break; */
5387 /*     default: */
5388     while (size--) {
5389       int emit_skip=1;
5390       if((AOP_TYPE(left) == AOP_DIR) && 
5391          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5392
5393         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5394         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5395
5396       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5397             
5398         switch (lit & 0xff) {
5399         case 0:
5400           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5401           break;
5402         case 1:
5403           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5404           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5405           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5406           emit_skip=0;
5407           break;
5408         case 0xff:
5409           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5410           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5411           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5412           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5413           emit_skip=0;
5414           break;
5415         default:
5416           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5417           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5418         }
5419         lit >>= 8;
5420
5421       } else {
5422         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5423       }
5424       if(emit_skip) {
5425         if(AOP_TYPE(result) == AOP_CRY) {
5426           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5427           if(rIfx.condition)
5428             emitSKPNZ;
5429           else
5430             emitSKPZ;
5431           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5432         } else {
5433           /* fix me. probably need to check result size too */
5434           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5435           if(rIfx.condition)
5436             emitSKPZ;
5437           else
5438             emitSKPNZ;
5439           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5440           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5441         }
5442         if(ifx)
5443           ifx->generated=1;
5444       }
5445       emit_skip++;
5446       offset++;
5447       if(res_offset < res_size-1)
5448         res_offset++;
5449     }
5450 /*       break; */
5451 /*     } */
5452   } else if(AOP_TYPE(right) == AOP_REG &&
5453             AOP_TYPE(left) != AOP_DIR){
5454
5455     while(size--) {
5456       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5457       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5458       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5459       if(rIfx.condition)
5460         emitSKPNZ;
5461       else
5462         emitSKPZ;
5463       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5464       offset++;
5465       if(res_offset < res_size-1)
5466         res_offset++;
5467     }
5468       
5469   }else{
5470     /* right is a pointer reg need both a & b */
5471     while(size--) {
5472       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5473       if(strcmp(l,"b"))
5474         pic16_emitcode("mov","b,%s",l);
5475       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5476       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5477       offset++;
5478     }
5479   }
5480
5481   if(result && preserve_result)
5482     {
5483       int i;
5484       for(i = 0; i < AOP_SIZE(result); i++)
5485         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5486     }
5487
5488   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5489
5490   if(result && preserve_result)
5491     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5492
5493   if(!rIfx.condition)
5494     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5495
5496   pic16_emitpLabel(lbl->key);
5497
5498   if(result && preserve_result)
5499     {
5500       int i;
5501       for(i = 0; i < AOP_SIZE(result); i++)
5502         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5503
5504       pic16_emitpLabel(lbl_done->key);
5505    }
5506
5507   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5508
5509   if(ifx)
5510     ifx->generated = 1;
5511 }
5512 #endif
5513
5514 #if 0
5515 /*-----------------------------------------------------------------*/
5516 /* gencjne - compare and jump if not equal                         */
5517 /*-----------------------------------------------------------------*/
5518 static void gencjne(operand *left, operand *right, iCode *ifx)
5519 {
5520     symbol *tlbl  = newiTempLabel(NULL);
5521
5522     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5523     gencjneshort(left, right, lbl);
5524
5525     pic16_emitcode("mov","a,%s",one);
5526     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5527     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5528     pic16_emitcode("clr","a");
5529     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5530
5531     pic16_emitpLabel(lbl->key);
5532     pic16_emitpLabel(tlbl->key);
5533
5534 }
5535 #endif
5536
5537
5538 /*-----------------------------------------------------------------*/
5539 /* is_LitOp - check if operand has to be treated as literal        */
5540 /*-----------------------------------------------------------------*/
5541 static bool is_LitOp(operand *op)
5542 {
5543   return (AOP_TYPE(op) == AOP_LIT)
5544       || ( (AOP_TYPE(op) == AOP_PCODE)
5545           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5546               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5547 }
5548
5549 /*-----------------------------------------------------------------*/
5550 /* is_LitAOp - check if operand has to be treated as literal        */
5551 /*-----------------------------------------------------------------*/
5552 static bool is_LitAOp(asmop *aop)
5553 {
5554   return (aop->type == AOP_LIT)
5555       || ( (aop->type == AOP_PCODE)
5556           && ( (aop->aopu.pcop->type == PO_LITERAL)
5557               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5558 }
5559
5560
5561
5562 /*-----------------------------------------------------------------*/
5563 /* genCmpEq - generates code for equal to                          */
5564 /*-----------------------------------------------------------------*/
5565 static void genCmpEq (iCode *ic, iCode *ifx)
5566 {
5567   operand *left, *right, *result;
5568   symbol *falselbl = newiTempLabel(NULL);
5569   symbol *donelbl = newiTempLabel(NULL);
5570
5571   int preserve_result = 0;
5572   int generate_result = 0;
5573   int i=0;
5574
5575   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5576   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5577   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5578  
5579   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5580   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5581
5582   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5583     {
5584       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5585       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5586       goto release;
5587     }
5588
5589   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5590     {
5591       operand *tmp = right ;
5592       right = left;
5593       left = tmp;
5594     }
5595
5596   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5597     preserve_result = 1;
5598
5599   if(result && AOP_SIZE(result))
5600     generate_result = 1;
5601
5602   if(generate_result && !preserve_result)
5603     {
5604       for(i = 0; i < AOP_SIZE(result); i++)
5605         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5606     }
5607
5608   for(i=0; i < AOP_SIZE(left); i++)
5609     {
5610       if(AOP_TYPE(left) != AOP_ACC)
5611         {
5612           if(is_LitOp(left))
5613             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5614           else
5615             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5616         }
5617       if(is_LitOp(right))
5618         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5619       else
5620         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5621
5622       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5623     }
5624
5625   // result == true
5626
5627   if(generate_result && preserve_result)
5628     {
5629       for(i = 0; i < AOP_SIZE(result); i++)
5630         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5631     }
5632
5633   if(generate_result)
5634     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5635
5636   if(generate_result && preserve_result)
5637     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5638
5639   if(ifx && IC_TRUE(ifx))
5640     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5641
5642   if(ifx && IC_FALSE(ifx))
5643     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5644
5645   pic16_emitpLabel(falselbl->key);
5646
5647   // result == false
5648
5649   if(ifx && IC_FALSE(ifx))
5650     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5651
5652   if(generate_result && preserve_result)
5653     {
5654       for(i = 0; i < AOP_SIZE(result); i++)
5655         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5656     }
5657
5658   pic16_emitpLabel(donelbl->key);
5659
5660   if(ifx)
5661     ifx->generated = 1;
5662
5663 release:
5664   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5665   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5666   pic16_freeAsmop(result,NULL,ic,TRUE);
5667
5668 }
5669
5670
5671 #if 0
5672 // old version kept for reference
5673
5674 /*-----------------------------------------------------------------*/
5675 /* genCmpEq - generates code for equal to                          */
5676 /*-----------------------------------------------------------------*/
5677 static void genCmpEq (iCode *ic, iCode *ifx)
5678 {
5679     operand *left, *right, *result;
5680     unsigned long lit = 0L;
5681     int size,offset=0;
5682     symbol *falselbl  = newiTempLabel(NULL);
5683
5684
5685     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5686
5687     if(ifx)
5688       DEBUGpic16_emitcode ("; ifx is non-null","");
5689     else
5690       DEBUGpic16_emitcode ("; ifx is null","");
5691
5692     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5693     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5694     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5695
5696     size = max(AOP_SIZE(left),AOP_SIZE(right));
5697
5698     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5699
5700     /* if literal, literal on the right or 
5701     if the right is in a pointer register and left 
5702     is not */
5703     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5704         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5705       operand *tmp = right ;
5706       right = left;
5707       left = tmp;
5708     }
5709
5710
5711     if(ifx && !AOP_SIZE(result)){
5712         symbol *tlbl;
5713         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5714         /* if they are both bit variables */
5715         if (AOP_TYPE(left) == AOP_CRY &&
5716             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5717                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5718             if(AOP_TYPE(right) == AOP_LIT){
5719                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5720                 if(lit == 0L){
5721                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5722                     pic16_emitcode("cpl","c");
5723                 } else if(lit == 1L) {
5724                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5725                 } else {
5726                     pic16_emitcode("clr","c");
5727                 }
5728                 /* AOP_TYPE(right) == AOP_CRY */
5729             } else {
5730                 symbol *lbl = newiTempLabel(NULL);
5731                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5732                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5733                 pic16_emitcode("cpl","c");
5734                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5735             }
5736             /* if true label then we jump if condition
5737             supplied is true */
5738             tlbl = newiTempLabel(NULL);
5739             if ( IC_TRUE(ifx) ) {
5740                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5741                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5742             } else {
5743                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5744                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5745             }
5746             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5747
5748                 {
5749                 /* left and right are both bit variables, result is carry */
5750                         resolvedIfx rIfx;
5751               
5752                         resolveIfx(&rIfx,ifx);
5753
5754                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5755                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5756                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5757                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5758                         genSkipz2(&rIfx,0);
5759                 }
5760         } else {
5761
5762                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5763
5764                         /* They're not both bit variables. Is the right a literal? */
5765                         if(AOP_TYPE(right) == AOP_LIT) {
5766                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5767             
5768                         switch(size) {
5769
5770                                 case 1:
5771                                         switch(lit & 0xff) {
5772                                                 case 1:
5773                                                                 if ( IC_TRUE(ifx) ) {
5774                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5775                                                                         emitSKPNZ;
5776                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5777                                                                 } else {
5778                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5779                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5780                                                                 }
5781                                                                 break;
5782                                                 case 0xff:
5783                                                                 if ( IC_TRUE(ifx) ) {
5784                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5785                                                                         emitSKPNZ;
5786                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5787                                                                 } else {
5788                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5789                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5790                                                                 }
5791                                                                 break;
5792                                                 default:
5793                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5794                                                                 if(lit)
5795                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5796                                                                 genSkip(ifx,'z');
5797                                         } // switch lit
5798
5799
5800                                         /* end of size == 1 */
5801                                         break;
5802               
5803                                 case 2:
5804                                         genc16bit2lit(left,lit,offset);
5805                                         genSkip(ifx,'z');
5806                                         break;
5807                                         /* end of size == 2 */
5808
5809                                 default:
5810                                         /* size is 4 */
5811                                         if(lit==0) {
5812                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5813                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5814                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5815                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5816                                                 genSkip(ifx,'z');
5817                                         } else {
5818                                                 /* search for patterns that can be optimized */
5819
5820                                                 genc16bit2lit(left,lit,0);
5821                                                 lit >>= 16;
5822                                                 if(lit) {
5823                                                                 if(IC_TRUE(ifx))
5824                                                                 emitSKPZ; // if hi word unequal
5825                                                                 else
5826                                                                 emitSKPNZ; // if hi word equal
5827                                                                 // fail early
5828                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5829                                                         genc16bit2lit(left,lit,2);
5830                                                         genSkip(ifx,'z');
5831                                                 } else {
5832                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5833                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5834                                                         genSkip(ifx,'z');
5835                                                 }
5836                                         }
5837                                                 pic16_emitpLabel(falselbl->key);
5838                                                 break;
5839
5840                         } // switch size
5841           
5842                         ifx->generated = 1;
5843                         goto release ;
5844             
5845
5846           } else if(AOP_TYPE(right) == AOP_CRY ) {
5847             /* we know the left is not a bit, but that the right is */
5848             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5849             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5850                       pic16_popGet(AOP(right),offset));
5851             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5852
5853             /* if the two are equal, then W will be 0 and the Z bit is set
5854              * we could test Z now, or go ahead and check the high order bytes if
5855              * the variable we're comparing is larger than a byte. */
5856
5857             while(--size)
5858               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5859
5860             if ( IC_TRUE(ifx) ) {
5861               emitSKPNZ;
5862               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5863               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5864             } else {
5865               emitSKPZ;
5866               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5867               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5868             }
5869
5870           } else {
5871             /* They're both variables that are larger than bits */
5872             int s = size;
5873
5874             tlbl = newiTempLabel(NULL);
5875
5876             while(size--) {
5877               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5878               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5879
5880               if ( IC_TRUE(ifx) ) {
5881                 if(size) {
5882                   emitSKPZ;
5883                 
5884                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5885
5886                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5887                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5888                 } else {
5889                   emitSKPNZ;
5890
5891                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5892
5893
5894                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5895                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5896                 }
5897               } else {
5898                 emitSKPZ;
5899
5900                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5901
5902                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5903                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5904               }
5905               offset++;
5906             }
5907             if(s>1 && IC_TRUE(ifx)) {
5908               pic16_emitpLabel(tlbl->key);
5909               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
5910             }
5911           }
5912         }
5913         /* mark the icode as generated */
5914         ifx->generated = 1;
5915         goto release ;
5916     }
5917
5918     /* if they are both bit variables */
5919     if (AOP_TYPE(left) == AOP_CRY &&
5920         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5921         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5922         if(AOP_TYPE(right) == AOP_LIT){
5923             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5924             if(lit == 0L){
5925                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5926                 pic16_emitcode("cpl","c");
5927             } else if(lit == 1L) {
5928                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5929             } else {
5930                 pic16_emitcode("clr","c");
5931             }
5932             /* AOP_TYPE(right) == AOP_CRY */
5933         } else {
5934             symbol *lbl = newiTempLabel(NULL);
5935             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5936             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5937             pic16_emitcode("cpl","c");
5938             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5939         }
5940         /* c = 1 if egal */
5941         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5942             pic16_outBitC(result);
5943             goto release ;
5944         }
5945         if (ifx) {
5946             genIfxJump (ifx,"c");
5947             goto release ;
5948         }
5949         /* if the result is used in an arithmetic operation
5950         then put the result in place */
5951         pic16_outBitC(result);
5952     } else {
5953       
5954       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5955       gencjne(left,right,result,ifx);
5956 /*
5957       if(ifx) 
5958         gencjne(left,right,newiTempLabel(NULL));
5959       else {
5960         if(IC_TRUE(ifx)->key)
5961           gencjne(left,right,IC_TRUE(ifx)->key);
5962         else
5963           gencjne(left,right,IC_FALSE(ifx)->key);
5964         ifx->generated = 1;
5965         goto release ;
5966       }
5967       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5968         pic16_aopPut(AOP(result),"a",0);
5969         goto release ;
5970       }
5971
5972       if (ifx) {
5973         genIfxJump (ifx,"a");
5974         goto release ;
5975       }
5976 */
5977       /* if the result is used in an arithmetic operation
5978          then put the result in place */
5979 /*
5980       if (AOP_TYPE(result) != AOP_CRY) 
5981         pic16_outAcc(result);
5982 */
5983       /* leave the result in acc */
5984     }
5985
5986 release:
5987     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5988     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5989     pic16_freeAsmop(result,NULL,ic,TRUE);
5990 }
5991 #endif
5992
5993 /*-----------------------------------------------------------------*/
5994 /* ifxForOp - returns the icode containing the ifx for operand     */
5995 /*-----------------------------------------------------------------*/
5996 static iCode *ifxForOp ( operand *op, iCode *ic )
5997 {
5998     /* if true symbol then needs to be assigned */
5999     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6000     if (IS_TRUE_SYMOP(op))
6001         return NULL ;
6002
6003     /* if this has register type condition and
6004     the next instruction is ifx with the same operand
6005     and live to of the operand is upto the ifx only then */
6006     if (ic->next
6007         && ic->next->op == IFX
6008         && IC_COND(ic->next)->key == op->key
6009         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6010         ) {
6011                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6012           return ic->next;
6013     }
6014
6015     if (ic->next &&
6016         ic->next->op == IFX &&
6017         IC_COND(ic->next)->key == op->key) {
6018       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6019       return ic->next;
6020     }
6021
6022     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6023     if (ic->next &&
6024         ic->next->op == IFX)
6025       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6026
6027     if (ic->next &&
6028         ic->next->op == IFX &&
6029         IC_COND(ic->next)->key == op->key) {
6030       DEBUGpic16_emitcode ("; "," key is okay");
6031       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6032                            OP_SYMBOL(op)->liveTo,
6033                            ic->next->seq);
6034     }
6035
6036 #if 0
6037     /* the code below is completely untested
6038      * it just allows ulong2fs.c compile -- VR */
6039          
6040     ic = ic->next;
6041     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6042                                         __FILE__, __FUNCTION__, __LINE__);
6043         
6044     /* if this has register type condition and
6045     the next instruction is ifx with the same operand
6046     and live to of the operand is upto the ifx only then */
6047     if (ic->next &&
6048         ic->next->op == IFX &&
6049         IC_COND(ic->next)->key == op->key &&
6050         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6051         return ic->next;
6052
6053     if (ic->next &&
6054         ic->next->op == IFX &&
6055         IC_COND(ic->next)->key == op->key) {
6056       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6057       return ic->next;
6058     }
6059
6060     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6061                                         __FILE__, __FUNCTION__, __LINE__);
6062
6063 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6064 #endif
6065
6066     return NULL;
6067 }
6068 /*-----------------------------------------------------------------*/
6069 /* genAndOp - for && operation                                     */
6070 /*-----------------------------------------------------------------*/
6071 static void genAndOp (iCode *ic)
6072 {
6073     operand *left,*right, *result;
6074 /*     symbol *tlbl; */
6075
6076     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6077     /* note here that && operations that are in an
6078     if statement are taken away by backPatchLabels
6079     only those used in arthmetic operations remain */
6080     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6081     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6082     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6083
6084     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6085
6086     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6087     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6088     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6089
6090     /* if both are bit variables */
6091 /*     if (AOP_TYPE(left) == AOP_CRY && */
6092 /*         AOP_TYPE(right) == AOP_CRY ) { */
6093 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6094 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6095 /*         pic16_outBitC(result); */
6096 /*     } else { */
6097 /*         tlbl = newiTempLabel(NULL); */
6098 /*         pic16_toBoolean(left);     */
6099 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6100 /*         pic16_toBoolean(right); */
6101 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6102 /*         pic16_outBitAcc(result); */
6103 /*     } */
6104
6105     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6106     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107     pic16_freeAsmop(result,NULL,ic,TRUE);
6108 }
6109
6110
6111 /*-----------------------------------------------------------------*/
6112 /* genOrOp - for || operation                                      */
6113 /*-----------------------------------------------------------------*/
6114 /*
6115   tsd pic port -
6116   modified this code, but it doesn't appear to ever get called
6117 */
6118
6119 static void genOrOp (iCode *ic)
6120 {
6121     operand *left,*right, *result;
6122     symbol *tlbl;
6123
6124     /* note here that || operations that are in an
6125     if statement are taken away by backPatchLabels
6126     only those used in arthmetic operations remain */
6127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6128     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6129     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6130     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6131
6132     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6133
6134     /* if both are bit variables */
6135     if (AOP_TYPE(left) == AOP_CRY &&
6136         AOP_TYPE(right) == AOP_CRY ) {
6137       pic16_emitcode("clrc","");
6138       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6139                AOP(left)->aopu.aop_dir,
6140                AOP(left)->aopu.aop_dir);
6141       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6142                AOP(right)->aopu.aop_dir,
6143                AOP(right)->aopu.aop_dir);
6144       pic16_emitcode("setc","");
6145
6146     } else {
6147         tlbl = newiTempLabel(NULL);
6148         pic16_toBoolean(left);
6149         emitSKPZ;
6150         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6151         pic16_toBoolean(right);
6152         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6153
6154         pic16_outBitAcc(result);
6155     }
6156
6157     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6158     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6159     pic16_freeAsmop(result,NULL,ic,TRUE);            
6160 }
6161
6162 /*-----------------------------------------------------------------*/
6163 /* isLiteralBit - test if lit == 2^n                               */
6164 /*-----------------------------------------------------------------*/
6165 static int isLiteralBit(unsigned long lit)
6166 {
6167     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6168     0x100L,0x200L,0x400L,0x800L,
6169     0x1000L,0x2000L,0x4000L,0x8000L,
6170     0x10000L,0x20000L,0x40000L,0x80000L,
6171     0x100000L,0x200000L,0x400000L,0x800000L,
6172     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6173     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6174     int idx;
6175     
6176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6177     for(idx = 0; idx < 32; idx++)
6178         if(lit == pw[idx])
6179             return idx+1;
6180     return 0;
6181 }
6182
6183 /*-----------------------------------------------------------------*/
6184 /* continueIfTrue -                                                */
6185 /*-----------------------------------------------------------------*/
6186 static void continueIfTrue (iCode *ic)
6187 {
6188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6189     if(IC_TRUE(ic))
6190         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6191     ic->generated = 1;
6192 }
6193
6194 /*-----------------------------------------------------------------*/
6195 /* jmpIfTrue -                                                     */
6196 /*-----------------------------------------------------------------*/
6197 static void jumpIfTrue (iCode *ic)
6198 {
6199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6200     if(!IC_TRUE(ic))
6201         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6202     ic->generated = 1;
6203 }
6204
6205 /*-----------------------------------------------------------------*/
6206 /* jmpTrueOrFalse -                                                */
6207 /*-----------------------------------------------------------------*/
6208 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6209 {
6210     // ugly but optimized by peephole
6211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6212     if(IC_TRUE(ic)){
6213         symbol *nlbl = newiTempLabel(NULL);
6214         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6215         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6216         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6217         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6218     }
6219     else{
6220         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6221         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6222     }
6223     ic->generated = 1;
6224 }
6225
6226 /*-----------------------------------------------------------------*/
6227 /* genAnd  - code for and                                          */
6228 /*-----------------------------------------------------------------*/
6229 static void genAnd (iCode *ic, iCode *ifx)
6230 {
6231   operand *left, *right, *result;
6232   int size, offset=0;  
6233   unsigned long lit = 0L;
6234   int bytelit = 0;
6235   resolvedIfx rIfx;
6236
6237
6238   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6239   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6240   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6241   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6242
6243   resolveIfx(&rIfx,ifx);
6244
6245   /* if left is a literal & right is not then exchange them */
6246   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6247       AOP_NEEDSACC(left)) {
6248     operand *tmp = right ;
6249     right = left;
6250     left = tmp;
6251   }
6252
6253   /* if result = right then exchange them */
6254   if(pic16_sameRegs(AOP(result),AOP(right))){
6255     operand *tmp = right ;
6256     right = left;
6257     left = tmp;
6258   }
6259
6260   /* if right is bit then exchange them */
6261   if (AOP_TYPE(right) == AOP_CRY &&
6262       AOP_TYPE(left) != AOP_CRY){
6263     operand *tmp = right ;
6264     right = left;
6265     left = tmp;
6266   }
6267   if(AOP_TYPE(right) == AOP_LIT)
6268     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6269
6270   size = AOP_SIZE(result);
6271
6272   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6273
6274   // if(bit & yy)
6275   // result = bit & yy;
6276   if (AOP_TYPE(left) == AOP_CRY){
6277     // c = bit & literal;
6278     if(AOP_TYPE(right) == AOP_LIT){
6279       if(lit & 1) {
6280         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6281           // no change
6282           goto release;
6283         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6284       } else {
6285         // bit(result) = 0;
6286         if(size && (AOP_TYPE(result) == AOP_CRY)){
6287           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6288           goto release;
6289         }
6290         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6291           jumpIfTrue(ifx);
6292           goto release;
6293         }
6294         pic16_emitcode("clr","c");
6295       }
6296     } else {
6297       if (AOP_TYPE(right) == AOP_CRY){
6298         // c = bit & bit;
6299         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6300         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6301       } else {
6302         // c = bit & val;
6303         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6304         // c = lsb
6305         pic16_emitcode("rrc","a");
6306         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6307       }
6308     }
6309     // bit = c
6310     // val = c
6311     if(size)
6312       pic16_outBitC(result);
6313     // if(bit & ...)
6314     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6315       genIfxJump(ifx, "c");           
6316     goto release ;
6317   }
6318
6319   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6320   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6321   if((AOP_TYPE(right) == AOP_LIT) &&
6322      (AOP_TYPE(result) == AOP_CRY) &&
6323      (AOP_TYPE(left) != AOP_CRY)){
6324     int posbit = isLiteralBit(lit);
6325     /* left &  2^n */
6326     if(posbit){
6327       posbit--;
6328       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6329       // bit = left & 2^n
6330       if(size)
6331         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6332       // if(left &  2^n)
6333       else{
6334         if(ifx){
6335 /*
6336           if(IC_TRUE(ifx)) {
6337             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6338             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6339           } else {
6340             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6341             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6342           }
6343 */
6344         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6345         size = AOP_SIZE(left);
6346
6347         {
6348           int bp = posbit, ofs=0;
6349           
6350             while(bp > 7) {
6351               bp -= 8;
6352               ofs++;
6353             }
6354         
6355           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6356                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6357
6358         }
6359 /*
6360           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6361                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6362 */
6363           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6364           
6365           ifx->generated = 1;
6366         }
6367         goto release;
6368       }
6369     } else {
6370       symbol *tlbl = newiTempLabel(NULL);
6371       int sizel = AOP_SIZE(left);
6372       if(size)
6373         pic16_emitcode("setb","c");
6374       while(sizel--){
6375         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6376           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6377           // byte ==  2^n ?
6378           if((posbit = isLiteralBit(bytelit)) != 0)
6379             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6380           else{
6381             if(bytelit != 0x0FFL)
6382               pic16_emitcode("anl","a,%s",
6383                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6384             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6385           }
6386         }
6387         offset++;
6388       }
6389       // bit = left & literal
6390       if(size){
6391         pic16_emitcode("clr","c");
6392         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6393       }
6394       // if(left & literal)
6395       else{
6396         if(ifx)
6397           jmpTrueOrFalse(ifx, tlbl);
6398         goto release ;
6399       }
6400     }
6401     pic16_outBitC(result);
6402     goto release ;
6403   }
6404
6405   /* if left is same as result */
6406   if(pic16_sameRegs(AOP(result),AOP(left))){
6407     int know_W = -1;
6408     for(;size--; offset++,lit>>=8) {
6409       if(AOP_TYPE(right) == AOP_LIT){
6410         switch(lit & 0xff) {
6411         case 0x00:
6412           /*  and'ing with 0 has clears the result */
6413 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6414           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6415           break;
6416         case 0xff:
6417           /* and'ing with 0xff is a nop when the result and left are the same */
6418           break;
6419
6420         default:
6421           {
6422             int p = my_powof2( (~lit) & 0xff );
6423             if(p>=0) {
6424               /* only one bit is set in the literal, so use a bcf instruction */
6425 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6426               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6427
6428             } else {
6429               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6430               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6431               if(know_W != (lit&0xff))
6432                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6433               know_W = lit &0xff;
6434               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6435             }
6436           }    
6437         }
6438       } else {
6439         if (AOP_TYPE(left) == AOP_ACC) {
6440           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6441         } else {                    
6442           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6443           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6444
6445         }
6446       }
6447     }
6448
6449   } else {
6450     // left & result in different registers
6451     if(AOP_TYPE(result) == AOP_CRY){
6452       // result = bit
6453       // if(size), result in bit
6454       // if(!size && ifx), conditional oper: if(left & right)
6455       symbol *tlbl = newiTempLabel(NULL);
6456       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6457       if(size)
6458         pic16_emitcode("setb","c");
6459       while(sizer--){
6460         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6461         pic16_emitcode("anl","a,%s",
6462                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6463         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6464         offset++;
6465       }
6466       if(size){
6467         CLRC;
6468         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6469         pic16_outBitC(result);
6470       } else if(ifx)
6471         jmpTrueOrFalse(ifx, tlbl);
6472     } else {
6473       for(;(size--);offset++) {
6474         // normal case
6475         // result = left & right
6476         if(AOP_TYPE(right) == AOP_LIT){
6477           int t = (lit >> (offset*8)) & 0x0FFL;
6478           switch(t) { 
6479           case 0x00:
6480             pic16_emitcode("clrf","%s",
6481                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6482             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6483             break;
6484           case 0xff:
6485             pic16_emitcode("movf","%s,w",
6486                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6487             pic16_emitcode("movwf","%s",
6488                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6489             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6490             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6491             break;
6492           default:
6493             pic16_emitcode("movlw","0x%x",t);
6494             pic16_emitcode("andwf","%s,w",
6495                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6496             pic16_emitcode("movwf","%s",
6497                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6498               
6499             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6500             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6501             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6502           }
6503           continue;
6504         }
6505
6506         if (AOP_TYPE(left) == AOP_ACC) {
6507           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6508           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6509         } else {
6510           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6511           pic16_emitcode("andwf","%s,w",
6512                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6513           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6514           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6515         }
6516         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6517         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6518       }
6519     }
6520   }
6521
6522   release :
6523     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6524   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6525   pic16_freeAsmop(result,NULL,ic,TRUE);     
6526 }
6527
6528 /*-----------------------------------------------------------------*/
6529 /* genOr  - code for or                                            */
6530 /*-----------------------------------------------------------------*/
6531 static void genOr (iCode *ic, iCode *ifx)
6532 {
6533     operand *left, *right, *result;
6534     int size, offset=0;
6535     unsigned long lit = 0L;
6536
6537     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6538
6539     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6540     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6541     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6542
6543     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6544
6545     /* if left is a literal & right is not then exchange them */
6546     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6547         AOP_NEEDSACC(left)) {
6548         operand *tmp = right ;
6549         right = left;
6550         left = tmp;
6551     }
6552
6553     /* if result = right then exchange them */
6554     if(pic16_sameRegs(AOP(result),AOP(right))){
6555         operand *tmp = right ;
6556         right = left;
6557         left = tmp;
6558     }
6559
6560     /* if right is bit then exchange them */
6561     if (AOP_TYPE(right) == AOP_CRY &&
6562         AOP_TYPE(left) != AOP_CRY){
6563         operand *tmp = right ;
6564         right = left;
6565         left = tmp;
6566     }
6567
6568     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6569
6570     if(AOP_TYPE(right) == AOP_LIT)
6571         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6572
6573     size = AOP_SIZE(result);
6574
6575     // if(bit | yy)
6576     // xx = bit | yy;
6577     if (AOP_TYPE(left) == AOP_CRY){
6578         if(AOP_TYPE(right) == AOP_LIT){
6579             // c = bit & literal;
6580             if(lit){
6581                 // lit != 0 => result = 1
6582                 if(AOP_TYPE(result) == AOP_CRY){
6583                   if(size)
6584                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6585                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6586                   //     AOP(result)->aopu.aop_dir,
6587                   //     AOP(result)->aopu.aop_dir);
6588                     else if(ifx)
6589                         continueIfTrue(ifx);
6590                     goto release;
6591                 }
6592             } else {
6593                 // lit == 0 => result = left
6594                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6595                     goto release;
6596                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6597             }
6598         } else {
6599             if (AOP_TYPE(right) == AOP_CRY){
6600               if(pic16_sameRegs(AOP(result),AOP(left))){
6601                 // c = bit | bit;
6602                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6603                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6604                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6605
6606                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6607                          AOP(result)->aopu.aop_dir,
6608                          AOP(result)->aopu.aop_dir);
6609                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6610                          AOP(right)->aopu.aop_dir,
6611                          AOP(right)->aopu.aop_dir);
6612                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6613                          AOP(result)->aopu.aop_dir,
6614                          AOP(result)->aopu.aop_dir);
6615               } else {
6616                 if( AOP_TYPE(result) == AOP_ACC) {
6617                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6618                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6619                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6620                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6621
6622                 } else {
6623
6624                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6625                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6626                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6627                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6628
6629                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6630                                  AOP(result)->aopu.aop_dir,
6631                                  AOP(result)->aopu.aop_dir);
6632                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6633                                  AOP(right)->aopu.aop_dir,
6634                                  AOP(right)->aopu.aop_dir);
6635                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6636                                  AOP(left)->aopu.aop_dir,
6637                                  AOP(left)->aopu.aop_dir);
6638                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6639                                  AOP(result)->aopu.aop_dir,
6640                                  AOP(result)->aopu.aop_dir);
6641                 }
6642               }
6643             } else {
6644                 // c = bit | val;
6645                 symbol *tlbl = newiTempLabel(NULL);
6646                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6647
6648
6649                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6650                 if( AOP_TYPE(right) == AOP_ACC) {
6651                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6652                   emitSKPNZ;
6653                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6654                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6655                 }
6656
6657
6658
6659                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6660                     pic16_emitcode(";XXX setb","c");
6661                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6662                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6663                 pic16_toBoolean(right);
6664                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6665                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6666                     jmpTrueOrFalse(ifx, tlbl);
6667                     goto release;
6668                 } else {
6669                     CLRC;
6670                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6671                 }
6672             }
6673         }
6674         // bit = c
6675         // val = c
6676         if(size)
6677             pic16_outBitC(result);
6678         // if(bit | ...)
6679         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6680             genIfxJump(ifx, "c");           
6681         goto release ;
6682     }
6683
6684     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6685     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6686     if((AOP_TYPE(right) == AOP_LIT) &&
6687        (AOP_TYPE(result) == AOP_CRY) &&
6688        (AOP_TYPE(left) != AOP_CRY)){
6689         if(lit){
6690           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6691             // result = 1
6692             if(size)
6693                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6694             else 
6695                 continueIfTrue(ifx);
6696             goto release;
6697         } else {
6698           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6699             // lit = 0, result = boolean(left)
6700             if(size)
6701                 pic16_emitcode(";XXX setb","c");
6702             pic16_toBoolean(right);
6703             if(size){
6704                 symbol *tlbl = newiTempLabel(NULL);
6705                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6706                 CLRC;
6707                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6708             } else {
6709                 genIfxJump (ifx,"a");
6710                 goto release;
6711             }
6712         }
6713         pic16_outBitC(result);
6714         goto release ;
6715     }
6716
6717     /* if left is same as result */
6718     if(pic16_sameRegs(AOP(result),AOP(left))){
6719       int know_W = -1;
6720       for(;size--; offset++,lit>>=8) {
6721         if(AOP_TYPE(right) == AOP_LIT){
6722           if((lit & 0xff) == 0)
6723             /*  or'ing with 0 has no effect */
6724             continue;
6725           else {
6726             int p = my_powof2(lit & 0xff);
6727             if(p>=0) {
6728               /* only one bit is set in the literal, so use a bsf instruction */
6729               pic16_emitpcode(POC_BSF,
6730                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6731             } else {
6732               if(know_W != (lit & 0xff))
6733                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6734               know_W = lit & 0xff;
6735               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6736             }
6737                     
6738           }
6739         } else {
6740           if (AOP_TYPE(left) == AOP_ACC) {
6741             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6742             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6743           } else {                  
6744             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6745             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6746
6747             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6748             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6749
6750           }
6751         }
6752       }
6753     } else {
6754         // left & result in different registers
6755         if(AOP_TYPE(result) == AOP_CRY){
6756             // result = bit
6757             // if(size), result in bit
6758             // if(!size && ifx), conditional oper: if(left | right)
6759             symbol *tlbl = newiTempLabel(NULL);
6760             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6761             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6762
6763
6764             if(size)
6765                 pic16_emitcode(";XXX setb","c");
6766             while(sizer--){
6767                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6768                 pic16_emitcode(";XXX orl","a,%s",
6769                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6770                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6771                 offset++;
6772             }
6773             if(size){
6774                 CLRC;
6775                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6776                 pic16_outBitC(result);
6777             } else if(ifx)
6778                 jmpTrueOrFalse(ifx, tlbl);
6779         } else for(;(size--);offset++){
6780           // normal case
6781           // result = left & right
6782           if(AOP_TYPE(right) == AOP_LIT){
6783             int t = (lit >> (offset*8)) & 0x0FFL;
6784             switch(t) { 
6785             case 0x00:
6786               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6787               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6788
6789               pic16_emitcode("movf","%s,w",
6790                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6791               pic16_emitcode("movwf","%s",
6792                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6793               break;
6794             default:
6795               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6796               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6797               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6798
6799               pic16_emitcode("movlw","0x%x",t);
6800               pic16_emitcode("iorwf","%s,w",
6801                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6802               pic16_emitcode("movwf","%s",
6803                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6804               
6805             }
6806             continue;
6807           }
6808
6809           // faster than result <- left, anl result,right
6810           // and better if result is SFR
6811           if (AOP_TYPE(left) == AOP_ACC) {
6812             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6813             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6814           } else {
6815             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6816             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6817
6818             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6819             pic16_emitcode("iorwf","%s,w",
6820                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6821           }
6822           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6823           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6824         }
6825     }
6826
6827 release :
6828     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6829     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6830     pic16_freeAsmop(result,NULL,ic,TRUE);     
6831 }
6832
6833 /*-----------------------------------------------------------------*/
6834 /* genXor - code for xclusive or                                   */
6835 /*-----------------------------------------------------------------*/
6836 static void genXor (iCode *ic, iCode *ifx)
6837 {
6838   operand *left, *right, *result;
6839   int size, offset=0;
6840   unsigned long lit = 0L;
6841
6842   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6843
6844   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6845   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6846   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6847
6848   /* if left is a literal & right is not ||
6849      if left needs acc & right does not */
6850   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6851       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6852     operand *tmp = right ;
6853     right = left;
6854     left = tmp;
6855   }
6856
6857   /* if result = right then exchange them */
6858   if(pic16_sameRegs(AOP(result),AOP(right))){
6859     operand *tmp = right ;
6860     right = left;
6861     left = tmp;
6862   }
6863
6864   /* if right is bit then exchange them */
6865   if (AOP_TYPE(right) == AOP_CRY &&
6866       AOP_TYPE(left) != AOP_CRY){
6867     operand *tmp = right ;
6868     right = left;
6869     left = tmp;
6870   }
6871   if(AOP_TYPE(right) == AOP_LIT)
6872     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6873
6874   size = AOP_SIZE(result);
6875
6876   // if(bit ^ yy)
6877   // xx = bit ^ yy;
6878   if (AOP_TYPE(left) == AOP_CRY){
6879     if(AOP_TYPE(right) == AOP_LIT){
6880       // c = bit & literal;
6881       if(lit>>1){
6882         // lit>>1  != 0 => result = 1
6883         if(AOP_TYPE(result) == AOP_CRY){
6884           if(size)
6885             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6886             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6887           else if(ifx)
6888             continueIfTrue(ifx);
6889           goto release;
6890         }
6891         pic16_emitcode("setb","c");
6892       } else{
6893         // lit == (0 or 1)
6894         if(lit == 0){
6895           // lit == 0, result = left
6896           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6897             goto release;
6898           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6899         } else{
6900           // lit == 1, result = not(left)
6901           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6902             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6903             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6904             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6905             goto release;
6906           } else {
6907             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6908             pic16_emitcode("cpl","c");
6909           }
6910         }
6911       }
6912
6913     } else {
6914       // right != literal
6915       symbol *tlbl = newiTempLabel(NULL);
6916       if (AOP_TYPE(right) == AOP_CRY){
6917         // c = bit ^ bit;
6918         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6919       }
6920       else{
6921         int sizer = AOP_SIZE(right);
6922         // c = bit ^ val
6923         // if val>>1 != 0, result = 1
6924         pic16_emitcode("setb","c");
6925         while(sizer){
6926           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6927           if(sizer == 1)
6928             // test the msb of the lsb
6929             pic16_emitcode("anl","a,#0xfe");
6930           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6931           sizer--;
6932         }
6933         // val = (0,1)
6934         pic16_emitcode("rrc","a");
6935       }
6936       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6937       pic16_emitcode("cpl","c");
6938       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6939     }
6940     // bit = c
6941     // val = c
6942     if(size)
6943       pic16_outBitC(result);
6944     // if(bit | ...)
6945     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6946       genIfxJump(ifx, "c");           
6947     goto release ;
6948   }
6949
6950   if(pic16_sameRegs(AOP(result),AOP(left))){
6951     /* if left is same as result */
6952     for(;size--; offset++) {
6953       if(AOP_TYPE(right) == AOP_LIT){
6954         int t  = (lit >> (offset*8)) & 0x0FFL;
6955         if(t == 0x00L)
6956           continue;
6957         else
6958           if (IS_AOP_PREG(left)) {
6959             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6960             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6961             pic16_aopPut(AOP(result),"a",offset);
6962           } else {
6963             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6964             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6965             pic16_emitcode("xrl","%s,%s",
6966                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6967                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6968           }
6969       } else {
6970         if (AOP_TYPE(left) == AOP_ACC)
6971           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6972         else {
6973           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6974           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6975 /*
6976           if (IS_AOP_PREG(left)) {
6977             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6978             pic16_aopPut(AOP(result),"a",offset);
6979           } else
6980             pic16_emitcode("xrl","%s,a",
6981                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6982 */
6983         }
6984       }
6985     }
6986   } else {
6987     // left & result in different registers
6988     if(AOP_TYPE(result) == AOP_CRY){
6989       // result = bit
6990       // if(size), result in bit
6991       // if(!size && ifx), conditional oper: if(left ^ right)
6992       symbol *tlbl = newiTempLabel(NULL);
6993       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6994       if(size)
6995         pic16_emitcode("setb","c");
6996       while(sizer--){
6997         if((AOP_TYPE(right) == AOP_LIT) &&
6998            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6999           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7000         } else {
7001           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7002           pic16_emitcode("xrl","a,%s",
7003                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7004         }
7005         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7006         offset++;
7007       }
7008       if(size){
7009         CLRC;
7010         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7011         pic16_outBitC(result);
7012       } else if(ifx)
7013         jmpTrueOrFalse(ifx, tlbl);
7014     } else for(;(size--);offset++){
7015       // normal case
7016       // result = left & right
7017       if(AOP_TYPE(right) == AOP_LIT){
7018         int t = (lit >> (offset*8)) & 0x0FFL;
7019         switch(t) { 
7020         case 0x00:
7021           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7022           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7023           pic16_emitcode("movf","%s,w",
7024                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7025           pic16_emitcode("movwf","%s",
7026                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7027           break;
7028         case 0xff:
7029           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7030           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7031           pic16_emitcode("comf","%s,w",
7032                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7033           pic16_emitcode("movwf","%s",
7034                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7035           break;
7036         default:
7037           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7038           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7039           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7040           pic16_emitcode("movlw","0x%x",t);
7041           pic16_emitcode("xorwf","%s,w",
7042                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7043           pic16_emitcode("movwf","%s",
7044                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7045
7046         }
7047         continue;
7048       }
7049
7050       // faster than result <- left, anl result,right
7051       // and better if result is SFR
7052       if (AOP_TYPE(left) == AOP_ACC) {
7053         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7054         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7055       } else {
7056         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7057         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7058         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7059         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7060       }
7061       if ( AOP_TYPE(result) != AOP_ACC){
7062         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7063         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7064       }
7065     }
7066   }
7067
7068   release :
7069     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7070   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7071   pic16_freeAsmop(result,NULL,ic,TRUE);     
7072 }
7073
7074 /*-----------------------------------------------------------------*/
7075 /* genInline - write the inline code out                           */
7076 /*-----------------------------------------------------------------*/
7077 static void genInline (iCode *ic)
7078 {
7079   char *buffer, *bp, *bp1;
7080     
7081         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7082
7083         _G.inLine += (!options.asmpeep);
7084
7085         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7086         strcpy(buffer,IC_INLINE(ic));
7087
7088 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7089
7090         /* emit each line as a code */
7091         while (*bp) {
7092                 if (*bp == '\n') {
7093                         *bp++ = '\0';
7094
7095                         if(*bp1)
7096                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7097                         bp1 = bp;
7098                 } else {
7099                         if (*bp == ':') {
7100                                 bp++;
7101                                 *bp = '\0';
7102                                 bp++;
7103
7104                                 /* print label, use this special format with NULL directive
7105                                  * to denote that the argument should not be indented with tab */
7106                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7107                                 bp1 = bp;
7108                         } else
7109                                 bp++;
7110                 }
7111         }
7112
7113         if ((bp1 != bp) && *bp1)
7114                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7115
7116
7117     Safe_free(buffer);
7118
7119     _G.inLine -= (!options.asmpeep);
7120 }
7121
7122 /*-----------------------------------------------------------------*/
7123 /* genRRC - rotate right with carry                                */
7124 /*-----------------------------------------------------------------*/
7125 static void genRRC (iCode *ic)
7126 {
7127   operand *left , *result ;
7128   int size, offset = 0, same;
7129
7130   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7131
7132   /* rotate right with carry */
7133   left = IC_LEFT(ic);
7134   result=IC_RESULT(ic);
7135   pic16_aopOp (left,ic,FALSE);
7136   pic16_aopOp (result,ic,FALSE);
7137
7138   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7139
7140   same = pic16_sameRegs(AOP(result),AOP(left));
7141
7142   size = AOP_SIZE(result);    
7143
7144   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7145
7146   /* get the lsb and put it into the carry */
7147   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7148
7149   offset = 0 ;
7150
7151   while(size--) {
7152
7153     if(same) {
7154       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7155     } else {
7156       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7157       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7158     }
7159
7160     offset++;
7161   }
7162
7163   pic16_freeAsmop(left,NULL,ic,TRUE);
7164   pic16_freeAsmop(result,NULL,ic,TRUE);
7165 }
7166
7167 /*-----------------------------------------------------------------*/
7168 /* genRLC - generate code for rotate left with carry               */
7169 /*-----------------------------------------------------------------*/
7170 static void genRLC (iCode *ic)
7171 {    
7172   operand *left , *result ;
7173   int size, offset = 0;
7174   int same;
7175
7176   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7177   /* rotate right with carry */
7178   left = IC_LEFT(ic);
7179   result=IC_RESULT(ic);
7180   pic16_aopOp (left,ic,FALSE);
7181   pic16_aopOp (result,ic,FALSE);
7182
7183   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7184
7185   same = pic16_sameRegs(AOP(result),AOP(left));
7186
7187   /* move it to the result */
7188   size = AOP_SIZE(result);    
7189
7190   /* get the msb and put it into the carry */
7191   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7192
7193   offset = 0 ;
7194
7195   while(size--) {
7196
7197     if(same) {
7198       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7199     } else {
7200       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7201       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7202     }
7203
7204     offset++;
7205   }
7206
7207
7208   pic16_freeAsmop(left,NULL,ic,TRUE);
7209   pic16_freeAsmop(result,NULL,ic,TRUE);
7210 }
7211
7212
7213 /* gpasm can get the highest order bit with HIGH/UPPER
7214  * so the following probably is not needed -- VR */
7215  
7216 /*-----------------------------------------------------------------*/
7217 /* genGetHbit - generates code get highest order bit               */
7218 /*-----------------------------------------------------------------*/
7219 static void genGetHbit (iCode *ic)
7220 {
7221     operand *left, *result;
7222     left = IC_LEFT(ic);
7223     result=IC_RESULT(ic);
7224     pic16_aopOp (left,ic,FALSE);
7225     pic16_aopOp (result,ic,FALSE);
7226
7227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7228     /* get the highest order byte into a */
7229     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7230     if(AOP_TYPE(result) == AOP_CRY){
7231         pic16_emitcode("rlc","a");
7232         pic16_outBitC(result);
7233     }
7234     else{
7235         pic16_emitcode("rl","a");
7236         pic16_emitcode("anl","a,#0x01");
7237         pic16_outAcc(result);
7238     }
7239
7240
7241     pic16_freeAsmop(left,NULL,ic,TRUE);
7242     pic16_freeAsmop(result,NULL,ic,TRUE);
7243 }
7244
7245 #if 0
7246 /*-----------------------------------------------------------------*/
7247 /* AccRol - rotate left accumulator by known count                 */
7248 /*-----------------------------------------------------------------*/
7249 static void AccRol (int shCount)
7250 {
7251     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7252     shCount &= 0x0007;              // shCount : 0..7
7253     switch(shCount){
7254         case 0 :
7255             break;
7256         case 1 :
7257             pic16_emitcode("rl","a");
7258             break;
7259         case 2 :
7260             pic16_emitcode("rl","a");
7261             pic16_emitcode("rl","a");
7262             break;
7263         case 3 :
7264             pic16_emitcode("swap","a");
7265             pic16_emitcode("rr","a");
7266             break;
7267         case 4 :
7268             pic16_emitcode("swap","a");
7269             break;
7270         case 5 :
7271             pic16_emitcode("swap","a");
7272             pic16_emitcode("rl","a");
7273             break;
7274         case 6 :
7275             pic16_emitcode("rr","a");
7276             pic16_emitcode("rr","a");
7277             break;
7278         case 7 :
7279             pic16_emitcode("rr","a");
7280             break;
7281     }
7282 }
7283 #endif
7284
7285 /*-----------------------------------------------------------------*/
7286 /* AccLsh - left shift accumulator by known count                  */
7287 /*-----------------------------------------------------------------*/
7288 static void AccLsh (int shCount)
7289 {
7290         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7291         switch(shCount){
7292                 case 0 :
7293                         return;
7294                         break;
7295                 case 1 :
7296                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7297                         break;
7298                 case 2 :
7299                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7300                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7301                         break;
7302                 case 3 :
7303                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7304                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7305                         break;
7306                 case 4 :
7307                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7308                         break;
7309                 case 5 :
7310                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7311                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7312                         break;
7313                 case 6 :
7314                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7315                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7316                         break;
7317                 case 7 :
7318                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7319                         break;
7320         }
7321
7322         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7323 }
7324
7325 /*-----------------------------------------------------------------*/
7326 /* AccRsh - right shift accumulator by known count                 */
7327 /*-----------------------------------------------------------------*/
7328 static void AccRsh (int shCount, int andmask)
7329 {
7330         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7331         switch(shCount){
7332                 case 0 :
7333                         return; break;
7334                 case 1 :
7335                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7336 //                      andmask = 0;    /* no need */
7337                         break;
7338                 case 2 :
7339                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7340                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7341 //                      andmask = 0;    /* no need */
7342                         break;
7343                 case 3 :
7344                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7345                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7346                         break;
7347                 case 4 :
7348                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7349                         break;
7350                 case 5 :
7351                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7352                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7353                         break;
7354                 case 6 :
7355                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7356                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7357                         break;
7358                 case 7 :
7359                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7360                         break;
7361         }
7362         
7363         if(andmask)
7364                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7365         else
7366                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7367 }
7368
7369 #if 0
7370 /*-----------------------------------------------------------------*/
7371 /* AccSRsh - signed right shift accumulator by known count                 */
7372 /*-----------------------------------------------------------------*/
7373 static void AccSRsh (int shCount)
7374 {
7375     symbol *tlbl ;
7376     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7377     if(shCount != 0){
7378         if(shCount == 1){
7379             pic16_emitcode("mov","c,acc.7");
7380             pic16_emitcode("rrc","a");
7381         } else if(shCount == 2){
7382             pic16_emitcode("mov","c,acc.7");
7383             pic16_emitcode("rrc","a");
7384             pic16_emitcode("mov","c,acc.7");
7385             pic16_emitcode("rrc","a");
7386         } else {
7387             tlbl = newiTempLabel(NULL);
7388             /* rotate right accumulator */
7389             AccRol(8 - shCount);
7390             /* and kill the higher order bits */
7391             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7392             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7393             pic16_emitcode("orl","a,#0x%02x",
7394                      (unsigned char)~SRMask[shCount]);
7395             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7396         }
7397     }
7398 }
7399 #endif
7400 /*-----------------------------------------------------------------*/
7401 /* shiftR1Left2Result - shift right one byte from left to result   */
7402 /*-----------------------------------------------------------------*/
7403 static void shiftR1Left2ResultSigned (operand *left, int offl,
7404                                 operand *result, int offr,
7405                                 int shCount)
7406 {
7407   int same;
7408
7409   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7410
7411   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7412
7413   switch(shCount) {
7414   case 1:
7415     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7416     if(same) 
7417       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7418     else {
7419       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7420       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7421     }
7422
7423     break;
7424   case 2:
7425
7426     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7427     if(same) 
7428       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7429     else {
7430       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7431       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7432     }
7433     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7434     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7435
7436     break;
7437
7438   case 3:
7439     if(same)
7440       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7441     else {
7442       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7443       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7444     }
7445
7446     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7447     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7448     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7449
7450     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7451     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7452
7453     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7454     break;
7455
7456   case 4:
7457     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7458     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7459     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7460     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7461     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7462     break;
7463   case 5:
7464     if(same) {
7465       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7466     } else {
7467       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7468       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7469     }
7470     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7471     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7472     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7473     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7474     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7475     break;
7476
7477   case 6:
7478     if(same) {
7479       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7480       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7481       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7482       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7483       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7484       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7485     } else {
7486       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7487       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7488       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7489       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7490       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7491     }
7492     break;
7493
7494   case 7:
7495     if(same) {
7496       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7497       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7498       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7499       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7500     } else {
7501       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7502       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7503       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7504     }
7505
7506   default:
7507     break;
7508   }
7509 }
7510
7511 /*-----------------------------------------------------------------*/
7512 /* shiftR1Left2Result - shift right one byte from left to result   */
7513 /*-----------------------------------------------------------------*/
7514 static void shiftR1Left2Result (operand *left, int offl,
7515                                 operand *result, int offr,
7516                                 int shCount, int sign)
7517 {
7518   int same;
7519
7520   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7521
7522   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7523
7524   /* Copy the msb into the carry if signed. */
7525   if(sign) {
7526     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7527     return;
7528   }
7529
7530
7531
7532   switch(shCount) {
7533   case 1:
7534     emitCLRC;
7535     if(same) 
7536       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7537     else {
7538       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7539       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7540     }
7541     break;
7542   case 2:
7543     emitCLRC;
7544     if(same) {
7545       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7546     } else {
7547       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7548       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7549     }
7550     emitCLRC;
7551     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7552
7553     break;
7554   case 3:
7555     if(same)
7556       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7557     else {
7558       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7559       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7560     }
7561
7562     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7563     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7564     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7565     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7566     break;
7567       
7568   case 4:
7569     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7570     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7571     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7572     break;
7573
7574   case 5:
7575     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7576     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7577     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7578     emitCLRC;
7579     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7580
7581     break;
7582   case 6:
7583
7584     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7585     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7586     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7587     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7588     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7589     break;
7590
7591   case 7:
7592
7593     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7594     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7595     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7596
7597     break;
7598
7599   default:
7600     break;
7601   }
7602 }
7603
7604 /*-----------------------------------------------------------------*/
7605 /* shiftL1Left2Result - shift left one byte from left to result    */
7606 /*-----------------------------------------------------------------*/
7607 static void shiftL1Left2Result (operand *left, int offl,
7608                                 operand *result, int offr, int shCount)
7609 {
7610   int same;
7611
7612   //    char *l;
7613   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7614
7615   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7616   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7617     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7618     //    MOVA(l);
7619     /* shift left accumulator */
7620     //AccLsh(shCount); // don't comment out just yet...
7621   //    pic16_aopPut(AOP(result),"a",offr);
7622
7623   switch(shCount) {
7624   case 1:
7625     /* Shift left 1 bit position */
7626     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7627     if(same) {
7628       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7629     } else {
7630       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7631       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7632     }
7633     break;
7634   case 2:
7635     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7636     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7637     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7638     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7639     break;
7640   case 3:
7641     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7642     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7643     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7644     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7645     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7646     break;
7647   case 4:
7648     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7649     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7650     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7651     break;
7652   case 5:
7653     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7654     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7655     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7656     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7657     break;
7658   case 6:
7659     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7660     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7661     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7662     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7663     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7664     break;
7665   case 7:
7666     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7667     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7668     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7669     break;
7670
7671   default:
7672     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7673   }
7674
7675 }
7676
7677 /*-----------------------------------------------------------------*/
7678 /* movLeft2Result - move byte from left to result                  */
7679 /*-----------------------------------------------------------------*/
7680 static void movLeft2Result (operand *left, int offl,
7681                             operand *result, int offr)
7682 {
7683   char *l;
7684   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7685   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7686     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7687
7688     if (*l == '@' && (IS_AOP_PREG(result))) {
7689       pic16_emitcode("mov","a,%s",l);
7690       pic16_aopPut(AOP(result),"a",offr);
7691     } else {
7692       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7693       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7694     }
7695   }
7696 }
7697
7698 /*-----------------------------------------------------------------*/
7699 /* shiftL2Left2Result - shift left two bytes from left to result   */
7700 /*-----------------------------------------------------------------*/
7701 static void shiftL2Left2Result (operand *left, int offl,
7702                                 operand *result, int offr, int shCount)
7703 {
7704   int same = pic16_sameRegs(AOP(result), AOP(left));
7705   int i;
7706
7707   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7708
7709   if (same && (offl != offr)) { // shift bytes
7710     if (offr > offl) {
7711        for(i=1;i>-1;i--) {
7712          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7713          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7714        }
7715     } else { // just treat as different later on
7716                 same = 0;
7717     }
7718   }
7719
7720   if(same) {
7721     switch(shCount) {
7722     case 0:
7723       break;
7724     case 1:
7725     case 2:
7726     case 3:
7727
7728       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7729       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7730       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7731
7732       while(--shCount) {
7733                 emitCLRC;
7734                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7735                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7736       }
7737
7738       break;
7739     case 4:
7740     case 5:
7741       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7742       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7743       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7744       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7745       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7746       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7747       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7748       if(shCount >=5) {
7749                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7750                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7751       }
7752       break;
7753     case 6:
7754       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7755       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7756       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7757       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7758       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7759       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7760       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7761       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7762       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7763       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7764       break;
7765     case 7:
7766       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7767       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7768       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7769       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7770       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7771     }
7772
7773   } else {
7774     switch(shCount) {
7775     case 0:
7776       break;
7777     case 1:
7778     case 2:
7779     case 3:
7780       /* note, use a mov/add for the shift since the mov has a
7781          chance of getting optimized out */
7782       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7783       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7784       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7785       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7786       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7787
7788       while(--shCount) {
7789                 emitCLRC;
7790                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7791                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7792       }
7793       break;
7794
7795     case 4:
7796     case 5:
7797       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7798       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7799       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7800       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7801       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7802       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7803       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7804       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7805
7806
7807       if(shCount == 5) {
7808                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7809                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7810       }
7811       break;
7812     case 6:
7813       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7814       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7815       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7816       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7817
7818       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7819       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7820       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7821       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7822       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7823       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7824       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7825       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7826       break;
7827     case 7:
7828       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7829       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7830       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7831       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7832       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7833     }
7834   }
7835
7836 }
7837 /*-----------------------------------------------------------------*/
7838 /* shiftR2Left2Result - shift right two bytes from left to result  */
7839 /*-----------------------------------------------------------------*/
7840 static void shiftR2Left2Result (operand *left, int offl,
7841                                 operand *result, int offr,
7842                                 int shCount, int sign)
7843 {
7844   int same = pic16_sameRegs(AOP(result), AOP(left));
7845   int i;
7846   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7847
7848   if (same && (offl != offr)) { // shift right bytes
7849     if (offr < offl) {
7850        for(i=0;i<2;i++) {
7851          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7852          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7853        }
7854     } else { // just treat as different later on
7855                 same = 0;
7856     }
7857   }
7858
7859   switch(shCount) {
7860   case 0:
7861     break;
7862   case 1:
7863   case 2:
7864   case 3:
7865     if(sign)
7866       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7867     else
7868       emitCLRC;
7869
7870     if(same) {
7871       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7872       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7873     } else {
7874       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7875       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7876       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7877       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7878     }
7879
7880     while(--shCount) {
7881       if(sign)
7882                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7883       else
7884                 emitCLRC;
7885       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7886       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7887     }
7888     break;
7889   case 4:
7890   case 5:
7891     if(same) {
7892
7893       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7894       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7895       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7896
7897       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7898       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7899       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7900       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7901     } else {
7902       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7903       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7904       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7905
7906       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7907       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7908       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7909       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7910       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7911     }
7912
7913     if(shCount >=5) {
7914       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7915       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7916     }
7917
7918     if(sign) {
7919       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7920       pic16_emitpcode(POC_BTFSC, 
7921                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7922       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7923     }
7924
7925     break;
7926
7927   case 6:
7928     if(same) {
7929
7930       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7931       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7932
7933       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7934       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7935       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7936       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7937       if(sign) {
7938         pic16_emitpcode(POC_BTFSC, 
7939                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
7940         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7941       }
7942       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7943       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7944       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7945       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7946     } else {
7947       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7948       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7949       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7950       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7951       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7952       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7953       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7954       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7955       if(sign) {
7956         pic16_emitpcode(POC_BTFSC, 
7957                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7958         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7959       }
7960       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7961       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7962
7963         
7964     }
7965
7966     break;
7967   case 7:
7968     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7969     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7970     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7971     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7972     if(sign) {
7973       emitSKPNC;
7974       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7975     } else 
7976       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7977   }
7978 }
7979
7980
7981 /*-----------------------------------------------------------------*/
7982 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7983 /*-----------------------------------------------------------------*/
7984 static void shiftLLeftOrResult (operand *left, int offl,
7985                                 operand *result, int offr, int shCount)
7986 {
7987     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7988
7989     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7990     /* shift left accumulator */
7991     AccLsh(shCount);
7992     /* or with result */
7993     /* back to result */
7994     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7995 }
7996
7997 /*-----------------------------------------------------------------*/
7998 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7999 /*-----------------------------------------------------------------*/
8000 static void shiftRLeftOrResult (operand *left, int offl,
8001                                 operand *result, int offr, int shCount)
8002 {
8003     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8004     
8005     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8006     /* shift right accumulator */
8007     AccRsh(shCount, 1);
8008     /* or with result */
8009     /* back to result */
8010     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8011 }
8012
8013 /*-----------------------------------------------------------------*/
8014 /* genlshOne - left shift a one byte quantity by known count       */
8015 /*-----------------------------------------------------------------*/
8016 static void genlshOne (operand *result, operand *left, int shCount)
8017 {       
8018     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8019     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8020 }
8021
8022 /*-----------------------------------------------------------------*/
8023 /* genlshTwo - left shift two bytes by known amount != 0           */
8024 /*-----------------------------------------------------------------*/
8025 static void genlshTwo (operand *result,operand *left, int shCount)
8026 {
8027     int size;
8028     
8029     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8030     size = pic16_getDataSize(result);
8031
8032     /* if shCount >= 8 */
8033     if (shCount >= 8) {
8034         shCount -= 8 ;
8035
8036         if (size > 1){
8037             if (shCount)
8038                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8039             else 
8040                 movLeft2Result(left, LSB, result, MSB16);
8041         }
8042         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8043     }
8044
8045     /*  1 <= shCount <= 7 */
8046     else {  
8047         if(size == 1)
8048             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8049         else 
8050             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8051     }
8052 }
8053
8054 /*-----------------------------------------------------------------*/
8055 /* shiftLLong - shift left one long from left to result            */
8056 /* offr = LSB or MSB16                                             */
8057 /*-----------------------------------------------------------------*/
8058 static void shiftLLong (operand *left, operand *result, int offr )
8059 {
8060     int size = AOP_SIZE(result);
8061     int same = pic16_sameRegs(AOP(left),AOP(result));
8062         int i;
8063
8064     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8065
8066         if (same && (offr == MSB16)) { //shift one byte
8067                 for(i=size-1;i>=MSB16;i--) {
8068                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8069                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8070                 }
8071         } else {
8072                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8073         }
8074         
8075     if (size >= LSB+offr ){
8076                 if (same) {
8077                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8078                 } else {
8079                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8080                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8081                 }
8082          }
8083
8084     if(size >= MSB16+offr){
8085                 if (same) {
8086                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8087                 } else {
8088                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8089                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8090                 }
8091     }
8092
8093     if(size >= MSB24+offr){
8094                 if (same) {
8095                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8096                 } else {
8097                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8098                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8099                 }
8100     }
8101
8102     if(size > MSB32+offr){
8103                 if (same) {
8104                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8105                 } else {
8106                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8107                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8108                 }
8109     }
8110     if(offr != LSB)
8111                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8112
8113 }
8114
8115 /*-----------------------------------------------------------------*/
8116 /* genlshFour - shift four byte by a known amount != 0             */
8117 /*-----------------------------------------------------------------*/
8118 static void genlshFour (operand *result, operand *left, int shCount)
8119 {
8120     int size;
8121
8122     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8123     size = AOP_SIZE(result);
8124
8125     /* if shifting more that 3 bytes */
8126     if (shCount >= 24 ) {
8127         shCount -= 24;
8128         if (shCount)
8129             /* lowest order of left goes to the highest
8130             order of the destination */
8131             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8132         else
8133             movLeft2Result(left, LSB, result, MSB32);
8134
8135                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8136                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8137                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8138
8139         return;
8140     }
8141
8142     /* more than two bytes */
8143     else if ( shCount >= 16 ) {
8144         /* lower order two bytes goes to higher order two bytes */
8145         shCount -= 16;
8146         /* if some more remaining */
8147         if (shCount)
8148             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8149         else {
8150             movLeft2Result(left, MSB16, result, MSB32);
8151             movLeft2Result(left, LSB, result, MSB24);
8152         }
8153                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8154                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8155         return;
8156     }    
8157
8158     /* if more than 1 byte */
8159     else if ( shCount >= 8 ) {
8160         /* lower order three bytes goes to higher order  three bytes */
8161         shCount -= 8;
8162         if(size == 2){
8163             if(shCount)
8164                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8165             else
8166                 movLeft2Result(left, LSB, result, MSB16);
8167         }
8168         else{   /* size = 4 */
8169             if(shCount == 0){
8170                 movLeft2Result(left, MSB24, result, MSB32);
8171                 movLeft2Result(left, MSB16, result, MSB24);
8172                 movLeft2Result(left, LSB, result, MSB16);
8173                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8174             }
8175             else if(shCount == 1)
8176                 shiftLLong(left, result, MSB16);
8177             else{
8178                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8179                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8180                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8181                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8182             }
8183         }
8184     }
8185
8186     /* 1 <= shCount <= 7 */
8187     else if(shCount <= 3)
8188     { 
8189         shiftLLong(left, result, LSB);
8190         while(--shCount >= 1)
8191             shiftLLong(result, result, LSB);
8192     }
8193     /* 3 <= shCount <= 7, optimize */
8194     else{
8195         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8196         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8197         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8198     }
8199 }
8200
8201 /*-----------------------------------------------------------------*/
8202 /* genLeftShiftLiteral - left shifting by known count              */
8203 /*-----------------------------------------------------------------*/
8204 static void genLeftShiftLiteral (operand *left,
8205                                  operand *right,
8206                                  operand *result,
8207                                  iCode *ic)
8208 {    
8209     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8210     int size;
8211
8212     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8213     pic16_freeAsmop(right,NULL,ic,TRUE);
8214
8215     pic16_aopOp(left,ic,FALSE);
8216     pic16_aopOp(result,ic,FALSE);
8217
8218     size = getSize(operandType(result));
8219
8220 #if VIEW_SIZE
8221     pic16_emitcode("; shift left ","result %d, left %d",size,
8222              AOP_SIZE(left));
8223 #endif
8224
8225     /* I suppose that the left size >= result size */
8226     if(shCount == 0){
8227         while(size--){
8228             movLeft2Result(left, size, result, size);
8229         }
8230     }
8231
8232     else if(shCount >= (size * 8))
8233         while(size--)
8234             pic16_aopPut(AOP(result),zero,size);
8235     else{
8236         switch (size) {
8237             case 1:
8238                 genlshOne (result,left,shCount);
8239                 break;
8240
8241             case 2:
8242             case 3:
8243                 genlshTwo (result,left,shCount);
8244                 break;
8245
8246             case 4:
8247                 genlshFour (result,left,shCount);
8248                 break;
8249         }
8250     }
8251     pic16_freeAsmop(left,NULL,ic,TRUE);
8252     pic16_freeAsmop(result,NULL,ic,TRUE);
8253 }
8254
8255 /*-----------------------------------------------------------------*
8256  * genMultiAsm - repeat assembly instruction for size of register.
8257  * if endian == 1, then the high byte (i.e base address + size of 
8258  * register) is used first else the low byte is used first;
8259  *-----------------------------------------------------------------*/
8260 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8261 {
8262
8263   int offset = 0;
8264
8265   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8266
8267   if(!reg)
8268     return;
8269
8270   if(!endian) {
8271     endian = 1;
8272   } else {
8273     endian = -1;
8274     offset = size-1;
8275   }
8276
8277   while(size--) {
8278     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8279     offset += endian;
8280   }
8281
8282 }
8283 /*-----------------------------------------------------------------*/
8284 /* genLeftShift - generates code for left shifting                 */
8285 /*-----------------------------------------------------------------*/
8286 static void genLeftShift (iCode *ic)
8287 {
8288   operand *left,*right, *result;
8289   int size, offset;
8290   char *l;
8291   symbol *tlbl , *tlbl1;
8292   pCodeOp *pctemp;
8293
8294   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8295
8296   right = IC_RIGHT(ic);
8297   left  = IC_LEFT(ic);
8298   result = IC_RESULT(ic);
8299
8300   pic16_aopOp(right,ic,FALSE);
8301
8302   /* if the shift count is known then do it 
8303      as efficiently as possible */
8304   if (AOP_TYPE(right) == AOP_LIT) {
8305     genLeftShiftLiteral (left,right,result,ic);
8306     return ;
8307   }
8308
8309   /* shift count is unknown then we have to form 
8310      a loop get the loop count in B : Note: we take
8311      only the lower order byte since shifting
8312      more that 32 bits make no sense anyway, ( the
8313      largest size of an object can be only 32 bits ) */  
8314
8315     
8316   pic16_aopOp(left,ic,FALSE);
8317   pic16_aopOp(result,ic,FALSE);
8318
8319   /* now move the left to the result if they are not the
8320      same */
8321   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8322       AOP_SIZE(result) > 1) {
8323
8324     size = AOP_SIZE(result);
8325     offset=0;
8326     while (size--) {
8327       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8328       if (*l == '@' && (IS_AOP_PREG(result))) {
8329
8330         pic16_emitcode("mov","a,%s",l);
8331         pic16_aopPut(AOP(result),"a",offset);
8332       } else {
8333         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8334         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8335         //pic16_aopPut(AOP(result),l,offset);
8336       }
8337       offset++;
8338     }
8339   }
8340
8341   size = AOP_SIZE(result);
8342
8343   /* if it is only one byte then */
8344   if (size == 1) {
8345     if(optimized_for_speed) {
8346       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8347       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8348       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8349       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8350       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8351       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8352       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8353       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8354       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8355       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8356       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8357       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8358     } else {
8359
8360       tlbl = newiTempLabel(NULL);
8361       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8362                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8363                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8364       }
8365
8366       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8367       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8368       pic16_emitpLabel(tlbl->key);
8369       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8370       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8371       emitSKPC;
8372       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8373     }
8374     goto release ;
8375   }
8376     
8377   if (pic16_sameRegs(AOP(left),AOP(result))) {
8378
8379     tlbl = newiTempLabel(NULL);
8380     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8381     genMultiAsm(POC_RRCF, result, size,1);
8382     pic16_emitpLabel(tlbl->key);
8383     genMultiAsm(POC_RLCF, result, size,0);
8384     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8385     emitSKPC;
8386     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8387     goto release;
8388   }
8389
8390   //tlbl = newiTempLabel(NULL);
8391   //offset = 0 ;   
8392   //tlbl1 = newiTempLabel(NULL);
8393
8394   //reAdjustPreg(AOP(result));    
8395     
8396   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8397   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8398   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8399   //MOVA(l);
8400   //pic16_emitcode("add","a,acc");         
8401   //pic16_aopPut(AOP(result),"a",offset++);
8402   //while (--size) {
8403   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8404   //  MOVA(l);
8405   //  pic16_emitcode("rlc","a");         
8406   //  pic16_aopPut(AOP(result),"a",offset++);
8407   //}
8408   //reAdjustPreg(AOP(result));
8409
8410   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8411   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8412
8413
8414   tlbl = newiTempLabel(NULL);
8415   tlbl1= newiTempLabel(NULL);
8416
8417   size = AOP_SIZE(result);
8418   offset = 1;
8419
8420   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8421
8422   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8423
8424   /* offset should be 0, 1 or 3 */
8425   
8426   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8427   emitSKPNZ;
8428   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8429
8430   pic16_emitpcode(POC_MOVWF, pctemp);
8431
8432
8433   pic16_emitpLabel(tlbl->key);
8434
8435   emitCLRC;
8436   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8437   while(--size)
8438     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8439
8440   pic16_emitpcode(POC_DECFSZ,  pctemp);
8441   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8442   pic16_emitpLabel(tlbl1->key);
8443
8444   pic16_popReleaseTempReg(pctemp);
8445
8446
8447  release:
8448   pic16_freeAsmop (right,NULL,ic,TRUE);
8449   pic16_freeAsmop(left,NULL,ic,TRUE);
8450   pic16_freeAsmop(result,NULL,ic,TRUE);
8451 }
8452
8453 /*-----------------------------------------------------------------*/
8454 /* genrshOne - right shift a one byte quantity by known count      */
8455 /*-----------------------------------------------------------------*/
8456 static void genrshOne (operand *result, operand *left,
8457                        int shCount, int sign)
8458 {
8459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8460     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8461 }
8462
8463 /*-----------------------------------------------------------------*/
8464 /* genrshTwo - right shift two bytes by known amount != 0          */
8465 /*-----------------------------------------------------------------*/
8466 static void genrshTwo (operand *result,operand *left,
8467                        int shCount, int sign)
8468 {
8469   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8470   /* if shCount >= 8 */
8471   if (shCount >= 8) {
8472     shCount -= 8 ;
8473     if (shCount)
8474       shiftR1Left2Result(left, MSB16, result, LSB,
8475                          shCount, sign);
8476     else
8477       movLeft2Result(left, MSB16, result, LSB);
8478
8479     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8480
8481     if(sign) {
8482       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8483       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8484     }
8485   }
8486
8487   /*  1 <= shCount <= 7 */
8488   else
8489     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8490 }
8491
8492 /*-----------------------------------------------------------------*/
8493 /* shiftRLong - shift right one long from left to result           */
8494 /* offl = LSB or MSB16                                             */
8495 /*-----------------------------------------------------------------*/
8496 static void shiftRLong (operand *left, int offl,
8497                         operand *result, int sign)
8498 {
8499     int size = AOP_SIZE(result);
8500     int same = pic16_sameRegs(AOP(left),AOP(result));
8501     int i;
8502     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8503
8504         if (same && (offl == MSB16)) { //shift one byte right
8505                 for(i=MSB16;i<size;i++) {
8506                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8507                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8508                 }
8509         }
8510
8511     if(sign)
8512                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8513         else
8514                 emitCLRC;
8515
8516         if (same) {
8517                 if (offl == LSB)
8518                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8519         } else {
8520         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8521         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8522         }
8523
8524     if(offl == MSB16) {
8525         /* add sign of "a" */
8526         pic16_addSign(result, MSB32, sign);
8527         }
8528
8529         if (same) {
8530         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8531         } else {
8532         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8533         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8534         }
8535         
8536         if (same) {
8537         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8538         } else {
8539         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8540         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8541         }
8542
8543         if (same) {
8544         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8545         } else {
8546         if(offl == LSB){
8547                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8548                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8549         }
8550         }
8551 }
8552
8553 /*-----------------------------------------------------------------*/
8554 /* genrshFour - shift four byte by a known amount != 0             */
8555 /*-----------------------------------------------------------------*/
8556 static void genrshFour (operand *result, operand *left,
8557                         int shCount, int sign)
8558 {
8559   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8560   /* if shifting more that 3 bytes */
8561   if(shCount >= 24 ) {
8562     shCount -= 24;
8563     if(shCount)
8564       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8565     else
8566       movLeft2Result(left, MSB32, result, LSB);
8567
8568     pic16_addSign(result, MSB16, sign);
8569   }
8570   else if(shCount >= 16){
8571     shCount -= 16;
8572     if(shCount)
8573       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8574     else{
8575       movLeft2Result(left, MSB24, result, LSB);
8576       movLeft2Result(left, MSB32, result, MSB16);
8577     }
8578     pic16_addSign(result, MSB24, sign);
8579   }
8580   else if(shCount >= 8){
8581     shCount -= 8;
8582     if(shCount == 1)
8583       shiftRLong(left, MSB16, result, sign);
8584     else if(shCount == 0){
8585       movLeft2Result(left, MSB16, result, LSB);
8586       movLeft2Result(left, MSB24, result, MSB16);
8587       movLeft2Result(left, MSB32, result, MSB24);
8588       pic16_addSign(result, MSB32, sign);
8589     }
8590     else{ //shcount >= 2
8591       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8592       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8593       /* the last shift is signed */
8594       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8595       pic16_addSign(result, MSB32, sign);
8596     }
8597   }
8598   else{   /* 1 <= shCount <= 7 */
8599     if(shCount <= 2){
8600       shiftRLong(left, LSB, result, sign);
8601       if(shCount == 2)
8602         shiftRLong(result, LSB, result, sign);
8603     }
8604     else{
8605       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8606       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8607       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8608     }
8609   }
8610 }
8611
8612 /*-----------------------------------------------------------------*/
8613 /* genRightShiftLiteral - right shifting by known count            */
8614 /*-----------------------------------------------------------------*/
8615 static void genRightShiftLiteral (operand *left,
8616                                   operand *right,
8617                                   operand *result,
8618                                   iCode *ic,
8619                                   int sign)
8620 {    
8621   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8622   int lsize,res_size;
8623
8624   pic16_freeAsmop(right,NULL,ic,TRUE);
8625
8626   pic16_aopOp(left,ic,FALSE);
8627   pic16_aopOp(result,ic,FALSE);
8628
8629   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8630
8631 #if VIEW_SIZE
8632   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8633                  AOP_SIZE(left));
8634 #endif
8635
8636   lsize = pic16_getDataSize(left);
8637   res_size = pic16_getDataSize(result);
8638   /* test the LEFT size !!! */
8639
8640   /* I suppose that the left size >= result size */
8641   if(shCount == 0){
8642     while(res_size--)
8643       movLeft2Result(left, lsize, result, res_size);
8644   }
8645
8646   else if(shCount >= (lsize * 8)){
8647
8648     if(res_size == 1) {
8649       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8650       if(sign) {
8651         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8652         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8653       }
8654     } else {
8655
8656       if(sign) {
8657         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8658         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8659         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8660         while(res_size--)
8661           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8662
8663       } else {
8664
8665         while(res_size--)
8666           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8667       }
8668     }
8669   } else {
8670
8671     switch (res_size) {
8672     case 1:
8673       genrshOne (result,left,shCount,sign);
8674       break;
8675
8676     case 2:
8677       genrshTwo (result,left,shCount,sign);
8678       break;
8679
8680     case 4:
8681       genrshFour (result,left,shCount,sign);
8682       break;
8683     default :
8684       break;
8685     }
8686
8687   }
8688
8689   pic16_freeAsmop(left,NULL,ic,TRUE);
8690   pic16_freeAsmop(result,NULL,ic,TRUE);
8691 }
8692
8693 /*-----------------------------------------------------------------*/
8694 /* genSignedRightShift - right shift of signed number              */
8695 /*-----------------------------------------------------------------*/
8696 static void genSignedRightShift (iCode *ic)
8697 {
8698   operand *right, *left, *result;
8699   int size, offset;
8700   //  char *l;
8701   symbol *tlbl, *tlbl1 ;
8702   pCodeOp *pctemp;
8703
8704   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8705
8706   /* we do it the hard way put the shift count in b
8707      and loop thru preserving the sign */
8708   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8709
8710   right = IC_RIGHT(ic);
8711   left  = IC_LEFT(ic);
8712   result = IC_RESULT(ic);
8713
8714   pic16_aopOp(right,ic,FALSE);  
8715   pic16_aopOp(left,ic,FALSE);
8716   pic16_aopOp(result,ic,FALSE);
8717
8718
8719   if ( AOP_TYPE(right) == AOP_LIT) {
8720     genRightShiftLiteral (left,right,result,ic,1);
8721     return ;
8722   }
8723   /* shift count is unknown then we have to form 
8724      a loop get the loop count in B : Note: we take
8725      only the lower order byte since shifting
8726      more that 32 bits make no sense anyway, ( the
8727      largest size of an object can be only 32 bits ) */  
8728
8729   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8730   //pic16_emitcode("inc","b");
8731   //pic16_freeAsmop (right,NULL,ic,TRUE);
8732   //pic16_aopOp(left,ic,FALSE);
8733   //pic16_aopOp(result,ic,FALSE);
8734
8735   /* now move the left to the result if they are not the
8736      same */
8737   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8738       AOP_SIZE(result) > 1) {
8739
8740     size = AOP_SIZE(result);
8741     offset=0;
8742     while (size--) { 
8743       /*
8744         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8745         if (*l == '@' && IS_AOP_PREG(result)) {
8746
8747         pic16_emitcode("mov","a,%s",l);
8748         pic16_aopPut(AOP(result),"a",offset);
8749         } else
8750         pic16_aopPut(AOP(result),l,offset);
8751       */
8752       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8753       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8754
8755       offset++;
8756     }
8757   }
8758
8759   /* mov the highest order bit to OVR */    
8760   tlbl = newiTempLabel(NULL);
8761   tlbl1= newiTempLabel(NULL);
8762
8763   size = AOP_SIZE(result);
8764   offset = size - 1;
8765
8766   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8767
8768   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8769
8770   /* offset should be 0, 1 or 3 */
8771   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8772   emitSKPNZ;
8773   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8774
8775   pic16_emitpcode(POC_MOVWF, pctemp);
8776
8777
8778   pic16_emitpLabel(tlbl->key);
8779
8780   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8781   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8782
8783   while(--size) {
8784     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8785   }
8786
8787   pic16_emitpcode(POC_DECFSZ,  pctemp);
8788   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8789   pic16_emitpLabel(tlbl1->key);
8790
8791   pic16_popReleaseTempReg(pctemp);
8792 #if 0
8793   size = AOP_SIZE(result);
8794   offset = size - 1;
8795   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8796   pic16_emitcode("rlc","a");
8797   pic16_emitcode("mov","ov,c");
8798   /* if it is only one byte then */
8799   if (size == 1) {
8800     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8801     MOVA(l);
8802     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8803     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8804     pic16_emitcode("mov","c,ov");
8805     pic16_emitcode("rrc","a");
8806     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8807     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8808     pic16_aopPut(AOP(result),"a",0);
8809     goto release ;
8810   }
8811
8812   reAdjustPreg(AOP(result));
8813   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8814   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8815   pic16_emitcode("mov","c,ov");
8816   while (size--) {
8817     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8818     MOVA(l);
8819     pic16_emitcode("rrc","a");         
8820     pic16_aopPut(AOP(result),"a",offset--);
8821   }
8822   reAdjustPreg(AOP(result));
8823   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8824   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8825
8826  release:
8827 #endif
8828
8829   pic16_freeAsmop(left,NULL,ic,TRUE);
8830   pic16_freeAsmop(result,NULL,ic,TRUE);
8831   pic16_freeAsmop(right,NULL,ic,TRUE);
8832 }
8833
8834 /*-----------------------------------------------------------------*/
8835 /* genRightShift - generate code for right shifting                */
8836 /*-----------------------------------------------------------------*/
8837 static void genRightShift (iCode *ic)
8838 {
8839     operand *right, *left, *result;
8840     sym_link *letype ;
8841     int size, offset;
8842     char *l;
8843     symbol *tlbl, *tlbl1 ;
8844
8845     /* if signed then we do it the hard way preserve the
8846     sign bit moving it inwards */
8847     letype = getSpec(operandType(IC_LEFT(ic)));
8848     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8849
8850     if (!SPEC_USIGN(letype)) {
8851         genSignedRightShift (ic);
8852         return ;
8853     }
8854
8855     /* signed & unsigned types are treated the same : i.e. the
8856     signed is NOT propagated inwards : quoting from the
8857     ANSI - standard : "for E1 >> E2, is equivalent to division
8858     by 2**E2 if unsigned or if it has a non-negative value,
8859     otherwise the result is implementation defined ", MY definition
8860     is that the sign does not get propagated */
8861
8862     right = IC_RIGHT(ic);
8863     left  = IC_LEFT(ic);
8864     result = IC_RESULT(ic);
8865
8866     pic16_aopOp(right,ic,FALSE);
8867
8868     /* if the shift count is known then do it 
8869     as efficiently as possible */
8870     if (AOP_TYPE(right) == AOP_LIT) {
8871         genRightShiftLiteral (left,right,result,ic, 0);
8872         return ;
8873     }
8874
8875     /* shift count is unknown then we have to form 
8876     a loop get the loop count in B : Note: we take
8877     only the lower order byte since shifting
8878     more that 32 bits make no sense anyway, ( the
8879     largest size of an object can be only 32 bits ) */  
8880
8881     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8882     pic16_emitcode("inc","b");
8883     pic16_aopOp(left,ic,FALSE);
8884     pic16_aopOp(result,ic,FALSE);
8885
8886     /* now move the left to the result if they are not the
8887     same */
8888     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8889         AOP_SIZE(result) > 1) {
8890
8891         size = AOP_SIZE(result);
8892         offset=0;
8893         while (size--) {
8894             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8895             if (*l == '@' && IS_AOP_PREG(result)) {
8896
8897                 pic16_emitcode("mov","a,%s",l);
8898                 pic16_aopPut(AOP(result),"a",offset);
8899             } else
8900                 pic16_aopPut(AOP(result),l,offset);
8901             offset++;
8902         }
8903     }
8904
8905     tlbl = newiTempLabel(NULL);
8906     tlbl1= newiTempLabel(NULL);
8907     size = AOP_SIZE(result);
8908     offset = size - 1;
8909
8910     /* if it is only one byte then */
8911     if (size == 1) {
8912
8913       tlbl = newiTempLabel(NULL);
8914       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8915         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8916         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8917       }
8918
8919       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8920       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8921       pic16_emitpLabel(tlbl->key);
8922       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8923       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8924       emitSKPC;
8925       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8926
8927       goto release ;
8928     }
8929
8930     reAdjustPreg(AOP(result));
8931     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8932     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8933     CLRC;
8934     while (size--) {
8935         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8936         MOVA(l);
8937         pic16_emitcode("rrc","a");         
8938         pic16_aopPut(AOP(result),"a",offset--);
8939     }
8940     reAdjustPreg(AOP(result));
8941
8942     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8943     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8944
8945 release:
8946     pic16_freeAsmop(left,NULL,ic,TRUE);
8947     pic16_freeAsmop (right,NULL,ic,TRUE);
8948     pic16_freeAsmop(result,NULL,ic,TRUE);
8949 }
8950
8951 /*-----------------------------------------------------------------*/
8952 /* genUnpackBits - generates code for unpacking bits               */
8953 /*-----------------------------------------------------------------*/
8954 static void genUnpackBits (operand *result, char *rname, int ptype)
8955 {    
8956     int shCnt ;
8957     int rlen = 0 ;
8958     sym_link *etype;
8959     int offset = 0 ;
8960
8961         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8962         etype = getSpec(operandType(result));
8963
8964         /* read the first byte  */
8965         switch (ptype) {
8966                 case POINTER:
8967                 case IPOINTER:
8968                 case PPOINTER:
8969                 case FPOINTER:
8970                 case GPOINTER:
8971                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8972                         break;
8973                 case CPOINTER:
8974                         pic16_emitcode("clr","a");
8975                         pic16_emitcode("movc","a","@a+dptr");
8976                         break;
8977         }
8978         
8979
8980         /* if we have bitdisplacement then it fits   */
8981         /* into this byte completely or if length is */
8982         /* less than a byte                          */
8983         if ((shCnt = SPEC_BSTR(etype)) || 
8984                 (SPEC_BLEN(etype) <= 8))  {
8985
8986                 /* shift right acc */
8987                 AccRsh(shCnt, 0);
8988
8989                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8990                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8991
8992 /* VR -- normally I would use the following, but since we use the hack,
8993  * to avoid the masking from AccRsh, why not mask it right now? */
8994
8995 /*
8996                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8997 */
8998
8999                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9000           return ;
9001         }
9002
9003
9004
9005         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9006         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9007         exit(-1);
9008
9009     /* bit field did not fit in a byte  */
9010     rlen = SPEC_BLEN(etype) - 8;
9011     pic16_aopPut(AOP(result),"a",offset++);
9012
9013     while (1)  {
9014
9015         switch (ptype) {
9016         case POINTER:
9017         case IPOINTER:
9018             pic16_emitcode("inc","%s",rname);
9019             pic16_emitcode("mov","a,@%s",rname);
9020             break;
9021             
9022         case PPOINTER:
9023             pic16_emitcode("inc","%s",rname);
9024             pic16_emitcode("movx","a,@%s",rname);
9025             break;
9026
9027         case FPOINTER:
9028             pic16_emitcode("inc","dptr");
9029             pic16_emitcode("movx","a,@dptr");
9030             break;
9031             
9032         case CPOINTER:
9033             pic16_emitcode("clr","a");
9034             pic16_emitcode("inc","dptr");
9035             pic16_emitcode("movc","a","@a+dptr");
9036             break;
9037             
9038         case GPOINTER:
9039             pic16_emitcode("inc","dptr");
9040             pic16_emitcode("lcall","__gptrget");
9041             break;
9042         }
9043
9044         rlen -= 8;            
9045         /* if we are done */
9046         if ( rlen <= 0 )
9047             break ;
9048         
9049         pic16_aopPut(AOP(result),"a",offset++);
9050                               
9051     }
9052     
9053     if (rlen) {
9054         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9055         pic16_aopPut(AOP(result),"a",offset);          
9056     }
9057     
9058     return ;
9059 }
9060
9061
9062 static void genDataPointerGet(operand *left,
9063                               operand *result,
9064                               iCode *ic)
9065 {
9066   int size, offset = 0, leoffset=0 ;
9067
9068         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9069         pic16_aopOp(result, ic, FALSE);
9070
9071         size = AOP_SIZE(result);
9072 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9073
9074
9075 #if 0
9076         /* The following tests may save a redudant movff instruction when
9077          * accessing unions */
9078          
9079         /* if they are the same */
9080         if (operandsEqu (left, result)) {
9081                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9082                 goto release;
9083         }
9084 #endif
9085
9086 #if 0
9087         /* if they are the same registers */
9088         if (pic16_sameRegs(AOP(left),AOP(result))) {
9089                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9090                 goto release;
9091         }
9092 #endif
9093
9094 #if 1
9095         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9096                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9097                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9098                 goto release;
9099         }
9100 #endif
9101
9102
9103 #if 0
9104         if ( AOP_TYPE(left) == AOP_PCODE) {
9105                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9106                                 AOP(left)->aopu.pcop->name,
9107                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9108                                 PCOR(AOP(left)->aopu.pcop)->instance:
9109                                 PCOI(AOP(left)->aopu.pcop)->offset);
9110         }
9111 #endif
9112
9113         if(AOP(left)->aopu.pcop->type == PO_DIR)
9114                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9115
9116         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9117
9118         while (size--) {
9119                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9120                 
9121                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9122                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9123                         mov2w(AOP(left), offset); // patch 8
9124                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9125                 } else {
9126                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9127                                 pic16_popGet(AOP(left), offset), //patch 8
9128                                 pic16_popGet(AOP(result), offset)));
9129                 }
9130
9131                 offset++;
9132                 leoffset++;
9133         }
9134
9135 release:
9136     pic16_freeAsmop(result,NULL,ic,TRUE);
9137 }
9138
9139 void pic16_loadFSR0(operand *op)
9140 {
9141         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9142 }
9143
9144
9145 /*-----------------------------------------------------------------*/
9146 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9147 /*-----------------------------------------------------------------*/
9148 static void genNearPointerGet (operand *left, 
9149                                operand *result, 
9150                                iCode *ic)
9151 {
9152     asmop *aop = NULL;
9153     //regs *preg = NULL ;
9154     sym_link *rtype, *retype;
9155     sym_link *ltype = operandType(left);    
9156
9157         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9158         rtype = operandType(result);
9159         retype= getSpec(rtype);
9160     
9161         pic16_aopOp(left,ic,FALSE);
9162
9163 //      pic16_DumpOp("(left)",left);
9164 //      pic16_DumpOp("(result)",result);
9165
9166         /* if left is rematerialisable and
9167          * result is not bit variable type and
9168          * the left is pointer to data space i.e
9169          * lower 128 bytes of space */
9170         if (AOP_TYPE(left) == AOP_PCODE
9171                 && !IS_BITFIELD(retype)
9172                 && DCL_TYPE(ltype) == POINTER) {
9173
9174                 genDataPointerGet (left,result,ic);
9175                 pic16_freeAsmop(left, NULL, ic, TRUE);
9176           return ;
9177         }
9178     
9179         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9180
9181         /* if the value is already in a pointer register
9182          * then don't need anything more */
9183         if (!AOP_INPREG(AOP(left))) {
9184                 /* otherwise get a free pointer register */
9185                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9186                 
9187                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9188                 if( (AOP_TYPE(left) == AOP_PCODE) 
9189                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9190                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9191                 {
9192                         pic16_loadFSR0( left );  // patch 10
9193                 } else {
9194                         // set up FSR0 with address from left
9195                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9196                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9197                 }
9198         }
9199 //       else
9200 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9201     
9202         pic16_aopOp (result,ic,FALSE);
9203     
9204       /* if bitfield then unpack the bits */
9205     if (IS_BITFIELD(retype)) 
9206         genUnpackBits (result, NULL, POINTER);
9207     else {
9208         /* we have can just get the values */
9209       int size = AOP_SIZE(result);
9210       int offset = 0;   
9211         
9212       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9213
9214
9215         /* fsr0 is loaded already -- VR */
9216 //      pic16_loadFSR0( left );
9217
9218 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9219 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9220       while(size--) {
9221
9222         if(size) {
9223                 pic16_emitpcode(POC_MOVFF,
9224                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9225                                 pic16_popGet(AOP(result), offset++)));
9226         } else {
9227                 pic16_emitpcode(POC_MOVFF,
9228                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9229                                 pic16_popGet(AOP(result), offset++)));
9230         }
9231       }
9232 #if 0
9233 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9234 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9235         if(size)
9236           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9237 #endif
9238 /*
9239         while (size--) {
9240             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9241
9242                 pic16_emitcode("mov","a,@%s",rname);
9243                 pic16_aopPut(AOP(result),"a",offset);
9244             } else {
9245                 sprintf(buffer,"@%s",rname);
9246                 pic16_aopPut(AOP(result),buffer,offset);
9247             }
9248             offset++ ;
9249             if (size)
9250                 pic16_emitcode("inc","%s",rname);
9251         }
9252 */
9253     }
9254
9255     /* now some housekeeping stuff */
9256     if (aop) {
9257         /* we had to allocate for this iCode */
9258     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9259         pic16_freeAsmop(NULL,aop,ic,TRUE);
9260     } else { 
9261         /* we did not allocate which means left
9262            already in a pointer register, then
9263            if size > 0 && this could be used again
9264            we have to point it back to where it 
9265            belongs */
9266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9267         if (AOP_SIZE(result) > 1 &&
9268             !OP_SYMBOL(left)->remat &&
9269             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9270               ic->depth )) {
9271 //          int size = AOP_SIZE(result) - 1;
9272 //          while (size--)
9273 //              pic16_emitcode("dec","%s",rname);
9274         }
9275     }
9276
9277     /* done */
9278     pic16_freeAsmop(left,NULL,ic,TRUE);
9279     pic16_freeAsmop(result,NULL,ic,TRUE);
9280      
9281 }
9282
9283 /*-----------------------------------------------------------------*/
9284 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9285 /*-----------------------------------------------------------------*/
9286 static void genPagedPointerGet (operand *left, 
9287                                operand *result, 
9288                                iCode *ic)
9289 {
9290     asmop *aop = NULL;
9291     regs *preg = NULL ;
9292     char *rname ;
9293     sym_link *rtype, *retype;    
9294
9295     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9296
9297     rtype = operandType(result);
9298     retype= getSpec(rtype);
9299     
9300     pic16_aopOp(left,ic,FALSE);
9301
9302   /* if the value is already in a pointer register
9303        then don't need anything more */
9304     if (!AOP_INPREG(AOP(left))) {
9305         /* otherwise get a free pointer register */
9306         aop = newAsmop(0);
9307         preg = getFreePtr(ic,&aop,FALSE);
9308         pic16_emitcode("mov","%s,%s",
9309                 preg->name,
9310                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9311         rname = preg->name ;
9312     } else
9313         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9314     
9315     pic16_freeAsmop(left,NULL,ic,TRUE);
9316     pic16_aopOp (result,ic,FALSE);
9317
9318     /* if bitfield then unpack the bits */
9319     if (IS_BITFIELD(retype)) 
9320         genUnpackBits (result,rname,PPOINTER);
9321     else {
9322         /* we have can just get the values */
9323         int size = AOP_SIZE(result);
9324         int offset = 0 ;        
9325         
9326         while (size--) {
9327             
9328             pic16_emitcode("movx","a,@%s",rname);
9329             pic16_aopPut(AOP(result),"a",offset);
9330             
9331             offset++ ;
9332             
9333             if (size)
9334                 pic16_emitcode("inc","%s",rname);
9335         }
9336     }
9337
9338     /* now some housekeeping stuff */
9339     if (aop) {
9340         /* we had to allocate for this iCode */
9341         pic16_freeAsmop(NULL,aop,ic,TRUE);
9342     } else { 
9343         /* we did not allocate which means left
9344            already in a pointer register, then
9345            if size > 0 && this could be used again
9346            we have to point it back to where it 
9347            belongs */
9348         if (AOP_SIZE(result) > 1 &&
9349             !OP_SYMBOL(left)->remat &&
9350             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9351               ic->depth )) {
9352             int size = AOP_SIZE(result) - 1;
9353             while (size--)
9354                 pic16_emitcode("dec","%s",rname);
9355         }
9356     }
9357
9358     /* done */
9359     pic16_freeAsmop(result,NULL,ic,TRUE);
9360     
9361         
9362 }
9363
9364 /*-----------------------------------------------------------------*/
9365 /* genFarPointerGet - gget value from far space                    */
9366 /*-----------------------------------------------------------------*/
9367 static void genFarPointerGet (operand *left,
9368                               operand *result, iCode *ic)
9369 {
9370     int size, offset ;
9371     sym_link *retype = getSpec(operandType(result));
9372
9373     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9374
9375     pic16_aopOp(left,ic,FALSE);
9376
9377     /* if the operand is already in dptr 
9378     then we do nothing else we move the value to dptr */
9379     if (AOP_TYPE(left) != AOP_STR) {
9380         /* if this is remateriazable */
9381         if (AOP_TYPE(left) == AOP_IMMD)
9382             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9383         else { /* we need to get it byte by byte */
9384             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9385             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9386             if (options.model == MODEL_FLAT24)
9387             {
9388                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9389             }
9390         }
9391     }
9392     /* so dptr know contains the address */
9393     pic16_freeAsmop(left,NULL,ic,TRUE);
9394     pic16_aopOp(result,ic,FALSE);
9395
9396     /* if bit then unpack */
9397     if (IS_BITFIELD(retype)) 
9398         genUnpackBits(result,"dptr",FPOINTER);
9399     else {
9400         size = AOP_SIZE(result);
9401         offset = 0 ;
9402
9403         while (size--) {
9404             pic16_emitcode("movx","a,@dptr");
9405             pic16_aopPut(AOP(result),"a",offset++);
9406             if (size)
9407                 pic16_emitcode("inc","dptr");
9408         }
9409     }
9410
9411     pic16_freeAsmop(result,NULL,ic,TRUE);
9412 }
9413 #if 0
9414 /*-----------------------------------------------------------------*/
9415 /* genCodePointerGet - get value from code space                  */
9416 /*-----------------------------------------------------------------*/
9417 static void genCodePointerGet (operand *left,
9418                                 operand *result, iCode *ic)
9419 {
9420     int size, offset ;
9421     sym_link *retype = getSpec(operandType(result));
9422
9423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9424
9425     pic16_aopOp(left,ic,FALSE);
9426
9427     /* if the operand is already in dptr 
9428     then we do nothing else we move the value to dptr */
9429     if (AOP_TYPE(left) != AOP_STR) {
9430         /* if this is remateriazable */
9431         if (AOP_TYPE(left) == AOP_IMMD)
9432             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9433         else { /* we need to get it byte by byte */
9434             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9435             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9436             if (options.model == MODEL_FLAT24)
9437             {
9438                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9439             }
9440         }
9441     }
9442     /* so dptr know contains the address */
9443     pic16_freeAsmop(left,NULL,ic,TRUE);
9444     pic16_aopOp(result,ic,FALSE);
9445
9446     /* if bit then unpack */
9447     if (IS_BITFIELD(retype)) 
9448         genUnpackBits(result,"dptr",CPOINTER);
9449     else {
9450         size = AOP_SIZE(result);
9451         offset = 0 ;
9452
9453         while (size--) {
9454             pic16_emitcode("clr","a");
9455             pic16_emitcode("movc","a,@a+dptr");
9456             pic16_aopPut(AOP(result),"a",offset++);
9457             if (size)
9458                 pic16_emitcode("inc","dptr");
9459         }
9460     }
9461
9462     pic16_freeAsmop(result,NULL,ic,TRUE);
9463 }
9464 #endif
9465 /*-----------------------------------------------------------------*/
9466 /* genGenPointerGet - gget value from generic pointer space        */
9467 /*-----------------------------------------------------------------*/
9468 static void genGenPointerGet (operand *left,
9469                               operand *result, iCode *ic)
9470 {
9471   int size, offset, lit;
9472   sym_link *retype = getSpec(operandType(result));
9473
9474         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9475         pic16_aopOp(left,ic,FALSE);
9476         pic16_aopOp(result,ic,FALSE);
9477         size = AOP_SIZE(result);
9478
9479         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9480
9481         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9482
9483                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9484                 // load FSR0 from immediate
9485                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9486
9487 //              pic16_loadFSR0( left );
9488
9489                 offset = 0;
9490                 while(size--) {
9491                         if(size) {
9492                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9493                         } else {
9494                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9495                         }
9496                         offset++;
9497                 }
9498                 goto release;
9499
9500         }
9501         else { /* we need to get it byte by byte */
9502                 // set up FSR0 with address from left
9503                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9504                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9505
9506                 offset = 0 ;
9507
9508                 while(size--) {
9509                         if(size) {
9510                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9511                         } else {
9512                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9513                         }
9514                         offset++;
9515                 }
9516                 goto release;
9517         }
9518
9519   /* if bit then unpack */
9520         if (IS_BITFIELD(retype)) 
9521                 genUnpackBits(result,"BAD",GPOINTER);
9522
9523         release:
9524         pic16_freeAsmop(left,NULL,ic,TRUE);
9525         pic16_freeAsmop(result,NULL,ic,TRUE);
9526
9527 }
9528
9529 /*-----------------------------------------------------------------*/
9530 /* genConstPointerGet - get value from const generic pointer space */
9531 /*-----------------------------------------------------------------*/
9532 static void genConstPointerGet (operand *left,
9533                                 operand *result, iCode *ic)
9534 {
9535   //sym_link *retype = getSpec(operandType(result));
9536   // symbol *albl = newiTempLabel(NULL);        // patch 15
9537   // symbol *blbl = newiTempLabel(NULL);        //
9538   // PIC_OPCODE poc;                            // patch 15
9539   int size;
9540   int offset = 0;
9541
9542   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9543   pic16_aopOp(left,ic,FALSE);
9544   pic16_aopOp(result,ic,TRUE);
9545   size = AOP_SIZE(result);
9546
9547   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9548
9549   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9550 #if 0                                                                   // patch 15
9551   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9552   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9553   pic16_emitpLabel(albl->key);
9554
9555   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9556     
9557   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9558   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9559   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9560   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9561   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9562
9563   pic16_emitpLabel(blbl->key);
9564
9565   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9566 #endif                                                                  // patch 15
9567
9568
9569   // set up table pointer
9570   if( (AOP_TYPE(left) == AOP_PCODE) 
9571       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9572           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9573     {
9574       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9575       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9576       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9577       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9578       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9579       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9580     }
9581   else
9582     {
9583       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9584       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9585       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9586     }
9587
9588
9589   while(size--)
9590     {
9591       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9592       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9593       offset++;
9594     }
9595     
9596   pic16_freeAsmop(left,NULL,ic,TRUE);
9597   pic16_freeAsmop(result,NULL,ic,TRUE);
9598
9599 }
9600
9601
9602 /*-----------------------------------------------------------------*/
9603 /* genPointerGet - generate code for pointer get                   */
9604 /*-----------------------------------------------------------------*/
9605 static void genPointerGet (iCode *ic)
9606 {
9607     operand *left, *result ;
9608     sym_link *type, *etype;
9609     int p_type;
9610
9611     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9612
9613     left = IC_LEFT(ic);
9614     result = IC_RESULT(ic) ;
9615
9616     /* depending on the type of pointer we need to
9617     move it to the correct pointer register */
9618     type = operandType(left);
9619     etype = getSpec(type);
9620
9621 #if 0
9622     if (IS_PTR_CONST(type))
9623 #else
9624     if (IS_CODEPTR(type))
9625 #endif
9626       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9627
9628     /* if left is of type of pointer then it is simple */
9629     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9630         p_type = DCL_TYPE(type);
9631     else {
9632         /* we have to go by the storage class */
9633         p_type = PTR_TYPE(SPEC_OCLS(etype));
9634
9635         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9636
9637         if (SPEC_OCLS(etype)->codesp ) {
9638           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9639           //p_type = CPOINTER ; 
9640         }
9641         else
9642             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9643               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9644                /*p_type = FPOINTER ;*/ 
9645             else
9646                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9647                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9648 /*                  p_type = PPOINTER; */
9649                 else
9650                     if (SPEC_OCLS(etype) == idata )
9651                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9652 /*                      p_type = IPOINTER; */
9653                     else
9654                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9655 /*                      p_type = POINTER ; */
9656     }
9657
9658     /* now that we have the pointer type we assign
9659     the pointer values */
9660     switch (p_type) {
9661
9662     case POINTER:       
9663     case IPOINTER:
9664         genNearPointerGet (left,result,ic);
9665         break;
9666
9667     case PPOINTER:
9668         genPagedPointerGet(left,result,ic);
9669         break;
9670
9671     case FPOINTER:
9672         genFarPointerGet (left,result,ic);
9673         break;
9674
9675     case CPOINTER:
9676         genConstPointerGet (left,result,ic);
9677         //pic16_emitcodePointerGet (left,result,ic);
9678         break;
9679
9680     case GPOINTER:
9681 #if 0
9682       if (IS_PTR_CONST(type))
9683         genConstPointerGet (left,result,ic);
9684       else
9685 #endif
9686         genGenPointerGet (left,result,ic);
9687       break;
9688
9689     default:
9690       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9691               "genPointerGet: illegal pointer type");
9692     
9693     }
9694
9695 }
9696
9697 /*-----------------------------------------------------------------*/
9698 /* genPackBits - generates code for packed bit storage             */
9699 /*-----------------------------------------------------------------*/
9700 static void genPackBits (sym_link    *etype ,
9701                          operand *right ,
9702                          char *rname, int p_type)
9703 {
9704   int shCnt = 0 ;
9705   int offset = 0  ;
9706   int rLen = 0 ;
9707   int blen, bstr ;   
9708   char *l ;
9709
9710         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9711         blen = SPEC_BLEN(etype);
9712         bstr = SPEC_BSTR(etype);
9713
9714         if(AOP_TYPE(right) == AOP_LIT) {
9715                 if((blen == 1) && (bstr < 8)) {
9716                   unsigned long lit;
9717                         /* it is a single bit, so use the appropriate bit instructions */
9718
9719                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9720
9721                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9722 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9723                         if(lit) {
9724                                 pic16_emitpcode(POC_BSF,
9725                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9726                         } else {
9727                                 pic16_emitpcode(POC_BCF,
9728                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9729                         }
9730         
9731                   return;
9732                 }
9733
9734                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9735                 offset++;
9736         } else
9737                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9738
9739         /* if the bit lenth is less than or    */
9740         /* it exactly fits a byte then         */
9741         if((shCnt=SPEC_BSTR(etype))
9742                 || SPEC_BLEN(etype) <= 8 )  {
9743
9744                 /* shift left acc */
9745                 AccLsh(shCnt);
9746
9747                 /* using PRODL as a temporary register here */
9748                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9749
9750                 switch (p_type) {
9751                         case FPOINTER:
9752                         case POINTER:
9753                         case GPOINTER:
9754                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9755 //                              pic16_emitcode ("mov","b,a");
9756 //                              pic16_emitcode("mov","a,@%s",rname);
9757                                 break;
9758                 }
9759 #if 1
9760                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9761                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9762                                         (unsigned char)(0xff >> (8-bstr))) ));
9763                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9764                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9765 #endif
9766
9767           return;
9768         }
9769
9770
9771         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9772         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9773         exit(-1);
9774
9775
9776     /* if we r done */
9777     if ( SPEC_BLEN(etype) <= 8 )
9778         return ;
9779
9780     pic16_emitcode("inc","%s",rname);
9781     rLen = SPEC_BLEN(etype) ;     
9782
9783
9784
9785     /* now generate for lengths greater than one byte */
9786     while (1) {
9787
9788         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9789
9790         rLen -= 8 ;
9791         if (rLen <= 0 )
9792             break ;
9793
9794         switch (p_type) {
9795             case POINTER:
9796                 if (*l == '@') {
9797                     MOVA(l);
9798                     pic16_emitcode("mov","@%s,a",rname);
9799                 } else
9800                     pic16_emitcode("mov","@%s,%s",rname,l);
9801                 break;
9802
9803             case FPOINTER:
9804                 MOVA(l);
9805                 pic16_emitcode("movx","@dptr,a");
9806                 break;
9807
9808             case GPOINTER:
9809                 MOVA(l);
9810                 DEBUGpic16_emitcode(";lcall","__gptrput");
9811                 break;  
9812         }   
9813         pic16_emitcode ("inc","%s",rname);
9814     }
9815
9816     MOVA(l);
9817
9818     /* last last was not complete */
9819     if (rLen)   {
9820         /* save the byte & read byte */
9821         switch (p_type) {
9822             case POINTER:
9823                 pic16_emitcode ("mov","b,a");
9824                 pic16_emitcode("mov","a,@%s",rname);
9825                 break;
9826
9827             case FPOINTER:
9828                 pic16_emitcode ("mov","b,a");
9829                 pic16_emitcode("movx","a,@dptr");
9830                 break;
9831
9832             case GPOINTER:
9833                 pic16_emitcode ("push","b");
9834                 pic16_emitcode ("push","acc");
9835                 pic16_emitcode ("lcall","__gptrget");
9836                 pic16_emitcode ("pop","b");
9837                 break;
9838         }
9839
9840         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9841         pic16_emitcode ("orl","a,b");
9842     }
9843
9844     if (p_type == GPOINTER)
9845         pic16_emitcode("pop","b");
9846
9847     switch (p_type) {
9848
9849     case POINTER:
9850         pic16_emitcode("mov","@%s,a",rname);
9851         break;
9852         
9853     case FPOINTER:
9854         pic16_emitcode("movx","@dptr,a");
9855         break;
9856         
9857     case GPOINTER:
9858         DEBUGpic16_emitcode(";lcall","__gptrput");
9859         break;                  
9860     }
9861 }
9862 /*-----------------------------------------------------------------*/
9863 /* genDataPointerSet - remat pointer to data space                 */
9864 /*-----------------------------------------------------------------*/
9865 static void genDataPointerSet(operand *right,
9866                               operand *result,
9867                               iCode *ic)
9868 {
9869     int size, offset = 0, resoffset=0 ;
9870
9871     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9872     pic16_aopOp(right,ic,FALSE);
9873
9874     size = AOP_SIZE(right);
9875
9876 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9877
9878 #if 0
9879     if ( AOP_TYPE(result) == AOP_PCODE) {
9880       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9881               AOP(result)->aopu.pcop->name,
9882                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9883               PCOR(AOP(result)->aopu.pcop)->instance:
9884               PCOI(AOP(result)->aopu.pcop)->offset);
9885     }
9886 #endif
9887
9888         if(AOP(result)->aopu.pcop->type == PO_DIR)
9889                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9890
9891         while (size--) {
9892                 if (AOP_TYPE(right) == AOP_LIT) {
9893                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9894
9895                         lit = lit >> (8*offset);
9896                         if(lit&0xff) {
9897                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9898                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9899                         } else {
9900                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9901                         }
9902                 } else {
9903                         mov2w(AOP(right), offset);
9904                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9905                 }
9906                 offset++;
9907                 resoffset++;
9908         }
9909
9910     pic16_freeAsmop(right,NULL,ic,TRUE);
9911 }
9912
9913
9914
9915 /*-----------------------------------------------------------------*/
9916 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9917 /*-----------------------------------------------------------------*/
9918 static void genNearPointerSet (operand *right,
9919                                operand *result, 
9920                                iCode *ic)
9921 {
9922   asmop *aop = NULL;
9923   char *l;
9924   sym_link *retype;
9925   sym_link *ptype = operandType(result);
9926   sym_link *resetype;
9927     
9928         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9929         retype= getSpec(operandType(right));
9930         resetype = getSpec(operandType(result));
9931   
9932         pic16_aopOp(result,ic,FALSE);
9933     
9934         /* if the result is rematerializable &
9935          * in data space & not a bit variable */
9936         
9937         /* and result is not a bit variable */
9938         if (AOP_TYPE(result) == AOP_PCODE
9939 //              && AOP_TYPE(result) == AOP_IMMD
9940                 && DCL_TYPE(ptype) == POINTER
9941                 && !IS_BITFIELD(retype)
9942                 && !IS_BITFIELD(resetype)) {
9943
9944                 genDataPointerSet (right,result,ic);
9945                 pic16_freeAsmop(result,NULL,ic,TRUE);
9946           return;
9947         }
9948
9949         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9950         pic16_aopOp(right,ic,FALSE);
9951         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9952
9953         /* if the value is already in a pointer register
9954          * then don't need anything more */
9955         if (!AOP_INPREG(AOP(result))) {
9956                 /* otherwise get a free pointer register */
9957                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9958
9959                 if( (AOP_TYPE(result) == AOP_PCODE) 
9960                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9961                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9962                 {
9963                         pic16_loadFSR0( result );  // patch 10
9964                 } else {
9965                         // set up FSR0 with address of result
9966                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9967                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9968                 }
9969
9970         }
9971 //      else
9972 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9973
9974         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9975
9976         /* if bitfield then unpack the bits */
9977         if (IS_BITFIELD(resetype)) {
9978                 genPackBits (resetype, right, NULL, POINTER);
9979         } else {
9980                 /* we have can just get the values */
9981           int size = AOP_SIZE(right);
9982           int offset = 0 ;    
9983
9984                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9985                 while (size--) {
9986                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9987                         if (*l == '@' ) {
9988                                 //MOVA(l);
9989                                 //pic16_emitcode("mov","@%s,a",rname);
9990                                 pic16_emitcode("movf","indf0,w ;1");
9991                         } else {
9992
9993                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9994                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9995                                         if (size) {                                                                     // 
9996                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9997                                         } else {                                                                        // 
9998                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9999                                         }                                                                               // 
10000                                 } else { // no literal                                                                  // 
10001                                         if(size) {                                                                      // 
10002                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10003                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10004                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10005                                         } else {                                                                        // 
10006                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10007                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10008                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10009                                         }                                                                               //
10010                                 }                                                                                       // patch 10
10011                         }
10012                         offset++;
10013                 }
10014         }
10015
10016         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10017         /* now some housekeeping stuff */
10018         if (aop) {
10019                 /* we had to allocate for this iCode */
10020                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10021         } else { 
10022                 /* we did not allocate which means left
10023                  * already in a pointer register, then
10024                  * if size > 0 && this could be used again
10025                  * we have to point it back to where it 
10026                  * belongs */
10027                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10028                 if (AOP_SIZE(right) > 1
10029                         && !OP_SYMBOL(result)->remat
10030                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10031                                 || ic->depth )) {
10032
10033                   int size = AOP_SIZE(right) - 1;
10034
10035                         while (size--)
10036                                 pic16_emitcode("decf","fsr0,f");
10037                         //pic16_emitcode("dec","%s",rname);
10038                 }
10039         }
10040
10041         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10042         /* done */
10043 //release:
10044         pic16_freeAsmop(right,NULL,ic,TRUE);
10045         pic16_freeAsmop(result,NULL,ic,TRUE);
10046 }
10047
10048 /*-----------------------------------------------------------------*/
10049 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10050 /*-----------------------------------------------------------------*/
10051 static void genPagedPointerSet (operand *right,
10052                                operand *result, 
10053                                iCode *ic)
10054 {
10055     asmop *aop = NULL;
10056     regs *preg = NULL ;
10057     char *rname , *l;
10058     sym_link *retype;
10059        
10060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10061
10062     retype= getSpec(operandType(right));
10063     
10064     pic16_aopOp(result,ic,FALSE);
10065     
10066     /* if the value is already in a pointer register
10067        then don't need anything more */
10068     if (!AOP_INPREG(AOP(result))) {
10069         /* otherwise get a free pointer register */
10070         aop = newAsmop(0);
10071         preg = getFreePtr(ic,&aop,FALSE);
10072         pic16_emitcode("mov","%s,%s",
10073                 preg->name,
10074                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10075         rname = preg->name ;
10076     } else
10077         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10078     
10079     pic16_freeAsmop(result,NULL,ic,TRUE);
10080     pic16_aopOp (right,ic,FALSE);
10081
10082     /* if bitfield then unpack the bits */
10083     if (IS_BITFIELD(retype)) 
10084         genPackBits (retype,right,rname,PPOINTER);
10085     else {
10086         /* we have can just get the values */
10087         int size = AOP_SIZE(right);
10088         int offset = 0 ;        
10089         
10090         while (size--) {
10091             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10092             
10093             MOVA(l);
10094             pic16_emitcode("movx","@%s,a",rname);
10095
10096             if (size)
10097                 pic16_emitcode("inc","%s",rname);
10098
10099             offset++;
10100         }
10101     }
10102     
10103     /* now some housekeeping stuff */
10104     if (aop) {
10105         /* we had to allocate for this iCode */
10106         pic16_freeAsmop(NULL,aop,ic,TRUE);
10107     } else { 
10108         /* we did not allocate which means left
10109            already in a pointer register, then
10110            if size > 0 && this could be used again
10111            we have to point it back to where it 
10112            belongs */
10113         if (AOP_SIZE(right) > 1 &&
10114             !OP_SYMBOL(result)->remat &&
10115             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10116               ic->depth )) {
10117             int size = AOP_SIZE(right) - 1;
10118             while (size--)
10119                 pic16_emitcode("dec","%s",rname);
10120         }
10121     }
10122
10123     /* done */
10124     pic16_freeAsmop(right,NULL,ic,TRUE);
10125     
10126         
10127 }
10128
10129 /*-----------------------------------------------------------------*/
10130 /* genFarPointerSet - set value from far space                     */
10131 /*-----------------------------------------------------------------*/
10132 static void genFarPointerSet (operand *right,
10133                               operand *result, iCode *ic)
10134 {
10135     int size, offset ;
10136     sym_link *retype = getSpec(operandType(right));
10137
10138     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10139     pic16_aopOp(result,ic,FALSE);
10140
10141     /* if the operand is already in dptr 
10142     then we do nothing else we move the value to dptr */
10143     if (AOP_TYPE(result) != AOP_STR) {
10144         /* if this is remateriazable */
10145         if (AOP_TYPE(result) == AOP_IMMD)
10146             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10147         else { /* we need to get it byte by byte */
10148             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10149             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10150             if (options.model == MODEL_FLAT24)
10151             {
10152                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10153             }
10154         }
10155     }
10156     /* so dptr know contains the address */
10157     pic16_freeAsmop(result,NULL,ic,TRUE);
10158     pic16_aopOp(right,ic,FALSE);
10159
10160     /* if bit then unpack */
10161     if (IS_BITFIELD(retype)) 
10162         genPackBits(retype,right,"dptr",FPOINTER);
10163     else {
10164         size = AOP_SIZE(right);
10165         offset = 0 ;
10166
10167         while (size--) {
10168             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10169             MOVA(l);
10170             pic16_emitcode("movx","@dptr,a");
10171             if (size)
10172                 pic16_emitcode("inc","dptr");
10173         }
10174     }
10175
10176     pic16_freeAsmop(right,NULL,ic,TRUE);
10177 }
10178
10179 /*-----------------------------------------------------------------*/
10180 /* genGenPointerSet - set value from generic pointer space         */
10181 /*-----------------------------------------------------------------*/
10182 static void genGenPointerSet (operand *right,
10183                               operand *result, iCode *ic)
10184 {
10185         int i, size, offset, lit;
10186         sym_link *retype = getSpec(operandType(right));
10187
10188         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10189
10190         pic16_aopOp(result,ic,FALSE);
10191         pic16_aopOp(right,ic,FALSE);
10192         size = AOP_SIZE(right);
10193         offset = 0;
10194
10195         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10196
10197         /* if the operand is already in dptr 
10198                 then we do nothing else we move the value to dptr */
10199         if (AOP_TYPE(result) != AOP_STR) {
10200                 /* if this is remateriazable */
10201                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10202                 // WARNING: anythig until "else" is untested!
10203                 if (AOP_TYPE(result) == AOP_IMMD) {
10204                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10205                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10206                         // load FSR0 from immediate
10207                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10208                         offset = 0;
10209                         while(size--) {
10210                                 if(size) {
10211                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10212                                 } else {
10213                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10214                                 }
10215                                 offset++;
10216                         }
10217                         goto release;
10218                 }
10219                 else { /* we need to get it byte by byte */
10220                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10221                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10222
10223                         // set up FSR0 with address of result
10224                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10225                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10226
10227                         /* hack hack! see if this the FSR. If so don't load W */
10228                         if(AOP_TYPE(right) != AOP_ACC) {
10229
10230                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10231
10232                                 if(AOP_TYPE(right) == AOP_LIT)
10233                                 {
10234                                         // copy literal
10235                                         // note: pic16_popGet handles sign extension
10236                                         for(i=0;i<size;i++) {
10237                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10238                                                 if(i < size-1)
10239                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10240                                                 else
10241                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10242                                         }
10243                                 } else {
10244                                         // copy regs
10245
10246                                         for(i=0;i<size;i++) {
10247                                                 if(i < size-1)
10248                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10249                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10250                                                 else
10251                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10252                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10253                                         }
10254                                 }
10255                                 goto release;
10256                         } 
10257                         // right = ACC
10258                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10259                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10260                         goto release;
10261         } // if (AOP_TYPE(result) != AOP_IMMD)
10262
10263         } // if (AOP_TYPE(result) != AOP_STR)
10264         /* so dptr know contains the address */
10265
10266
10267         /* if bit then unpack */
10268         if (IS_BITFIELD(retype)) 
10269                 genPackBits(retype,right,"dptr",GPOINTER);
10270         else {
10271                 size = AOP_SIZE(right);
10272                 offset = 0 ;
10273
10274                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10275
10276                 // set up FSR0 with address of result
10277                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10278                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10279         
10280                 while (size--) {
10281                         if (AOP_TYPE(right) == AOP_LIT) {
10282                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10283                                 if (size) {
10284                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10285                                 } else {
10286                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10287                                 }
10288                         } else { // no literal
10289                                 if(size) {
10290                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10291                                 } else {
10292                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10293                                 }
10294                         }
10295                         offset++;
10296                 }
10297         }
10298
10299         release:
10300         pic16_freeAsmop(right,NULL,ic,TRUE);
10301         pic16_freeAsmop(result,NULL,ic,TRUE);
10302 }
10303
10304 /*-----------------------------------------------------------------*/
10305 /* genPointerSet - stores the value into a pointer location        */
10306 /*-----------------------------------------------------------------*/
10307 static void genPointerSet (iCode *ic)
10308 {    
10309     operand *right, *result ;
10310     sym_link *type, *etype;
10311     int p_type;
10312
10313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10314
10315     right = IC_RIGHT(ic);
10316     result = IC_RESULT(ic) ;
10317
10318     /* depending on the type of pointer we need to
10319     move it to the correct pointer register */
10320     type = operandType(result);
10321     etype = getSpec(type);
10322     /* if left is of type of pointer then it is simple */
10323     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10324         p_type = DCL_TYPE(type);
10325     }
10326     else {
10327         /* we have to go by the storage class */
10328         p_type = PTR_TYPE(SPEC_OCLS(etype));
10329
10330 /*      if (SPEC_OCLS(etype)->codesp ) { */
10331 /*          p_type = CPOINTER ;  */
10332 /*      } */
10333 /*      else */
10334 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10335 /*              p_type = FPOINTER ; */
10336 /*          else */
10337 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10338 /*                  p_type = PPOINTER ; */
10339 /*              else */
10340 /*                  if (SPEC_OCLS(etype) == idata ) */
10341 /*                      p_type = IPOINTER ; */
10342 /*                  else */
10343 /*                      p_type = POINTER ; */
10344     }
10345
10346     /* now that we have the pointer type we assign
10347     the pointer values */
10348     switch (p_type) {
10349
10350     case POINTER:
10351     case IPOINTER:
10352         genNearPointerSet (right,result,ic);
10353         break;
10354
10355     case PPOINTER:
10356         genPagedPointerSet (right,result,ic);
10357         break;
10358
10359     case FPOINTER:
10360         genFarPointerSet (right,result,ic);
10361         break;
10362
10363     case GPOINTER:
10364         genGenPointerSet (right,result,ic);
10365         break;
10366
10367     default:
10368       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10369               "genPointerSet: illegal pointer type");
10370     }
10371 }
10372
10373 /*-----------------------------------------------------------------*/
10374 /* genIfx - generate code for Ifx statement                        */
10375 /*-----------------------------------------------------------------*/
10376 static void genIfx (iCode *ic, iCode *popIc)
10377 {
10378   operand *cond = IC_COND(ic);
10379   int isbit =0;
10380
10381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10382
10383   pic16_aopOp(cond,ic,FALSE);
10384
10385   /* get the value into acc */
10386   if (AOP_TYPE(cond) != AOP_CRY)
10387     pic16_toBoolean(cond);
10388   else
10389     isbit = 1;
10390   /* the result is now in the accumulator */
10391   pic16_freeAsmop(cond,NULL,ic,TRUE);
10392
10393   /* if there was something to be popped then do it */
10394   if (popIc)
10395     genIpop(popIc);
10396
10397   /* if the condition is  a bit variable */
10398   if (isbit && IS_ITEMP(cond) && 
10399       SPIL_LOC(cond)) {
10400     genIfxJump(ic,SPIL_LOC(cond)->rname);
10401     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10402   }
10403   else {
10404     if (isbit && !IS_ITEMP(cond))
10405       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10406     else
10407       genIfxJump(ic,"a");
10408   }
10409   ic->generated = 1;
10410
10411 }
10412
10413 /*-----------------------------------------------------------------*/
10414 /* genAddrOf - generates code for address of                       */
10415 /*-----------------------------------------------------------------*/
10416 static void genAddrOf (iCode *ic)
10417 {
10418   operand *result, *left;
10419   int size;
10420   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10421   pCodeOp *pcop0, *pcop1, *pcop2;
10422
10423         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10424
10425         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10426         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10427
10428         sym = OP_SYMBOL( left );
10429
10430         size = AOP_SIZE(IC_RESULT(ic));
10431
10432 //      if(pic16_debug_verbose) {
10433 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10434 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10435 //      }
10436         
10437         /* Assume that what we want the address of is in data space
10438          * since there is no stack on the PIC, yet! -- VR */
10439         /* low */
10440         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10441
10442         /* high */
10443         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10444         
10445         /* upper */
10446         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10447         
10448
10449         if (size == 3) {
10450                 pic16_emitpcode(POC_MOVLW, pcop0);
10451                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10452                 pic16_emitpcode(POC_MOVLW, pcop1);
10453                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10454                 pic16_emitpcode(POC_MOVLW, pcop2);
10455                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10456         } else
10457         if (size == 2) {
10458                 pic16_emitpcode(POC_MOVLW, pcop0);
10459                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10460                 pic16_emitpcode(POC_MOVLW, pcop1);
10461                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10462         } else {
10463                 pic16_emitpcode(POC_MOVLW, pcop0);
10464                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10465         }
10466
10467         pic16_freeAsmop(result,NULL,ic,TRUE);
10468         pic16_freeAsmop(left, NULL, ic, FALSE);
10469 }
10470
10471
10472 #if 0
10473 /*-----------------------------------------------------------------*/
10474 /* genFarFarAssign - assignment when both are in far space         */
10475 /*-----------------------------------------------------------------*/
10476 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10477 {
10478     int size = AOP_SIZE(right);
10479     int offset = 0;
10480     char *l ;
10481     /* first push the right side on to the stack */
10482     while (size--) {
10483         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10484         MOVA(l);
10485         pic16_emitcode ("push","acc");
10486     }
10487     
10488     pic16_freeAsmop(right,NULL,ic,FALSE);
10489     /* now assign DPTR to result */
10490     pic16_aopOp(result,ic,FALSE);
10491     size = AOP_SIZE(result);
10492     while (size--) {
10493         pic16_emitcode ("pop","acc");
10494         pic16_aopPut(AOP(result),"a",--offset);
10495     }
10496     pic16_freeAsmop(result,NULL,ic,FALSE);
10497         
10498 }
10499 #endif
10500
10501 /*-----------------------------------------------------------------*/
10502 /* genAssign - generate code for assignment                        */
10503 /*-----------------------------------------------------------------*/
10504 static void genAssign (iCode *ic)
10505 {
10506   operand *result, *right;
10507   int size, offset,know_W;
10508   unsigned long lit = 0L;
10509
10510   result = IC_RESULT(ic);
10511   right  = IC_RIGHT(ic) ;
10512
10513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10514   
10515   /* if they are the same */
10516   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10517     return ;
10518
10519   pic16_aopOp(right,ic,FALSE);
10520   pic16_aopOp(result,ic,TRUE);
10521
10522   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10523
10524   /* if they are the same registers */
10525   if (pic16_sameRegs(AOP(right),AOP(result)))
10526     goto release;
10527
10528   /* if the result is a bit */
10529   if (AOP_TYPE(result) == AOP_CRY) {
10530     /* if the right size is a literal then
10531        we know what the value is */
10532     if (AOP_TYPE(right) == AOP_LIT) {
10533           
10534       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10535                   pic16_popGet(AOP(result),0));
10536
10537       if (((int) operandLitValue(right))) 
10538         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10539                        AOP(result)->aopu.aop_dir,
10540                        AOP(result)->aopu.aop_dir);
10541       else
10542         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10543                        AOP(result)->aopu.aop_dir,
10544                        AOP(result)->aopu.aop_dir);
10545       goto release;
10546     }
10547
10548     /* the right is also a bit variable */
10549     if (AOP_TYPE(right) == AOP_CRY) {
10550       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10551       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10552       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10553
10554       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10555                      AOP(result)->aopu.aop_dir,
10556                      AOP(result)->aopu.aop_dir);
10557       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10558                      AOP(right)->aopu.aop_dir,
10559                      AOP(right)->aopu.aop_dir);
10560       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10561                      AOP(result)->aopu.aop_dir,
10562                      AOP(result)->aopu.aop_dir);
10563       goto release ;
10564     }
10565
10566     /* we need to or */
10567     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10568     pic16_toBoolean(right);
10569     emitSKPZ;
10570     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10571     //pic16_aopPut(AOP(result),"a",0);
10572     goto release ;
10573   }
10574
10575   /* bit variables done */
10576   /* general case */
10577   size = AOP_SIZE(result);
10578   offset = 0 ;
10579
10580   if(AOP_TYPE(right) == AOP_LIT) {
10581         if(!IS_FLOAT(operandType( right )))
10582                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10583         else {
10584            union {
10585               unsigned long lit_int;
10586               float lit_float;
10587             } info;
10588         
10589                 /* take care if literal is a float */
10590                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10591                 lit = info.lit_int;
10592         }
10593   }
10594
10595 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10596 //                      sizeof(unsigned long int), sizeof(float));
10597
10598   if(AOP_TYPE(right) != AOP_LIT
10599         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10600         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10601
10602         // set up table pointer
10603         if( (AOP_TYPE(right) == AOP_PCODE)
10604                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10605                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10606         {
10607                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10608                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10609                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10610                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10611                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10612                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10613         } else {
10614                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10615                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10616                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10617                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10618                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10619                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10620         }
10621
10622         size = min(AOP_SIZE(right), AOP_SIZE(result));
10623         while(size--) {
10624                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10625                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10626                         pic16_popGet(AOP(result),offset)));
10627                 offset++;
10628         }
10629
10630         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10631                 size = AOP_SIZE(result) - AOP_SIZE(right);
10632                 while(size--) {
10633                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10634                         offset++;
10635                 }
10636         }
10637         goto release;
10638   }
10639
10640
10641
10642 /* VR - What is this?! */
10643   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10644   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10645     if(aopIdx(AOP(result),0) == 4) {
10646   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10647         assert(0);
10648       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10649       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10650       goto release;
10651     } else
10652 //      assert(0);
10653       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10654   }
10655
10656   know_W=-1;
10657   while (size--) {
10658   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10659     if(AOP_TYPE(right) == AOP_LIT) {
10660       if(lit&0xff) {
10661         if(know_W != (lit&0xff))
10662           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10663         know_W = lit&0xff;
10664         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10665       } else
10666         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10667
10668       lit >>= 8;
10669
10670     } else if (AOP_TYPE(right) == AOP_CRY) {
10671       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10672       if(offset == 0) {
10673         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10674         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10675       }
10676     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10677         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10678         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10679     } else {
10680   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10681
10682 #if 1
10683         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10684            normally should work, but mind that the W register live range
10685            is not checked, so if the code generator assumes that the W
10686            is already loaded after such a pair, wrong code will be generated.
10687            
10688            Checking the live range is the next step.
10689            This is experimental code yet and has not been fully tested yet.
10690            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10691            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10692            
10693         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10694 #else   
10695         /* This is the old code, which is assumed(?!) that works fine(!?) */
10696
10697         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10698         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10699 #endif
10700     }
10701             
10702     offset++;
10703   }
10704
10705     
10706  release:
10707   pic16_freeAsmop (right,NULL,ic,FALSE);
10708   pic16_freeAsmop (result,NULL,ic,TRUE);
10709 }   
10710
10711 /*-----------------------------------------------------------------*/
10712 /* genJumpTab - generates code for jump table                       */
10713 /*-----------------------------------------------------------------*/
10714 static void genJumpTab (iCode *ic)
10715 {
10716     symbol *jtab;
10717     char *l;
10718
10719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10720
10721     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10722     /* get the condition into accumulator */
10723     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10724     MOVA(l);
10725     /* multiply by three */
10726     pic16_emitcode("add","a,acc");
10727     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10728
10729     jtab = newiTempLabel(NULL);
10730     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10731     pic16_emitcode("jmp","@a+dptr");
10732     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10733
10734     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10735     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10736     emitSKPNC;
10737     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10738     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10739     pic16_emitpLabel(jtab->key);
10740
10741     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10742
10743     /* now generate the jump labels */
10744     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10745          jtab = setNextItem(IC_JTLABELS(ic))) {
10746         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10747         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10748         
10749     }
10750
10751 }
10752
10753 /*-----------------------------------------------------------------*/
10754 /* genMixedOperation - gen code for operators between mixed types  */
10755 /*-----------------------------------------------------------------*/
10756 /*
10757   TSD - Written for the PIC port - but this unfortunately is buggy.
10758   This routine is good in that it is able to efficiently promote 
10759   types to different (larger) sizes. Unfortunately, the temporary
10760   variables that are optimized out by this routine are sometimes
10761   used in other places. So until I know how to really parse the 
10762   iCode tree, I'm going to not be using this routine :(.
10763 */
10764 static int genMixedOperation (iCode *ic)
10765 {
10766 #if 0
10767   operand *result = IC_RESULT(ic);
10768   sym_link *ctype = operandType(IC_LEFT(ic));
10769   operand *right = IC_RIGHT(ic);
10770   int ret = 0;
10771   int big,small;
10772   int offset;
10773
10774   iCode *nextic;
10775   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10776
10777   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10778
10779   nextic = ic->next;
10780   if(!nextic)
10781     return 0;
10782
10783   nextright = IC_RIGHT(nextic);
10784   nextleft  = IC_LEFT(nextic);
10785   nextresult = IC_RESULT(nextic);
10786
10787   pic16_aopOp(right,ic,FALSE);
10788   pic16_aopOp(result,ic,FALSE);
10789   pic16_aopOp(nextright,  nextic, FALSE);
10790   pic16_aopOp(nextleft,   nextic, FALSE);
10791   pic16_aopOp(nextresult, nextic, FALSE);
10792
10793   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10794
10795     operand *t = right;
10796     right = nextright;
10797     nextright = t; 
10798
10799     pic16_emitcode(";remove right +","");
10800
10801   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10802 /*
10803     operand *t = right;
10804     right = nextleft;
10805     nextleft = t; 
10806 */
10807     pic16_emitcode(";remove left +","");
10808   } else
10809     return 0;
10810
10811   big = AOP_SIZE(nextleft);
10812   small = AOP_SIZE(nextright);
10813
10814   switch(nextic->op) {
10815
10816   case '+':
10817     pic16_emitcode(";optimize a +","");
10818     /* if unsigned or not an integral type */
10819     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10820       pic16_emitcode(";add a bit to something","");
10821     } else {
10822
10823       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10824
10825       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10826         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10827         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10828       } else
10829         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10830
10831       offset = 0;
10832       while(--big) {
10833
10834         offset++;
10835
10836         if(--small) {
10837           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10838             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10839             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10840           }
10841
10842           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10843           emitSKPNC;
10844           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10845                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10846                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10847           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10848           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10849
10850         } else {
10851           pic16_emitcode("rlf","known_zero,w");
10852
10853           /*
10854             if right is signed
10855               btfsc  right,7
10856                addlw ff
10857           */
10858           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10859             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10860             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10861           } else {
10862             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10863           }
10864         }
10865       }
10866       ret = 1;
10867     }
10868   }
10869   ret = 1;
10870
10871 release:
10872   pic16_freeAsmop(right,NULL,ic,TRUE);
10873   pic16_freeAsmop(result,NULL,ic,TRUE);
10874   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10875   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10876   if(ret)
10877     nextic->generated = 1;
10878
10879   return ret;
10880 #else
10881   return 0;
10882 #endif
10883 }
10884 /*-----------------------------------------------------------------*/
10885 /* genCast - gen code for casting                                  */
10886 /*-----------------------------------------------------------------*/
10887 static void genCast (iCode *ic)
10888 {
10889   operand *result = IC_RESULT(ic);
10890   sym_link *ctype = operandType(IC_LEFT(ic));
10891   sym_link *rtype = operandType(IC_RIGHT(ic));
10892   operand *right = IC_RIGHT(ic);
10893   int size, offset ;
10894
10895         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10896         /* if they are equivalent then do nothing */
10897         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10898                 return ;
10899
10900         pic16_aopOp(right,ic,FALSE) ;
10901         pic16_aopOp(result,ic,FALSE);
10902
10903         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10904
10905         /* if the result is a bit */
10906         if (AOP_TYPE(result) == AOP_CRY) {
10907         
10908                 /* if the right size is a literal then
10909                  * we know what the value is */
10910                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10911
10912                 if (AOP_TYPE(right) == AOP_LIT) {
10913                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10914                                 pic16_popGet(AOP(result),0));
10915
10916                         if (((int) operandLitValue(right))) 
10917                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10918                                         AOP(result)->aopu.aop_dir,
10919                                         AOP(result)->aopu.aop_dir);
10920                         else
10921                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10922                                         AOP(result)->aopu.aop_dir,
10923                                         AOP(result)->aopu.aop_dir);
10924                         goto release;
10925                 }
10926
10927                 /* the right is also a bit variable */
10928                 if (AOP_TYPE(right) == AOP_CRY) {
10929                         emitCLRC;
10930                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10931
10932                         pic16_emitcode("clrc","");
10933                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10934                                 AOP(right)->aopu.aop_dir,
10935                                 AOP(right)->aopu.aop_dir);
10936                         pic16_aopPut(AOP(result),"c",0);
10937                         goto release ;
10938                 }
10939
10940                 /* we need to or */
10941                 if (AOP_TYPE(right) == AOP_REG) {
10942                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10943                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10944                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10945                 }
10946                 pic16_toBoolean(right);
10947                 pic16_aopPut(AOP(result),"a",0);
10948                 goto release ;
10949         }
10950
10951         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10952           int offset = 1;
10953
10954                 size = AOP_SIZE(result);
10955
10956                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10957
10958                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10959                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10960                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10961
10962                 while (size--)
10963                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10964
10965                 goto release;
10966         }
10967
10968         /* if they are the same size : or less */
10969         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10970
10971                 /* if they are in the same place */
10972                 if (pic16_sameRegs(AOP(right),AOP(result)))
10973                         goto release;
10974
10975                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10976 #if 0
10977                 if (IS_PTR_CONST(rtype))
10978 #else
10979                 if (IS_CODEPTR(rtype))
10980 #endif
10981                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10982
10983 #if 0
10984                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10985 #else
10986                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10987 #endif
10988                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10989
10990 #if 0
10991                 if(AOP_TYPE(right) == AOP_IMMD) {
10992                   pCodeOp *pcop0, *pcop1, *pcop2;
10993                   symbol *sym = OP_SYMBOL( right );
10994
10995                         size = AOP_SIZE(result);
10996                         /* low */
10997                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10998                         /* high */
10999                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11000                         /* upper */
11001                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11002         
11003                         if (size == 3) {
11004                                 pic16_emitpcode(POC_MOVLW, pcop0);
11005                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11006                                 pic16_emitpcode(POC_MOVLW, pcop1);
11007                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11008                                 pic16_emitpcode(POC_MOVLW, pcop2);
11009                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11010                         } else
11011                         if (size == 2) {
11012                                 pic16_emitpcode(POC_MOVLW, pcop0);
11013                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11014                                 pic16_emitpcode(POC_MOVLW, pcop1);
11015                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11016                         } else {
11017                                 pic16_emitpcode(POC_MOVLW, pcop0);
11018                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11019                         }
11020                 } else
11021 #endif
11022                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11023                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11024                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11025                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11026                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11027                         if(AOP_SIZE(result) <2)
11028                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11029                 } else {
11030                         /* if they in different places then copy */
11031                         size = AOP_SIZE(result);
11032                         offset = 0 ;
11033                         while (size--) {
11034                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11035                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11036                                 offset++;
11037                         }
11038                 }
11039                 goto release;
11040         }
11041
11042         /* if the result is of type pointer */
11043         if (IS_PTR(ctype)) {
11044           int p_type;
11045           sym_link *type = operandType(right);
11046           sym_link *etype = getSpec(type);
11047
11048                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11049
11050                 /* pointer to generic pointer */
11051                 if (IS_GENPTR(ctype)) {
11052                   char *l = zero;
11053             
11054                         if (IS_PTR(type)) 
11055                                 p_type = DCL_TYPE(type);
11056                         else {
11057                 /* we have to go by the storage class */
11058                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11059
11060 /*              if (SPEC_OCLS(etype)->codesp )  */
11061 /*                  p_type = CPOINTER ;  */
11062 /*              else */
11063 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11064 /*                      p_type = FPOINTER ; */
11065 /*                  else */
11066 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11067 /*                          p_type = PPOINTER; */
11068 /*                      else */
11069 /*                          if (SPEC_OCLS(etype) == idata ) */
11070 /*                              p_type = IPOINTER ; */
11071 /*                          else */
11072 /*                              p_type = POINTER ; */
11073             }
11074                 
11075             /* the first two bytes are known */
11076       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11077             size = GPTRSIZE - 1; 
11078             offset = 0 ;
11079             while (size--) {
11080               if(offset < AOP_SIZE(right)) {
11081       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11082                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11083                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11084                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11085                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11086                 } else { 
11087                   pic16_aopPut(AOP(result),
11088                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11089                          offset);
11090                 }
11091               } else 
11092                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11093               offset++;
11094             }
11095             /* the last byte depending on type */
11096             switch (p_type) {
11097             case IPOINTER:
11098             case POINTER:
11099                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11100                 break;
11101             case FPOINTER:
11102               pic16_emitcode(";BUG!? ","%d",__LINE__);
11103                 l = one;
11104                 break;
11105             case CPOINTER:
11106               pic16_emitcode(";BUG!? ","%d",__LINE__);
11107                 l = "#0x02";
11108                 break;                          
11109             case PPOINTER:
11110               pic16_emitcode(";BUG!? ","%d",__LINE__);
11111                 l = "#0x03";
11112                 break;
11113                 
11114             default:
11115                 /* this should never happen */
11116                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11117                        "got unknown pointer type");
11118                 exit(1);
11119             }
11120             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11121             goto release ;
11122         }
11123         
11124         /* just copy the pointers */
11125         size = AOP_SIZE(result);
11126         offset = 0 ;
11127         while (size--) {
11128             pic16_aopPut(AOP(result),
11129                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11130                    offset);
11131             offset++;
11132         }
11133         goto release ;
11134     }
11135     
11136
11137
11138     /* so we now know that the size of destination is greater
11139     than the size of the source.
11140     Now, if the next iCode is an operator then we might be
11141     able to optimize the operation without performing a cast.
11142     */
11143     if(genMixedOperation(ic))
11144       goto release;
11145
11146     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11147     
11148     /* we move to result for the size of source */
11149     size = AOP_SIZE(right);
11150     offset = 0 ;
11151     while (size--) {
11152       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11153       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11154       offset++;
11155     }
11156
11157     /* now depending on the sign of the destination */
11158     size = AOP_SIZE(result) - AOP_SIZE(right);
11159     /* if unsigned or not an integral type */
11160     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11161       while (size--)
11162         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11163     } else {
11164       /* we need to extend the sign :( */
11165
11166       if(size == 1) {
11167         /* Save one instruction of casting char to int */
11168         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11169         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11170         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11171       } else {
11172         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11173
11174         if(offset)
11175           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11176         else
11177           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11178         
11179         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11180
11181         while (size--)
11182           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11183       }
11184     }
11185
11186 release:
11187     pic16_freeAsmop(right,NULL,ic,TRUE);
11188     pic16_freeAsmop(result,NULL,ic,TRUE);
11189
11190 }
11191
11192 /*-----------------------------------------------------------------*/
11193 /* genDjnz - generate decrement & jump if not zero instrucion      */
11194 /*-----------------------------------------------------------------*/
11195 static int genDjnz (iCode *ic, iCode *ifx)
11196 {
11197     symbol *lbl, *lbl1;
11198     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11199
11200     if (!ifx)
11201         return 0;
11202     
11203     /* if the if condition has a false label
11204        then we cannot save */
11205     if (IC_FALSE(ifx))
11206         return 0;
11207
11208     /* if the minus is not of the form 
11209        a = a - 1 */
11210     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11211         !IS_OP_LITERAL(IC_RIGHT(ic)))
11212         return 0;
11213
11214     if (operandLitValue(IC_RIGHT(ic)) != 1)
11215         return 0;
11216
11217     /* if the size of this greater than one then no
11218        saving */
11219     if (getSize(operandType(IC_RESULT(ic))) > 1)
11220         return 0;
11221
11222     /* otherwise we can save BIG */
11223     lbl = newiTempLabel(NULL);
11224     lbl1= newiTempLabel(NULL);
11225
11226     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11227     
11228     if (IS_AOP_PREG(IC_RESULT(ic))) {
11229         pic16_emitcode("dec","%s",
11230                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11231         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11232         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11233     } else {    
11234
11235
11236       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11237       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11238
11239       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11240       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11241
11242     }
11243 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11244 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11245 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11246 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11247
11248     
11249     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11250     ifx->generated = 1;
11251     return 1;
11252 }
11253
11254 /*-----------------------------------------------------------------*/
11255 /* genReceive - generate code for a receive iCode                  */
11256 /*-----------------------------------------------------------------*/
11257 static void genReceive (iCode *ic)
11258 {    
11259         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11260
11261 #if 0
11262         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11263                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11264 #endif
11265 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11266
11267         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11268                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11269                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11270
11271           int size = getSize(operandType(IC_RESULT(ic)));
11272           int offset =  pic16_fReturnSizePic - size;
11273
11274                 assert( 0 );
11275                 while (size--) {
11276                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11277                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11278                         offset++;
11279                 }
11280
11281                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11282
11283                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11284                 size = AOP_SIZE(IC_RESULT(ic));
11285                 offset = 0;
11286                 while (size--) {
11287                         pic16_emitcode ("pop","acc");
11288                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11289                 }
11290         } else {
11291                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11292
11293                 _G.accInUse++;
11294                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11295                 _G.accInUse--;
11296                 assignResultValue(IC_RESULT(ic), 0);
11297         }
11298
11299         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11300 }
11301
11302 /*-----------------------------------------------------------------*/
11303 /* genDummyRead - generate code for dummy read of volatiles        */
11304 /*-----------------------------------------------------------------*/
11305 static void
11306 genDummyRead (iCode * ic)
11307 {
11308   pic16_emitcode ("; genDummyRead","");
11309   pic16_emitcode ("; not implemented","");
11310
11311   ic = ic;
11312 }
11313
11314 /*-----------------------------------------------------------------*/
11315 /* genpic16Code - generate code for pic16 based controllers        */
11316 /*-----------------------------------------------------------------*/
11317 /*
11318  * At this point, ralloc.c has gone through the iCode and attempted
11319  * to optimize in a way suitable for a PIC. Now we've got to generate
11320  * PIC instructions that correspond to the iCode.
11321  *
11322  * Once the instructions are generated, we'll pass through both the
11323  * peep hole optimizer and the pCode optimizer.
11324  *-----------------------------------------------------------------*/
11325
11326 void genpic16Code (iCode *lic)
11327 {
11328     iCode *ic;
11329     int cln = 0;
11330
11331     lineHead = lineCurr = NULL;
11332
11333     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11334     pic16_addpBlock(pb);
11335
11336 #if 0
11337     /* if debug information required */
11338     if (options.debug && currFunc) {
11339       if (currFunc) {
11340         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11341       }
11342     }
11343 #endif
11344
11345     for (ic = lic ; ic ; ic = ic->next ) {
11346
11347       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11348         if ( cln != ic->lineno ) {
11349             if ( options.debug ) {
11350               debugFile->writeCLine (ic);
11351             }
11352             
11353             if(!options.noCcodeInAsm) {
11354                 pic16_addpCode2pBlock(pb,
11355                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11356                                 printCLine(ic->filename, ic->lineno)));
11357             }
11358
11359             cln = ic->lineno ;
11360         }
11361         
11362         if(options.iCodeInAsm) {
11363                 char *l;
11364                 /* insert here code to print iCode as comment */
11365                 l = Safe_strdup(printILine(ic));
11366                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11367         }
11368         
11369         /* if the result is marked as
11370            spilt and rematerializable or code for
11371            this has already been generated then
11372            do nothing */
11373         if (resultRemat(ic) || ic->generated ) 
11374             continue ;
11375         
11376         /* depending on the operation */
11377         switch (ic->op) {
11378         case '!' :
11379             pic16_genNot(ic);
11380             break;
11381             
11382         case '~' :
11383             pic16_genCpl(ic);
11384             break;
11385             
11386         case UNARYMINUS:
11387             genUminus (ic);
11388             break;
11389             
11390         case IPUSH:
11391             genIpush (ic);
11392             break;
11393             
11394         case IPOP:
11395             /* IPOP happens only when trying to restore a 
11396                spilt live range, if there is an ifx statement
11397                following this pop then the if statement might
11398                be using some of the registers being popped which
11399                would destroy the contents of the register so
11400                we need to check for this condition and handle it */
11401             if (ic->next            && 
11402                 ic->next->op == IFX &&
11403                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11404                 genIfx (ic->next,ic);
11405             else
11406                 genIpop (ic);
11407             break; 
11408             
11409         case CALL:
11410             genCall (ic);
11411             break;
11412             
11413         case PCALL:
11414             genPcall (ic);
11415             break;
11416             
11417         case FUNCTION:
11418             genFunction (ic);
11419             break;
11420             
11421         case ENDFUNCTION:
11422             genEndFunction (ic);
11423             break;
11424             
11425         case RETURN:
11426             genRet (ic);
11427             break;
11428             
11429         case LABEL:
11430             genLabel (ic);
11431             break;
11432             
11433         case GOTO:
11434             genGoto (ic);
11435             break;
11436             
11437         case '+' :
11438             pic16_genPlus (ic) ;
11439             break;
11440             
11441         case '-' :
11442             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11443                 pic16_genMinus (ic);
11444             break;
11445             
11446         case '*' :
11447             genMult (ic);
11448             break;
11449             
11450         case '/' :
11451             genDiv (ic) ;
11452             break;
11453             
11454         case '%' :
11455             genMod (ic);
11456             break;
11457             
11458         case '>' :
11459             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11460             break;
11461             
11462         case '<' :
11463             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11464             break;
11465             
11466         case LE_OP:
11467         case GE_OP:
11468         case NE_OP:
11469             
11470             /* note these two are xlated by algebraic equivalence
11471                during parsing SDCC.y */
11472             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11473                    "got '>=' or '<=' shouldn't have come here");
11474             break;      
11475             
11476         case EQ_OP:
11477             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11478             break;          
11479             
11480         case AND_OP:
11481             genAndOp (ic);
11482             break;
11483             
11484         case OR_OP:
11485             genOrOp (ic);
11486             break;
11487             
11488         case '^' :
11489             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11490             break;
11491             
11492         case '|' :
11493                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11494             break;
11495             
11496         case BITWISEAND:
11497             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11498             break;
11499             
11500         case INLINEASM:
11501             genInline (ic);
11502             break;
11503             
11504         case RRC:
11505             genRRC (ic);
11506             break;
11507             
11508         case RLC:
11509             genRLC (ic);
11510             break;
11511             
11512         case GETHBIT:
11513             genGetHbit (ic);
11514             break;
11515             
11516         case LEFT_OP:
11517             genLeftShift (ic);
11518             break;
11519             
11520         case RIGHT_OP:
11521             genRightShift (ic);
11522             break;
11523             
11524         case GET_VALUE_AT_ADDRESS:
11525             genPointerGet(ic);
11526             break;
11527             
11528         case '=' :
11529             if (POINTER_SET(ic))
11530                 genPointerSet(ic);
11531             else
11532                 genAssign(ic);
11533             break;
11534             
11535         case IFX:
11536             genIfx (ic,NULL);
11537             break;
11538             
11539         case ADDRESS_OF:
11540             genAddrOf (ic);
11541             break;
11542             
11543         case JUMPTABLE:
11544             genJumpTab (ic);
11545             break;
11546             
11547         case CAST:
11548             genCast (ic);
11549             break;
11550             
11551         case RECEIVE:
11552             genReceive(ic);
11553             break;
11554             
11555         case SEND:
11556             addSet(&_G.sendSet,ic);
11557             break;
11558
11559         case DUMMY_READ_VOLATILE:
11560           genDummyRead (ic);
11561           break;
11562
11563         default :
11564             ic = ic;
11565         }
11566     }
11567
11568
11569     /* now we are ready to call the
11570        peep hole optimizer */
11571     if (!options.nopeep) {
11572       peepHole (&lineHead);
11573     }
11574     /* now do the actual printing */
11575     printLine (lineHead,codeOutFile);
11576
11577 #ifdef PCODE_DEBUG
11578     DFPRINTF((stderr,"printing pBlock\n\n"));
11579     pic16_printpBlock(stdout,pb);
11580 #endif
11581
11582     return;
11583 }
11584