* src/pic16/gen.c (genPointerGet): added E_INTERNAL_ERROR for
[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 static int 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+labelOffset));
274 }
275
276 void pic16_emitpLabelFORCE(int key)
277 {
278   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+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,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 (strcmp(sym1->rname,sym2->rname) == 0)
850         return TRUE;
851
852
853     /* if left is a tmp & right is not */
854     if (IS_ITEMP(op1)  && 
855         !IS_ITEMP(op2) &&
856         sym1->isspilt  &&
857         (sym1->usl.spillLoc == sym2))
858         return TRUE;
859
860     if (IS_ITEMP(op2)  && 
861         !IS_ITEMP(op1) &&
862         sym2->isspilt  &&
863         sym1->level > 0 &&
864         (sym2->usl.spillLoc == sym1))
865         return TRUE ;
866
867     return FALSE ;
868 }
869
870 /*-----------------------------------------------------------------*/
871 /* pic16_sameRegs - two asmops have the same registers                   */
872 /*-----------------------------------------------------------------*/
873 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
874 {
875     int i;
876
877     if (aop1 == aop2)
878         return TRUE ;
879
880     if (aop1->type != AOP_REG ||
881         aop2->type != AOP_REG )
882         return FALSE ;
883
884     if (aop1->size != aop2->size )
885         return FALSE ;
886
887     for (i = 0 ; i < aop1->size ; i++ )
888         if (aop1->aopu.aop_reg[i] !=
889             aop2->aopu.aop_reg[i] )
890             return FALSE ;
891
892     return TRUE ;
893 }
894
895 /*-----------------------------------------------------------------*/
896 /* pic16_aopOp - allocates an asmop for an operand  :                    */
897 /*-----------------------------------------------------------------*/
898 void pic16_aopOp (operand *op, iCode *ic, bool result)
899 {
900     asmop *aop;
901     symbol *sym;
902     int i;
903
904     if (!op)
905         return ;
906
907 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
908
909     /* if this a literal */
910     if (IS_OP_LITERAL(op)) {
911         op->aop = aop = newAsmop(AOP_LIT);
912         aop->aopu.aop_lit = op->operand.valOperand;
913         aop->size = getSize(operandType(op));
914         return;
915     }
916
917     {
918       sym_link *type = operandType(op);
919 #if 0
920       if(IS_PTR_CONST(type))
921 #else
922       if(IS_CODEPTR(type))
923 #endif
924         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
925     }
926
927     /* if already has a asmop then continue */
928     if (op->aop)
929         return ;
930
931     /* if the underlying symbol has a aop */
932     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
933       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
934         op->aop = OP_SYMBOL(op)->aop;
935         return;
936     }
937
938     /* if this is a true symbol */
939     if (IS_TRUE_SYMOP(op)) {    
940         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
941       op->aop = aopForSym(ic, op, result);
942       return ;
943     }
944
945     /* this is a temporary : this has
946     only four choices :
947     a) register
948     b) spillocation
949     c) rematerialize 
950     d) conditional   
951     e) can be a return use only */
952
953     sym = OP_SYMBOL(op);
954
955         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
956     /* if the type is a conditional */
957     if (sym->regType == REG_CND) {
958         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
959         aop->size = 0;
960         return;
961     }
962
963     /* if it is spilt then two situations
964     a) is rematerialize 
965     b) has a spill location */
966     if (sym->isspilt || sym->nRegs == 0) {
967
968       DEBUGpic16_emitcode(";","%d",__LINE__);
969         /* rematerialize it NOW */
970         if (sym->remat) {
971
972             sym->aop = op->aop = aop =
973                                       aopForRemat (op);
974             aop->size = getSize(sym->type);
975             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
976             return;
977         }
978
979 #if 1
980         if (sym->accuse) {
981             int i;
982             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
983             aop->size = getSize(sym->type);
984             for ( i = 0 ; i < 1 ; i++ ) {
985                 aop->aopu.aop_str[i] = accUse[i];
986 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
987             }
988             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
989             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
990             return;  
991         }
992 #endif
993
994 #if 1
995         if (sym->ruonly ) {
996           /*
997           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
998           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
999           //pic16_allocDirReg (IC_LEFT(ic));
1000           aop->size = getSize(sym->type);
1001           */
1002
1003           unsigned i;
1004
1005           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1006           aop->size = getSize(sym->type);
1007           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1008             aop->aopu.aop_str[i] = fReturn[i];
1009
1010           DEBUGpic16_emitcode(";","%d",__LINE__);
1011           return;
1012         }
1013 #endif
1014         /* else spill location  */
1015         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1016             /* force a new aop if sizes differ */
1017             sym->usl.spillLoc->aop = NULL;
1018         }
1019         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1020                             __FUNCTION__,__LINE__,
1021                             sym->usl.spillLoc->rname,
1022                             sym->rname, sym->usl.spillLoc->offset);
1023
1024         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1025         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1026         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1027                                           getSize(sym->type), 
1028                                           sym->usl.spillLoc->offset, op);
1029         aop->size = getSize(sym->type);
1030
1031         return;
1032     }
1033
1034     {
1035       sym_link *type = operandType(op);
1036 #if 0
1037       if(IS_PTR_CONST(type)) 
1038 #else
1039       if(IS_CODEPTR(type)) 
1040 #endif
1041         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1042     }
1043
1044     /* must be in a register */
1045     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1046     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1047     aop->size = sym->nRegs;
1048     for ( i = 0 ; i < sym->nRegs ;i++)
1049         aop->aopu.aop_reg[i] = sym->regs[i];
1050 }
1051
1052 /*-----------------------------------------------------------------*/
1053 /* pic16_freeAsmop - free up the asmop given to an operand               */
1054 /*----------------------------------------------------------------*/
1055 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1056 {   
1057     asmop *aop ;
1058
1059     if (!op)
1060         aop = aaop;
1061     else 
1062         aop = op->aop;
1063
1064     if (!aop)
1065         return ;
1066
1067     if (aop->freed)
1068         goto dealloc; 
1069
1070     aop->freed = 1;
1071
1072     /* depending on the asmop type only three cases need work AOP_RO
1073        , AOP_R1 && AOP_STK */
1074 #if 0
1075     switch (aop->type) {
1076         case AOP_R0 :
1077             if (_G.r0Pushed ) {
1078                 if (pop) {
1079                     pic16_emitcode ("pop","ar0");     
1080                     _G.r0Pushed--;
1081                 }
1082             }
1083             bitVectUnSetBit(ic->rUsed,R0_IDX);
1084             break;
1085
1086         case AOP_R1 :
1087             if (_G.r1Pushed ) {
1088                 if (pop) {
1089                     pic16_emitcode ("pop","ar1");
1090                     _G.r1Pushed--;
1091                 }
1092             }
1093             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1094             break;
1095
1096         case AOP_STK :
1097         {
1098             int sz = aop->size;    
1099             int stk = aop->aopu.aop_stk + aop->size;
1100             bitVectUnSetBit(ic->rUsed,R0_IDX);
1101             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1102
1103             getFreePtr(ic,&aop,FALSE);
1104             
1105             if (options.stack10bit)
1106             {
1107                 /* I'm not sure what to do here yet... */
1108                 /* #STUB */
1109                 fprintf(stderr, 
1110                         "*** Warning: probably generating bad code for "
1111                         "10 bit stack mode.\n");
1112             }
1113             
1114             if (stk) {
1115                 pic16_emitcode ("mov","a,_bp");
1116                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1117                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1118             } else {
1119                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1120             }
1121
1122             while (sz--) {
1123                 pic16_emitcode("pop","acc");
1124                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1125                 if (!sz) break;
1126                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1127             }
1128             op->aop = aop;
1129             pic16_freeAsmop(op,NULL,ic,TRUE);
1130             if (_G.r0Pushed) {
1131                 pic16_emitcode("pop","ar0");
1132                 _G.r0Pushed--;
1133             }
1134
1135             if (_G.r1Pushed) {
1136                 pic16_emitcode("pop","ar1");
1137                 _G.r1Pushed--;
1138             }       
1139         }
1140     }
1141 #endif
1142
1143 dealloc:
1144     /* all other cases just dealloc */
1145     if (op ) {
1146         op->aop = NULL;
1147         if (IS_SYMOP(op)) {
1148             OP_SYMBOL(op)->aop = NULL;    
1149             /* if the symbol has a spill */
1150             if (SPIL_LOC(op))
1151                 SPIL_LOC(op)->aop = NULL;
1152         }
1153     }
1154 }
1155
1156 /*-----------------------------------------------------------------*/
1157 /* pic16_aopGet - for fetching value of the aop                          */
1158 /*-----------------------------------------------------------------*/
1159 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1160 {
1161     char *s = buffer ;
1162     char *rs;
1163
1164     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1165
1166     /* offset is greater than size then zero */
1167     if (offset > (aop->size - 1) &&
1168         aop->type != AOP_LIT)
1169         return zero;
1170
1171     /* depending on type */
1172     switch (aop->type) {
1173         
1174     case AOP_R0:
1175     case AOP_R1:
1176         DEBUGpic16_emitcode(";","%d",__LINE__);
1177         /* if we need to increment it */       
1178         while (offset > aop->coff) {        
1179             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1180             aop->coff++;
1181         }
1182         
1183         while (offset < aop->coff) {
1184             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1185             aop->coff--;
1186         }
1187         
1188         aop->coff = offset ;
1189         if (aop->paged) {
1190             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1191             return (dname ? "acc" : "a");
1192         }       
1193         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1194         rs = Safe_calloc(1,strlen(s)+1);
1195         strcpy(rs,s);   
1196         return rs;
1197         
1198     case AOP_DPTR:
1199     case AOP_DPTR2:
1200         DEBUGpic16_emitcode(";","%d",__LINE__);
1201     if (aop->type == AOP_DPTR2)
1202     {
1203         genSetDPTR(1);
1204     }
1205     
1206         while (offset > aop->coff) {
1207             pic16_emitcode ("inc","dptr");
1208             aop->coff++;
1209         }
1210         
1211         while (offset < aop->coff) {        
1212             pic16_emitcode("lcall","__decdptr");
1213             aop->coff--;
1214         }
1215         
1216         aop->coff = offset;
1217         if (aop->code) {
1218             pic16_emitcode("clr","a");
1219             pic16_emitcode("movc","a,@a+dptr");
1220         }
1221     else {
1222             pic16_emitcode("movx","a,@dptr");
1223     }
1224             
1225     if (aop->type == AOP_DPTR2)
1226     {
1227         genSetDPTR(0);
1228     }
1229             
1230     return (dname ? "acc" : "a");
1231         
1232         
1233     case AOP_IMMD:
1234         if (bit16) 
1235             sprintf (s,"%s",aop->aopu.aop_immd);
1236         else
1237             if (offset) 
1238                 sprintf(s,"(%s >> %d)",
1239                         aop->aopu.aop_immd,
1240                         offset*8);
1241             else
1242                 sprintf(s,"%s",
1243                         aop->aopu.aop_immd);
1244         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1245         rs = Safe_calloc(1,strlen(s)+1);
1246         strcpy(rs,s);   
1247         return rs;
1248         
1249     case AOP_DIR:
1250       if (offset) {
1251         sprintf(s,"(%s + %d)",
1252                 aop->aopu.aop_dir,
1253                 offset);
1254         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1255       } else
1256             sprintf(s,"%s",aop->aopu.aop_dir);
1257         rs = Safe_calloc(1,strlen(s)+1);
1258         strcpy(rs,s);   
1259         return rs;
1260         
1261     case AOP_REG:
1262       //if (dname) 
1263       //    return aop->aopu.aop_reg[offset]->dname;
1264       //else
1265             return aop->aopu.aop_reg[offset]->name;
1266         
1267     case AOP_CRY:
1268       //pic16_emitcode(";","%d",__LINE__);
1269       return aop->aopu.aop_dir;
1270         
1271     case AOP_ACC:
1272         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1273 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1274 //        assert( 0 );
1275         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1276
1277     case AOP_LIT:
1278         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1279         rs = Safe_calloc(1,strlen(s)+1);
1280         strcpy(rs,s);   
1281         return rs;
1282         
1283     case AOP_STR:
1284         aop->coff = offset ;
1285         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1286             dname)
1287             return "acc";
1288         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1289         
1290         return aop->aopu.aop_str[offset];
1291         
1292     case AOP_PCODE:
1293       {
1294         pCodeOp *pcop = aop->aopu.pcop;
1295         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1296         if(pcop->name) {
1297           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1298           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1299           sprintf(s,"%s", pcop->name);
1300         } else
1301           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1302
1303       }
1304       rs = Safe_calloc(1,strlen(s)+1);
1305       strcpy(rs,s);   
1306       return rs;
1307
1308     }
1309
1310     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1311            "aopget got unsupported aop->type");
1312     exit(0);
1313 }
1314
1315
1316 /*-----------------------------------------------------------------*/
1317 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1318 /*-----------------------------------------------------------------*/
1319 pCodeOp *pic16_popGetTempReg(void)
1320 {
1321   pCodeOp *pcop;
1322   symbol *cfunc;
1323
1324 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1325
1326         cfunc = currFunc;
1327         currFunc = NULL;
1328
1329         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1330         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1331                 PCOR(pcop)->r->wasUsed=1;
1332                 PCOR(pcop)->r->isFree=0;
1333
1334                 /* push value on stack */
1335                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1336         }
1337
1338         currFunc = cfunc;
1339
1340   return pcop;
1341 }
1342
1343 /*-----------------------------------------------------------------*/
1344 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1345 /*-----------------------------------------------------------------*/
1346 void pic16_popReleaseTempReg(pCodeOp *pcop)
1347 {
1348         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1349
1350         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1351                 PCOR(pcop)->r->isFree = 1;
1352                 
1353                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1354         }
1355 }
1356 /*-----------------------------------------------------------------*/
1357 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1358 /*-----------------------------------------------------------------*/
1359 pCodeOp *pic16_popGetLabel(unsigned int key)
1360 {
1361
1362   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1363
1364   if(key>max_key)
1365     max_key = key;
1366
1367   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1368 }
1369
1370 /*-----------------------------------------------------------------*/
1371 /* pic16_popCopyReg - copy a pcode operator                              */
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1374 {
1375   pCodeOpReg *pcor;
1376
1377   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1378   pcor->pcop.type = pc->pcop.type;
1379   if(pc->pcop.name) {
1380     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1381       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1382   } else
1383     pcor->pcop.name = NULL;
1384
1385   pcor->r = pc->r;
1386   pcor->rIdx = pc->rIdx;
1387   pcor->r->wasUsed=1;
1388
1389 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1390
1391   return PCOP(pcor);
1392 }
1393
1394 /*-----------------------------------------------------------------*/
1395 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1396 /*-----------------------------------------------------------------*/
1397 pCodeOp *pic16_popGetLit(unsigned int lit)
1398 {
1399   return pic16_newpCodeOpLit(lit);
1400 }
1401
1402 /*-----------------------------------------------------------------*/
1403 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1404 /*-----------------------------------------------------------------*/
1405 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1406 {
1407   return pic16_newpCodeOpLit2(lit, arg2);
1408 }
1409
1410
1411 /*-----------------------------------------------------------------*/
1412 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1413 /*-----------------------------------------------------------------*/
1414 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1415 {
1416   return pic16_newpCodeOpImmd(name, offset,index, 0);
1417 }
1418
1419
1420 /*-----------------------------------------------------------------*/
1421 /* pic16_popGet - asm operator to pcode operator conversion              */
1422 /*-----------------------------------------------------------------*/
1423 pCodeOp *pic16_popGetWithString(char *str)
1424 {
1425   pCodeOp *pcop;
1426
1427
1428   if(!str) {
1429     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1430     exit (1);
1431   }
1432
1433   pcop = pic16_newpCodeOp(str,PO_STR);
1434
1435   return pcop;
1436 }
1437
1438 /*-----------------------------------------------------------------*/
1439 /* pic16_popRegFromString -                                        */
1440 /*-----------------------------------------------------------------*/
1441 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1442 {
1443
1444   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1445   pcop->type = PO_DIR;
1446
1447   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1448   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1449
1450   if(!str)
1451     str = "BAD_STRING";
1452
1453   pcop->name = Safe_calloc(1,strlen(str)+1);
1454   strcpy(pcop->name,str);
1455
1456   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1457
1458   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1459   if(PCOR(pcop)->r == NULL) {
1460 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1461 //              __FUNCTION__, __LINE__, str, size, offset);
1462     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1463
1464         //fprintf(stderr, "allocating new register -> %s\n", str);
1465
1466 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1467   } else {
1468 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1469   }
1470   PCOR(pcop)->instance = offset;
1471
1472   return pcop;
1473 }
1474
1475 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1476 {
1477   pCodeOp *pcop;
1478
1479 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1480
1481         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1482         PCOR(pcop)->rIdx = rIdx;
1483         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1484         PCOR(pcop)->r->isFree = 0;
1485         PCOR(pcop)->r->wasUsed = 1;
1486
1487         pcop->type = PCOR(pcop)->r->pc_type;
1488
1489   return pcop;
1490 }
1491
1492 /*---------------------------------------------------------------------------------*/
1493 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1494 /*                 VR 030601                                                       */
1495 /*---------------------------------------------------------------------------------*/
1496 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1497 {
1498   pCodeOpReg2 *pcop2;
1499   pCodeOp *temp;
1500   
1501         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1502
1503         /* comment the following check, so errors to throw up */
1504 //      if(!pcop2)return NULL;
1505
1506         temp = pic16_popGet(aop_dst, offset);
1507         pcop2->pcop2 = temp;
1508         
1509   return PCOP(pcop2);
1510 }
1511
1512
1513
1514 /*--------------------------------------------------------------------------------.-*/
1515 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1516 /*                  VR 030601 , adapted by Hans Dorn                                */
1517 /*--------------------------------------------------------------------------------.-*/
1518 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1519 {
1520   pCodeOpReg2 *pcop2;
1521  
1522         pcop2 = (pCodeOpReg2 *)src;
1523         pcop2->pcop2 = dst;
1524         
1525         return PCOP(pcop2);
1526 }
1527
1528
1529
1530 /*---------------------------------------------------------------------------------*/
1531 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1532 /*                     movff instruction                                           */
1533 /*---------------------------------------------------------------------------------*/
1534 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1535 {
1536   pCodeOpReg2 *pcop2;
1537
1538         if(!noalloc) {
1539                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1540                 pcop2->pcop2 = pic16_popCopyReg(dst);
1541         } else {
1542                 /* the pCodeOp may be already allocated */
1543                 pcop2 = (pCodeOpReg2 *)(src);
1544                 pcop2->pcop2 = (pCodeOp *)(dst);
1545         }
1546
1547   return PCOP(pcop2);
1548 }
1549
1550
1551 /*-----------------------------------------------------------------*/
1552 /* pic16_popGet - asm operator to pcode operator conversion              */
1553 /*-----------------------------------------------------------------*/
1554 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1555 {
1556   //char *s = buffer ;
1557   char *rs;
1558   pCodeOp *pcop;
1559
1560     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1561     /* offset is greater than
1562     size then zero */
1563
1564 //    if (offset > (aop->size - 1) &&
1565 //        aop->type != AOP_LIT)
1566 //      return NULL;  //zero;
1567
1568     /* depending on type */
1569     switch (aop->type) {
1570         
1571     case AOP_R0:
1572     case AOP_R1:
1573     case AOP_DPTR:
1574     case AOP_DPTR2:
1575         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1576         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1577         assert( 0 );
1578         return NULL;
1579
1580
1581
1582     case AOP_IMMD:
1583       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1584       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1585
1586     case AOP_ACC:
1587       {
1588         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1589
1590         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1591
1592         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1593         
1594         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595         PCOR(pcop)->rIdx = rIdx;
1596         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1597         PCOR(pcop)->r->wasUsed=1;
1598         PCOR(pcop)->r->isFree=0;
1599
1600         PCOR(pcop)->instance = offset;
1601         pcop->type = PCOR(pcop)->r->pc_type;
1602 //      rs = aop->aopu.aop_reg[offset]->name;
1603 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1604         return pcop;
1605
1606
1607 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1608 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1609
1610 //      assert( 0 );
1611       }
1612         
1613     case AOP_DIR:
1614       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1615       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1616         
1617     case AOP_REG:
1618       {
1619         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1620
1621         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1622         
1623         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1624         PCOR(pcop)->rIdx = rIdx;
1625         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1626         PCOR(pcop)->r->wasUsed=1;
1627         PCOR(pcop)->r->isFree=0;
1628
1629         PCOR(pcop)->instance = offset;
1630         pcop->type = PCOR(pcop)->r->pc_type;
1631         rs = aop->aopu.aop_reg[offset]->name;
1632         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1633         return pcop;
1634       }
1635
1636     case AOP_CRY:
1637         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1638
1639       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1640       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1641       //if(PCOR(pcop)->r == NULL)
1642       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1643       return pcop;
1644         
1645     case AOP_LIT:
1646         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1647       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1648
1649     case AOP_STR:
1650       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1651       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1652
1653       /*
1654       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1655       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1656       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1657       pcop->type = PCOR(pcop)->r->pc_type;
1658       pcop->name = PCOR(pcop)->r->name;
1659
1660       return pcop;
1661       */
1662
1663     case AOP_PCODE:
1664       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1665                           __LINE__, 
1666                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1667       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1668 #if 1
1669         switch( aop->aopu.pcop->type ) {
1670                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1671                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1672                 default:
1673                         assert( 0 );    /* should never reach here */;
1674         }
1675 #else
1676       PCOI(pcop)->offset = offset;
1677 #endif
1678       return pcop;
1679     }
1680
1681     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1682            "pic16_popGet got unsupported aop->type");
1683     exit(0);
1684 }
1685 /*-----------------------------------------------------------------*/
1686 /* pic16_aopPut - puts a string for a aop                                */
1687 /*-----------------------------------------------------------------*/
1688 void pic16_aopPut (asmop *aop, char *s, int offset)
1689 {
1690     char *d = buffer ;
1691     symbol *lbl ;
1692
1693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1694
1695     if (aop->size && offset > ( aop->size - 1)) {
1696         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1697                "pic16_aopPut got offset > aop->size");
1698         exit(0);
1699     }
1700
1701     /* will assign value to value */
1702     /* depending on where it is ofcourse */
1703     switch (aop->type) {
1704     case AOP_DIR:
1705       if (offset) {
1706         sprintf(d,"(%s + %d)",
1707                 aop->aopu.aop_dir,offset);
1708         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1709
1710       } else
1711             sprintf(d,"%s",aop->aopu.aop_dir);
1712         
1713         if (strcmp(d,s)) {
1714           DEBUGpic16_emitcode(";","%d",__LINE__);
1715           if(strcmp(s,"W"))
1716             pic16_emitcode("movf","%s,w",s);
1717           pic16_emitcode("movwf","%s",d);
1718
1719           if(strcmp(s,"W")) {
1720             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1721             if(offset >= aop->size) {
1722               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1723               break;
1724             } else
1725               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1726           }
1727
1728           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1729
1730
1731         }
1732         break;
1733         
1734     case AOP_REG:
1735       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1736         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1737           /*
1738             if (*s == '@'           ||
1739                 strcmp(s,"r0") == 0 ||
1740                 strcmp(s,"r1") == 0 ||
1741                 strcmp(s,"r2") == 0 ||
1742                 strcmp(s,"r3") == 0 ||
1743                 strcmp(s,"r4") == 0 ||
1744                 strcmp(s,"r5") == 0 ||
1745                 strcmp(s,"r6") == 0 || 
1746                 strcmp(s,"r7") == 0 )
1747                 pic16_emitcode("mov","%s,%s  ; %d",
1748                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1749             else
1750           */
1751
1752           if(strcmp(s,"W")==0 )
1753             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1754
1755           pic16_emitcode("movwf","%s",
1756                    aop->aopu.aop_reg[offset]->name);
1757
1758           if(strcmp(s,zero)==0) {
1759             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1760
1761           } else if(strcmp(s,"W")==0) {
1762             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1763             pcop->type = PO_GPR_REGISTER;
1764
1765             PCOR(pcop)->rIdx = -1;
1766             PCOR(pcop)->r = NULL;
1767
1768             DEBUGpic16_emitcode(";","%d",__LINE__);
1769             pcop->name = Safe_strdup(s);
1770             pic16_emitpcode(POC_MOVFW,pcop);
1771             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1772           } else if(strcmp(s,one)==0) {
1773             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1774             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1775           } else {
1776             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1777           }
1778         }
1779         break;
1780         
1781     case AOP_DPTR:
1782     case AOP_DPTR2:
1783     
1784     if (aop->type == AOP_DPTR2)
1785     {
1786         genSetDPTR(1);
1787     }
1788     
1789         if (aop->code) {
1790             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1791                    "pic16_aopPut writting to code space");
1792             exit(0);
1793         }
1794         
1795         while (offset > aop->coff) {
1796             aop->coff++;
1797             pic16_emitcode ("inc","dptr");
1798         }
1799         
1800         while (offset < aop->coff) {
1801             aop->coff-- ;
1802             pic16_emitcode("lcall","__decdptr");
1803         }
1804         
1805         aop->coff = offset;
1806         
1807         /* if not in accumulater */
1808         MOVA(s);        
1809         
1810         pic16_emitcode ("movx","@dptr,a");
1811         
1812     if (aop->type == AOP_DPTR2)
1813     {
1814         genSetDPTR(0);
1815     }
1816         break;
1817         
1818     case AOP_R0:
1819     case AOP_R1:
1820         while (offset > aop->coff) {
1821             aop->coff++;
1822             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1823         }
1824         while (offset < aop->coff) {
1825             aop->coff-- ;
1826             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1827         }
1828         aop->coff = offset;
1829         
1830         if (aop->paged) {
1831             MOVA(s);           
1832             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1833             
1834         } else
1835             if (*s == '@') {
1836                 MOVA(s);
1837                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1838             } else
1839                 if (strcmp(s,"r0") == 0 ||
1840                     strcmp(s,"r1") == 0 ||
1841                     strcmp(s,"r2") == 0 ||
1842                     strcmp(s,"r3") == 0 ||
1843                     strcmp(s,"r4") == 0 ||
1844                     strcmp(s,"r5") == 0 ||
1845                     strcmp(s,"r6") == 0 || 
1846                     strcmp(s,"r7") == 0 ) {
1847                     char buffer[10];
1848                     sprintf(buffer,"a%s",s);
1849                     pic16_emitcode("mov","@%s,%s",
1850                              aop->aopu.aop_ptr->name,buffer);
1851                 } else
1852                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1853         
1854         break;
1855         
1856     case AOP_STK:
1857         if (strcmp(s,"a") == 0)
1858             pic16_emitcode("push","acc");
1859         else
1860             pic16_emitcode("push","%s",s);
1861         
1862         break;
1863         
1864     case AOP_CRY:
1865         /* if bit variable */
1866         if (!aop->aopu.aop_dir) {
1867             pic16_emitcode("clr","a");
1868             pic16_emitcode("rlc","a");
1869         } else {
1870             if (s == zero) 
1871                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1872             else
1873                 if (s == one)
1874                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1875                 else
1876                     if (!strcmp(s,"c"))
1877                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1878                     else {
1879                         lbl = newiTempLabel(NULL);
1880                         
1881                         if (strcmp(s,"a")) {
1882                             MOVA(s);
1883                         }
1884                         pic16_emitcode("clr","c");
1885                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1886                         pic16_emitcode("cpl","c");
1887                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1888                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1889                     }
1890         }
1891         break;
1892         
1893     case AOP_STR:
1894         aop->coff = offset;
1895         if (strcmp(aop->aopu.aop_str[offset],s))
1896             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1897         break;
1898         
1899     case AOP_ACC:
1900         aop->coff = offset;
1901         if (!offset && (strcmp(s,"acc") == 0))
1902             break;
1903         
1904         if (strcmp(aop->aopu.aop_str[offset],s))
1905             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1906         break;
1907
1908     default :
1909         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1910                "pic16_aopPut got unsupported aop->type");
1911         exit(0);    
1912     }    
1913
1914 }
1915
1916 /*-----------------------------------------------------------------*/
1917 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1918 /*-----------------------------------------------------------------*/
1919 static void mov2w (asmop *aop, int offset)
1920 {
1921
1922 //  if(!aop)
1923 //    return;
1924
1925         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1926
1927         if(is_LitAOp(aop))
1928                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1929         else
1930                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1931
1932 }
1933
1934
1935 /* push pcop into stack */
1936 void pic16_pushpCodeOp(pCodeOp *pcop)
1937 {
1938 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1939         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1940 }
1941
1942 /* pop pcop from stack */
1943 void pic16_poppCodeOp(pCodeOp *pcop)
1944 {
1945         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1946 }
1947
1948
1949 /*-----------------------------------------------------------------*/
1950 /* pushw - pushes wreg to stack                                    */
1951 /*-----------------------------------------------------------------*/
1952 void pushw(void)
1953 {
1954         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1955         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1956 }
1957
1958                 
1959 /*-----------------------------------------------------------------*/
1960 /* pushaop - pushes aop to stack                                   */
1961 /*-----------------------------------------------------------------*/
1962 void pushaop(asmop *aop, int offset)
1963 {
1964         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1965         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1966 }
1967
1968 /*-----------------------------------------------------------------*/
1969 /* popaop - pops aop from stack                                    */
1970 /*-----------------------------------------------------------------*/
1971 void popaop(asmop *aop, int offset)
1972 {
1973         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1974         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1975 }
1976
1977 void popaopidx(asmop *aop, int offset, int index)
1978 {
1979   int ofs=1;
1980
1981         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1982
1983         if(STACK_MODEL_LARGE)ofs++;
1984
1985         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1986         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1987 }
1988
1989 /*-----------------------------------------------------------------*/
1990 /* reAdjustPreg - points a register back to where it should        */
1991 /*-----------------------------------------------------------------*/
1992 static void reAdjustPreg (asmop *aop)
1993 {
1994     int size ;
1995
1996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1997     aop->coff = 0;
1998     if ((size = aop->size) <= 1)
1999         return ;
2000     size-- ;
2001     switch (aop->type) {
2002         case AOP_R0 :
2003         case AOP_R1 :
2004             while (size--)
2005                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2006             break;          
2007         case AOP_DPTR :
2008         case AOP_DPTR2:
2009             if (aop->type == AOP_DPTR2)
2010             {
2011                 genSetDPTR(1);
2012             } 
2013             while (size--)
2014             {
2015                 pic16_emitcode("lcall","__decdptr");
2016             }
2017                 
2018             if (aop->type == AOP_DPTR2)
2019             {
2020                 genSetDPTR(0);
2021             }                
2022             break;  
2023
2024     }   
2025
2026 }
2027
2028
2029 #if 0
2030 /*-----------------------------------------------------------------*/
2031 /* opIsGptr: returns non-zero if the passed operand is             */   
2032 /* a generic pointer type.                                         */
2033 /*-----------------------------------------------------------------*/ 
2034 static int opIsGptr(operand *op)
2035 {
2036     sym_link *type = operandType(op);
2037     
2038     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2039     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2040     {
2041         return 1;
2042     }
2043     return 0;        
2044 }
2045 #endif
2046
2047 /*-----------------------------------------------------------------*/
2048 /* pic16_getDataSize - get the operand data size                         */
2049 /*-----------------------------------------------------------------*/
2050 int pic16_getDataSize(operand *op)
2051 {
2052     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2053
2054
2055     return AOP_SIZE(op);
2056
2057     // tsd- in the pic port, the genptr size is 1, so this code here
2058     // fails. ( in the 8051 port, the size was 4).
2059 #if 0
2060     int size;
2061     size = AOP_SIZE(op);
2062     if (size == GPTRSIZE)
2063     {
2064         sym_link *type = operandType(op);
2065         if (IS_GENPTR(type))
2066         {
2067             /* generic pointer; arithmetic operations
2068              * should ignore the high byte (pointer type).
2069              */
2070             size--;
2071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2072         }
2073     }
2074     return size;
2075 #endif
2076 }
2077
2078 /*-----------------------------------------------------------------*/
2079 /* pic16_outAcc - output Acc                                             */
2080 /*-----------------------------------------------------------------*/
2081 void pic16_outAcc(operand *result)
2082 {
2083   int size,offset;
2084   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2085   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2086
2087
2088   size = pic16_getDataSize(result);
2089   if(size){
2090     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2091     size--;
2092     offset = 1;
2093     /* unsigned or positive */
2094     while(size--)
2095       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2096   }
2097
2098 }
2099
2100 /*-----------------------------------------------------------------*/
2101 /* pic16_outBitC - output a bit C                                  */
2102 /*                 Move to result the value of Carry flag -- VR    */
2103 /*-----------------------------------------------------------------*/
2104 void pic16_outBitC(operand *result)
2105 {
2106   int i;
2107
2108     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109     /* if the result is bit */
2110     if (AOP_TYPE(result) == AOP_CRY) {
2111         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2112         pic16_aopPut(AOP(result),"c",0);
2113     } else {
2114
2115         i = AOP_SIZE(result);
2116         while(i--) {
2117                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2118         }
2119         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2120         
2121 /*
2122         pic16_emitcode("clr","a  ; %d", __LINE__);
2123         pic16_emitcode("rlc","a");
2124         pic16_outAcc(result);
2125 */
2126     }
2127 }
2128
2129 /*-----------------------------------------------------------------*/
2130 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2131 /*-----------------------------------------------------------------*/
2132 void pic16_toBoolean(operand *oper)
2133 {
2134     int size = AOP_SIZE(oper) - 1;
2135     int offset = 1;
2136
2137     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2138
2139     if ( AOP_TYPE(oper) != AOP_ACC) {
2140       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2141     }
2142     while (size--) {
2143       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2144     }
2145 }
2146
2147
2148 #if !defined(GEN_Not)
2149 /*-----------------------------------------------------------------*/
2150 /* genNot - generate code for ! operation                          */
2151 /*-----------------------------------------------------------------*/
2152 static void pic16_genNot (iCode *ic)
2153 {
2154   symbol *tlbl;
2155   int size;
2156
2157   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2158   /* assign asmOps to operand & result */
2159   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2160   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2161
2162   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2163   /* if in bit space then a special case */
2164   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2165     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2166       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2167       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2168     } else {
2169       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2170       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2171       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2172     }
2173     goto release;
2174   }
2175
2176   size = AOP_SIZE(IC_LEFT(ic));
2177   if(size == 1) {
2178     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2179     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2180     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2181     goto release;
2182   }
2183   pic16_toBoolean(IC_LEFT(ic));
2184
2185   tlbl = newiTempLabel(NULL);
2186   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2187   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2188   pic16_outBitC(IC_RESULT(ic));
2189
2190  release:    
2191   /* release the aops */
2192   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2193   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2194 }
2195 #endif
2196
2197
2198 #if !defined(GEN_Cpl)
2199 /*-----------------------------------------------------------------*/
2200 /* genCpl - generate code for complement                           */
2201 /*-----------------------------------------------------------------*/
2202 static void pic16_genCpl (iCode *ic)
2203 {
2204     int offset = 0;
2205     int size ;
2206
2207
2208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2209     /* assign asmOps to operand & result */
2210     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2211     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2212
2213     /* if both are in bit space then 
2214     a special case */
2215     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2216         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2217
2218         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2219         pic16_emitcode("cpl","c"); 
2220         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2221         goto release; 
2222     } 
2223
2224     size = AOP_SIZE(IC_RESULT(ic));
2225     while (size--) {
2226 /*
2227         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2228         MOVA(l);       
2229         pic16_emitcode("cpl","a");
2230         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2231 */
2232         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2233               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2234         } else {
2235                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2236                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2237         }
2238         offset++;
2239
2240     }
2241
2242
2243 release:
2244     /* release the aops */
2245     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2246     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2247 }
2248 #endif
2249
2250 /*-----------------------------------------------------------------*/
2251 /* genUminusFloat - unary minus for floating points                */
2252 /*-----------------------------------------------------------------*/
2253 static void genUminusFloat(operand *op,operand *result)
2254 {
2255     int size ,offset =0 ;
2256     char *l;
2257
2258     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2259     /* for this we just need to flip the 
2260     first it then copy the rest in place */
2261     size = AOP_SIZE(op) - 1;
2262     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2263
2264     MOVA(l);    
2265
2266     pic16_emitcode("cpl","acc.7");
2267     pic16_aopPut(AOP(result),"a",3);    
2268
2269     while(size--) {
2270         pic16_aopPut(AOP(result),
2271                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2272                offset);
2273         offset++;
2274     }          
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* genUminus - unary minus code generation                         */
2279 /*-----------------------------------------------------------------*/
2280 static void genUminus (iCode *ic)
2281 {
2282   int size, i;
2283   sym_link *optype, *rtype;
2284
2285         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2286         
2287         /* assign asmops */
2288         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2289         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2290
2291         /* if both in bit space then special case */
2292         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2293                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2294
2295                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2296                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2297                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2298                 
2299                 goto release; 
2300         } 
2301
2302         optype = operandType(IC_LEFT(ic));
2303         rtype = operandType(IC_RESULT(ic));
2304
2305         /* if float then do float stuff */
2306         if (IS_FLOAT(optype)) {
2307                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2308                 goto release;
2309         }
2310
2311         /* otherwise subtract from zero by taking the 2's complement */
2312         size = AOP_SIZE(IC_LEFT(ic));
2313
2314         for(i=0; i<size; i++) {
2315                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2316                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2317                 else {
2318                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2319                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2320                 }
2321         }
2322
2323         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2324         for(i=1; i<size; i++) {
2325                 emitSKPNZ;
2326                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2327         }
2328
2329 release:
2330         /* release the aops */
2331         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2332         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2333 }
2334
2335 /*-----------------------------------------------------------------*/
2336 /* saveRegisters - will look for a call and save the registers     */
2337 /*-----------------------------------------------------------------*/
2338 static void saveRegisters(iCode *lic) 
2339 {
2340     int i;
2341     iCode *ic;
2342     bitVect *rsave;
2343     sym_link *dtype;
2344
2345     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2346     /* look for call */
2347     for (ic = lic ; ic ; ic = ic->next) 
2348         if (ic->op == CALL || ic->op == PCALL)
2349             break;
2350
2351     if (!ic) {
2352         fprintf(stderr,"found parameter push with no function call\n");
2353         return ;
2354     }
2355
2356     /* if the registers have been saved already then
2357     do nothing */
2358     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2359         return ;
2360
2361     /* find the registers in use at this time 
2362     and push them away to safety */
2363     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2364                           ic->rUsed);
2365
2366     ic->regsSaved = 1;
2367     if (options.useXstack) {
2368         if (bitVectBitValue(rsave,R0_IDX))
2369             pic16_emitcode("mov","b,r0");
2370         pic16_emitcode("mov","r0,%s",spname);
2371         for (i = 0 ; i < pic16_nRegs ; i++) {
2372             if (bitVectBitValue(rsave,i)) {
2373                 if (i == R0_IDX)
2374                     pic16_emitcode("mov","a,b");
2375                 else
2376                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2377                 pic16_emitcode("movx","@r0,a");
2378                 pic16_emitcode("inc","r0");
2379             }
2380         }
2381         pic16_emitcode("mov","%s,r0",spname);
2382         if (bitVectBitValue(rsave,R0_IDX))
2383             pic16_emitcode("mov","r0,b");           
2384     }// else
2385     //for (i = 0 ; i < pic16_nRegs ; i++) {
2386     //    if (bitVectBitValue(rsave,i))
2387     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2388     //}
2389
2390     dtype = operandType(IC_LEFT(ic));
2391     if (currFunc && dtype && 
2392         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2393         IFFUNC_ISISR(currFunc->type) &&
2394         !ic->bankSaved) 
2395
2396         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2397
2398 }
2399 /*-----------------------------------------------------------------*/
2400 /* unsaveRegisters - pop the pushed registers                      */
2401 /*-----------------------------------------------------------------*/
2402 static void unsaveRegisters (iCode *ic)
2403 {
2404     int i;
2405     bitVect *rsave;
2406
2407     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2408     /* find the registers in use at this time 
2409     and push them away to safety */
2410     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2411                           ic->rUsed);
2412     
2413     if (options.useXstack) {
2414         pic16_emitcode("mov","r0,%s",spname);   
2415         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2416             if (bitVectBitValue(rsave,i)) {
2417                 pic16_emitcode("dec","r0");
2418                 pic16_emitcode("movx","a,@r0");
2419                 if (i == R0_IDX)
2420                     pic16_emitcode("mov","b,a");
2421                 else
2422                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2423             }       
2424
2425         }
2426         pic16_emitcode("mov","%s,r0",spname);
2427         if (bitVectBitValue(rsave,R0_IDX))
2428             pic16_emitcode("mov","r0,b");
2429     } //else
2430     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2431     //    if (bitVectBitValue(rsave,i))
2432     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2433     //}
2434
2435 }  
2436
2437 #if 0  // patch 14
2438 /*-----------------------------------------------------------------*/
2439 /* pushSide -                                                      */
2440 /*-----------------------------------------------------------------*/
2441 static void pushSide(operand * oper, int size)
2442 {
2443         int offset = 0;
2444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2445         while (size--) {
2446                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2447                 if (AOP_TYPE(oper) != AOP_REG &&
2448                     AOP_TYPE(oper) != AOP_DIR &&
2449                     strcmp(l,"a") ) {
2450                         pic16_emitcode("mov","a,%s",l);
2451                         pic16_emitcode("push","acc");
2452                 } else
2453                         pic16_emitcode("push","%s",l);
2454         }
2455 }
2456 #endif // patch 14
2457
2458 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2459 {
2460 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2461
2462         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2463                 pic16_emitpcode(POC_MOVFW, src);
2464                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2465         } else {
2466                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2467                         src, pic16_popGet(AOP(op), offset)));
2468         }
2469 }
2470
2471
2472 /*-----------------------------------------------------------------*/
2473 /* assignResultValue - assign results to oper, rescall==1 is       */
2474 /*                     called from genCall() or genPCall()         */
2475 /*-----------------------------------------------------------------*/
2476 static void assignResultValue(operand * oper, int rescall)
2477 {
2478   int size = AOP_SIZE(oper);
2479
2480         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2481         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2482
2483         if(rescall) {
2484                 /* assign result from a call/pcall function() */
2485                 
2486                 /* function results are stored in a special order,
2487                  * see top of file with Function return policy, or manual */
2488
2489                 if(size <= 4) {
2490                         /* 8-bits, result in WREG */
2491                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2492                         
2493                         if(size>1) {
2494                                 /* 16-bits, result in PRODL:WREG */
2495                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2496                         }
2497                         
2498                         if(size>2) {
2499                                 /* 24-bits, result in PRODH:PRODL:WREG */
2500                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2501                         }
2502                         
2503                         if(size>3) {
2504                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2505                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2506                         }
2507                 } else {
2508                         /* >32-bits, result on stack, and FSR0 points to beginning.
2509                          * Fix stack when done */
2510                          
2511                         while (size--) {
2512 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2513 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2514                 
2515                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2516                                 GpsuedoStkPtr++;
2517                         }
2518                         
2519                         /* fix stack */
2520                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2521                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2522                         if(STACK_MODEL_LARGE) {
2523                                 emitSKPNC;
2524                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2525                         }
2526                 }                       
2527         } else {        
2528                 if(!GpsuedoStkPtr) {
2529 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2530                         /* The last byte in the assignment is in W */
2531                         size--;
2532                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2533                         GpsuedoStkPtr++;
2534                 }
2535
2536                 while (size--) {
2537 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2538 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2539                 
2540                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2541                         GpsuedoStkPtr++;
2542
2543 #if 0
2544 #if STACK_SUPPORT
2545                 if(!USE_STACK)
2546                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2547 #else
2548                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2549 #endif
2550 #endif
2551
2552                 }
2553         }
2554                 
2555 }
2556
2557
2558 /*-----------------------------------------------------------------*/
2559 /* genIpush - genrate code for pushing this gets a little complex  */
2560 /*-----------------------------------------------------------------*/
2561 static void genIpush (iCode *ic)
2562 {
2563
2564   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2565 #if 0
2566     int size, offset = 0 ;
2567     char *l;
2568
2569
2570     /* if this is not a parm push : ie. it is spill push 
2571     and spill push is always done on the local stack */
2572     if (!ic->parmPush) {
2573
2574         /* and the item is spilt then do nothing */
2575         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2576             return ;
2577
2578         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2579         size = AOP_SIZE(IC_LEFT(ic));
2580         /* push it on the stack */
2581         while(size--) {
2582             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2583             if (*l == '#') {
2584                 MOVA(l);
2585                 l = "acc";
2586             }
2587             pic16_emitcode("push","%s",l);
2588         }
2589         return ;        
2590     }
2591
2592     /* this is a paramter push: in this case we call
2593     the routine to find the call and save those
2594     registers that need to be saved */   
2595     saveRegisters(ic);
2596
2597     /* then do the push */
2598     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2599
2600
2601         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2602     size = AOP_SIZE(IC_LEFT(ic));
2603
2604     while (size--) {
2605         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2606         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2607             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2608             strcmp(l,"a") ) {
2609             pic16_emitcode("mov","a,%s",l);
2610             pic16_emitcode("push","acc");
2611         } else
2612             pic16_emitcode("push","%s",l);
2613     }       
2614
2615     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2616 #endif
2617 }
2618
2619 /*-----------------------------------------------------------------*/
2620 /* genIpop - recover the registers: can happen only for spilling   */
2621 /*-----------------------------------------------------------------*/
2622 static void genIpop (iCode *ic)
2623 {
2624   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2625 #if 0
2626     int size,offset ;
2627
2628
2629     /* if the temp was not pushed then */
2630     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2631         return ;
2632
2633     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2634     size = AOP_SIZE(IC_LEFT(ic));
2635     offset = (size-1);
2636     while (size--) 
2637         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2638                                    FALSE,TRUE));
2639
2640     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2641 #endif
2642 }
2643
2644 /*-----------------------------------------------------------------*/
2645 /* unsaverbank - restores the resgister bank from stack            */
2646 /*-----------------------------------------------------------------*/
2647 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2648 {
2649   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2650 #if 0
2651     int i;
2652     asmop *aop ;
2653     regs *r = NULL;
2654
2655     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2656     if (popPsw) {
2657         if (options.useXstack) {
2658             aop = newAsmop(0);
2659             r = getFreePtr(ic,&aop,FALSE);
2660             
2661             
2662             pic16_emitcode("mov","%s,_spx",r->name);
2663             pic16_emitcode("movx","a,@%s",r->name);
2664             pic16_emitcode("mov","psw,a");
2665             pic16_emitcode("dec","%s",r->name);
2666             
2667         }else
2668             pic16_emitcode ("pop","psw");
2669     }
2670
2671     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2672         if (options.useXstack) {       
2673             pic16_emitcode("movx","a,@%s",r->name);
2674             //pic16_emitcode("mov","(%s+%d),a",
2675             //       regspic16[i].base,8*bank+regspic16[i].offset);
2676             pic16_emitcode("dec","%s",r->name);
2677
2678         } else 
2679           pic16_emitcode("pop",""); //"(%s+%d)",
2680         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2681     }
2682
2683     if (options.useXstack) {
2684
2685         pic16_emitcode("mov","_spx,%s",r->name);
2686         pic16_freeAsmop(NULL,aop,ic,TRUE);
2687
2688     }
2689 #endif 
2690 }
2691
2692 /*-----------------------------------------------------------------*/
2693 /* saverbank - saves an entire register bank on the stack          */
2694 /*-----------------------------------------------------------------*/
2695 static void saverbank (int bank, iCode *ic, bool pushPsw)
2696 {
2697   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2698 #if 0
2699     int i;
2700     asmop *aop ;
2701     regs *r = NULL;
2702
2703     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2704     if (options.useXstack) {
2705
2706         aop = newAsmop(0);
2707         r = getFreePtr(ic,&aop,FALSE);  
2708         pic16_emitcode("mov","%s,_spx",r->name);
2709
2710     }
2711
2712     for (i = 0 ; i < pic16_nRegs ;i++) {
2713         if (options.useXstack) {
2714             pic16_emitcode("inc","%s",r->name);
2715             //pic16_emitcode("mov","a,(%s+%d)",
2716             //         regspic16[i].base,8*bank+regspic16[i].offset);
2717             pic16_emitcode("movx","@%s,a",r->name);           
2718         } else 
2719           pic16_emitcode("push","");// "(%s+%d)",
2720                      //regspic16[i].base,8*bank+regspic16[i].offset);
2721     }
2722     
2723     if (pushPsw) {
2724         if (options.useXstack) {
2725             pic16_emitcode("mov","a,psw");
2726             pic16_emitcode("movx","@%s,a",r->name);     
2727             pic16_emitcode("inc","%s",r->name);
2728             pic16_emitcode("mov","_spx,%s",r->name);       
2729             pic16_freeAsmop (NULL,aop,ic,TRUE);
2730             
2731         } else
2732             pic16_emitcode("push","psw");
2733         
2734         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2735     }
2736     ic->bankSaved = 1;
2737 #endif
2738 }
2739
2740
2741
2742 /*-----------------------------------------------------------------*/
2743 /* genCall - generates a call statement                            */
2744 /*-----------------------------------------------------------------*/
2745 static void genCall (iCode *ic)
2746 {
2747   sym_link *dtype;   
2748   int stackParms=0;
2749   
2750         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2751
2752         /* if caller saves & we have not saved then */
2753         if (!ic->regsSaved)
2754                 saveRegisters(ic);
2755
2756         /* if we are calling a function that is not using
2757          * the same register bank then we need to save the
2758          * destination registers on the stack */
2759         dtype = operandType(IC_LEFT(ic));
2760         if (currFunc && dtype && 
2761                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2762                 IFFUNC_ISISR(currFunc->type) &&
2763                 !ic->bankSaved) 
2764
2765                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2766
2767         /* if send set is not empty the assign */
2768         if (_G.sendSet) {
2769           iCode *sic;
2770
2771                 /* For the Pic port, there is no data stack.
2772                  * So parameters passed to functions are stored
2773                  * in registers. (The pCode optimizer will get
2774                  * rid of most of these :). */
2775
2776           int psuedoStkPtr=-1; 
2777           int firstTimeThruLoop = 1;
2778
2779                 _G.sendSet = reverseSet(_G.sendSet);
2780
2781                 /* First figure how many parameters are getting passed */
2782                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2783                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2784                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2785                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2786                 }
2787
2788                 stackParms = psuedoStkPtr;
2789
2790                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2791                   int size, offset = 0;
2792
2793                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2794                         size = AOP_SIZE(IC_LEFT(sic));
2795
2796                         while (size--) {
2797                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2798                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2799                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2800
2801                                 if(!firstTimeThruLoop) {
2802                                         /* If this is not the first time we've been through the loop
2803                                          * then we need to save the parameter in a temporary
2804                                          * register. The last byte of the last parameter is
2805                                          * passed in W. */
2806
2807                                         pushw();
2808                                         --psuedoStkPtr;         // sanity check
2809                                 }
2810                         
2811                                 firstTimeThruLoop=0;
2812
2813                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2814                                 offset++;
2815                         }
2816                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2817                 }
2818                 _G.sendSet = NULL;
2819         }
2820
2821         /* make the call */
2822         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2823                         OP_SYMBOL(IC_LEFT(ic))->rname :
2824                         OP_SYMBOL(IC_LEFT(ic))->name));
2825
2826         GpsuedoStkPtr=0;
2827         /* if we need assign a result value */
2828         if ((IS_ITEMP(IC_RESULT(ic)) && 
2829                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2830                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2831                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2832
2833                 _G.accInUse++;
2834                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2835                 _G.accInUse--;
2836
2837                 assignResultValue(IC_RESULT(ic), 1);
2838
2839                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2840                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2841                 
2842                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2843         }
2844
2845         if(stackParms>0) {
2846                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2847                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2848                 if(STACK_MODEL_LARGE) {
2849                         emitSKPNC;
2850                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2851                 }
2852         }
2853
2854         /* adjust the stack for parameters if required */
2855 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2856
2857         if (ic->parmBytes) {
2858           int i;
2859
2860                 if (ic->parmBytes > 3) {
2861                         pic16_emitcode("mov","a,%s",spname);
2862                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2863                         pic16_emitcode("mov","%s,a",spname);
2864                 } else 
2865                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2866                                 pic16_emitcode("dec","%s",spname);
2867         }
2868
2869 #if 0
2870         /* if register bank was saved then pop them */
2871         if (ic->bankSaved)
2872                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2873
2874         /* if we hade saved some registers then unsave them */
2875         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2876                 unsaveRegisters (ic);
2877 #endif
2878 }
2879
2880
2881
2882 /*-----------------------------------------------------------------*/   // patch 14
2883 /* genPcall - generates a call by pointer statement                */
2884 /*-----------------------------------------------------------------*/
2885
2886 // new version, created from genCall
2887
2888 static void genPcall (iCode *ic)
2889 {
2890   sym_link *dtype;   
2891   int stackParms=0;
2892   symbol *retlbl = newiTempLabel(NULL);
2893   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2894   
2895         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2896
2897         /* if caller saves & we have not saved then */
2898         if (!ic->regsSaved)
2899                 saveRegisters(ic);
2900
2901         /* if we are calling a function that is not using
2902          * the same register bank then we need to save the
2903          * destination registers on the stack */
2904         dtype = operandType(IC_LEFT(ic));
2905         if (currFunc && dtype && 
2906                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2907                 IFFUNC_ISISR(currFunc->type) &&
2908                 !ic->bankSaved) 
2909
2910                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2911
2912         /* if send set is not empty the assign */
2913         if (_G.sendSet) {
2914           iCode *sic;
2915
2916                 /* For the Pic port, there is no data stack.
2917                  * So parameters passed to functions are stored
2918                  * in registers. (The pCode optimizer will get
2919                  * rid of most of these :). */
2920
2921           int psuedoStkPtr=-1; 
2922           int firstTimeThruLoop = 1;
2923
2924                 _G.sendSet = reverseSet(_G.sendSet);
2925
2926                 /* First figure how many parameters are getting passed */
2927                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2928                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2929                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2930                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2931                 }
2932
2933                 stackParms = psuedoStkPtr;
2934
2935                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2936                   int size, offset = 0;
2937
2938                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2939                         size = AOP_SIZE(IC_LEFT(sic));
2940
2941                         while (size--) {
2942                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2943                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2944                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2945
2946                                 if(!firstTimeThruLoop) {
2947                                         /* If this is not the first time we've been through the loop
2948                                          * then we need to save the parameter in a temporary
2949                                          * register. The last byte of the last parameter is
2950                                          * passed in W. */
2951
2952                                         pushw();
2953                                         --psuedoStkPtr;         // sanity check
2954                                 }
2955                         
2956                                 firstTimeThruLoop=0;
2957
2958                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2959                                 offset++;
2960                         }
2961                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2962                 }
2963                 _G.sendSet = NULL;
2964         }
2965
2966         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2967
2968         // push return address
2969         // push $ on return stack, then replace with retlbl
2970
2971         pic16_emitpcodeNULLop(POC_PUSH);
2972
2973         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2974         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2975         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2976         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2977         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2978         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2979
2980         /* make the call by writing the pointer into pc */
2981         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2982         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2983
2984         // note: MOVFF to PCL not allowed
2985         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2986         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2987
2988
2989 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2990 //      pic16_emitpcodeNULLop(POC_NOP);
2991 //      pic16_emitpcodeNULLop(POC_NOP);
2992
2993         /* return address is here: (X) */
2994         pic16_emitpLabelFORCE(retlbl->key);
2995
2996 //      pic16_emitpcodeNULLop(POC_NOP);
2997
2998         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2999
3000         GpsuedoStkPtr=0;
3001         /* if we need assign a result value */
3002         if ((IS_ITEMP(IC_RESULT(ic)) && 
3003                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3004                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3005                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3006
3007                 _G.accInUse++;
3008                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3009                 _G.accInUse--;
3010
3011                 assignResultValue(IC_RESULT(ic), 1);
3012
3013                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3014                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3015                 
3016                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3017         }
3018
3019         if(stackParms>0) {
3020                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3021                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3022                 if(STACK_MODEL_LARGE) {
3023                         emitSKPNC;
3024                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3025                 }
3026         }
3027
3028         /* adjust the stack for parameters if required */
3029 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3030
3031         if (ic->parmBytes) {
3032           int i;
3033
3034                 if (ic->parmBytes > 3) {
3035                         pic16_emitcode("mov","a,%s",spname);
3036                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3037                         pic16_emitcode("mov","%s,a",spname);
3038                 } else 
3039                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3040                                 pic16_emitcode("dec","%s",spname);
3041         }
3042
3043         /* if register bank was saved then pop them */
3044         if (ic->bankSaved)
3045                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3046
3047         /* if we hade saved some registers then unsave them */
3048         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3049                 unsaveRegisters (ic);
3050 }
3051
3052
3053 #if 0                                                                           // patch 14
3054 // old version, kept for reference
3055
3056 /*-----------------------------------------------------------------*/
3057 /* genPcall - generates a call by pointer statement                */
3058 /*-----------------------------------------------------------------*/
3059 static void genPcall (iCode *ic)
3060 {
3061     sym_link *dtype;
3062     symbol *rlbl = newiTempLabel(NULL);
3063
3064
3065     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3066     /* if caller saves & we have not saved then */
3067     if (!ic->regsSaved)
3068         saveRegisters(ic);
3069
3070     /* if we are calling a function that is not using
3071     the same register bank then we need to save the
3072     destination registers on the stack */
3073     dtype = operandType(IC_LEFT(ic));
3074     if (currFunc && dtype && 
3075         IFFUNC_ISISR(currFunc->type) &&
3076         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3077         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3078
3079
3080     /* push the return address on to the stack */
3081     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3082     pic16_emitcode("push","acc");    
3083     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3084     pic16_emitcode("push","acc");
3085     
3086     if (options.model == MODEL_FLAT24)
3087     {
3088         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3089         pic16_emitcode("push","acc");    
3090     }
3091
3092     /* now push the calling address */
3093     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3094
3095     pushSide(IC_LEFT(ic), FPTRSIZE);
3096
3097     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3098
3099     /* if send set is not empty the assign */
3100     if (_G.sendSet) {
3101         iCode *sic ;
3102
3103         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3104              sic = setNextItem(_G.sendSet)) {
3105             int size, offset = 0;
3106             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3107             size = AOP_SIZE(IC_LEFT(sic));
3108             while (size--) {
3109                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3110                                 FALSE,FALSE);
3111                 if (strcmp(l,fReturn[offset]))
3112                     pic16_emitcode("mov","%s,%s",
3113                              fReturn[offset],
3114                              l);
3115                 offset++;
3116             }
3117             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3118         }
3119         _G.sendSet = NULL;
3120     }
3121
3122     pic16_emitcode("ret","");
3123     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3124
3125
3126     /* if we need assign a result value */
3127     if ((IS_ITEMP(IC_RESULT(ic)) &&
3128          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3129           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3130         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3131
3132         _G.accInUse++;
3133         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3134         _G.accInUse--;
3135         
3136         assignResultValue(IC_RESULT(ic), 1);
3137
3138         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3139     }
3140
3141     /* adjust the stack for parameters if 
3142     required */
3143     if (ic->parmBytes) {
3144         int i;
3145         if (ic->parmBytes > 3) {
3146             pic16_emitcode("mov","a,%s",spname);
3147             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3148             pic16_emitcode("mov","%s,a",spname);
3149         } else 
3150             for ( i = 0 ; i <  ic->parmBytes ;i++)
3151                 pic16_emitcode("dec","%s",spname);
3152
3153     }
3154
3155     /* if register bank was saved then unsave them */
3156     if (currFunc && dtype && 
3157         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3158         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3159
3160     /* if we hade saved some registers then
3161     unsave them */
3162     if (ic->regsSaved)
3163         unsaveRegisters (ic);
3164
3165 }
3166 #endif                                                                          // patch 14
3167
3168
3169 /*-----------------------------------------------------------------*/
3170 /* resultRemat - result  is rematerializable                       */
3171 /*-----------------------------------------------------------------*/
3172 static int resultRemat (iCode *ic)
3173 {
3174   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3175   if (SKIP_IC(ic) || ic->op == IFX)
3176     return 0;
3177
3178   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3179     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3180     if (sym->remat && !POINTER_SET(ic)) 
3181       return 1;
3182   }
3183
3184   return 0;
3185 }
3186
3187 #if defined(__BORLANDC__) || defined(_MSC_VER)
3188 #define STRCASECMP stricmp
3189 #else
3190 #define STRCASECMP strcasecmp
3191 #endif
3192
3193 #if 0
3194 /*-----------------------------------------------------------------*/
3195 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3196 /*-----------------------------------------------------------------*/
3197 static bool inExcludeList(char *s)
3198 {
3199   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3200     int i =0;
3201     
3202     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3203     if (options.excludeRegs[i] &&
3204     STRCASECMP(options.excludeRegs[i],"none") == 0)
3205         return FALSE ;
3206
3207     for ( i = 0 ; options.excludeRegs[i]; i++) {
3208         if (options.excludeRegs[i] &&
3209         STRCASECMP(s,options.excludeRegs[i]) == 0)
3210             return TRUE;
3211     }
3212     return FALSE ;
3213 }
3214 #endif
3215
3216 /*-----------------------------------------------------------------*/
3217 /* genFunction - generated code for function entry                 */
3218 /*-----------------------------------------------------------------*/
3219 static void genFunction (iCode *ic)
3220 {
3221   symbol *sym;
3222   sym_link *ftype;
3223   
3224         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3225
3226         labelOffset += (max_key+4);
3227         max_key=0;
3228         GpsuedoStkPtr=0;
3229         _G.nRegsSaved = 0;
3230
3231         ftype = operandType(IC_LEFT(ic));
3232         sym = OP_SYMBOL(IC_LEFT(ic));
3233
3234         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3235                 /* create an absolute section at the interrupt vector:
3236                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3237           symbol *asym;
3238           char asymname[128];
3239           pBlock *apb;
3240
3241                 {
3242                   int i, found=-1;
3243
3244                         sym = OP_SYMBOL( IC_LEFT(ic));
3245                         for(i=0;i<=2;i++) {
3246                                 if(interrupts[i]->name
3247                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3248                                         found = i;
3249                                         break;
3250                                 }
3251                         }
3252                         
3253                         if(found == -1) {
3254                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3255                                         __FILE__, __LINE__, sym->name);
3256                                 assert( 0 );
3257                         }
3258                         _G.interruptvector = found;
3259                 }
3260
3261                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3262                 asym = newSymbol(asymname, 0);
3263
3264                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3265                 pic16_addpBlock( apb );
3266
3267                 pic16_addpCode2pBlock(apb,
3268                         pic16_newpCodeCharP(";-----------------------------------------"));
3269
3270
3271                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3272
3273                 pic16_addpCode2pBlock(apb,
3274                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3275                 
3276                 /* mark the end of this tiny function */
3277                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3278
3279                 {
3280                   absSym *abSym;
3281
3282                         abSym = Safe_calloc(1, sizeof(absSym));
3283                         abSym->name = Safe_strdup( asymname );
3284
3285                         switch( _G.interruptvector ) {
3286                                 case 0: abSym->address = 0x000000; break;
3287                                 case 1: abSym->address = 0x000008; break;
3288                                 case 2: abSym->address = 0x000018; break;
3289                         }
3290
3291                         addSet(&absSymSet, abSym);
3292                 }
3293         }
3294
3295
3296         /* create the function header */
3297         pic16_emitcode(";","-----------------------------------------");
3298         pic16_emitcode(";"," function %s",sym->name);
3299         pic16_emitcode(";","-----------------------------------------");
3300
3301         pic16_emitcode("","%s:",sym->rname);
3302         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3303
3304
3305         {
3306           absSym *ab;
3307
3308                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3309                         if(!strcmp(ab->name, sym->name)) {
3310                                 pic16_pBlockConvert2Absolute(pb);
3311                                 break;
3312                         }
3313
3314         }
3315
3316
3317         if(IFFUNC_ISNAKED(ftype)) {
3318                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3319                 return;
3320         }
3321         
3322         /* if critical function then turn interrupts off */
3323         if (IFFUNC_ISCRITICAL(ftype))
3324                 pic16_emitcode("clr","ea");
3325
3326         /* if this is an interrupt service routine then
3327          * save acc, b, dpl, dph  */
3328         if (IFFUNC_ISISR(sym->type)) {
3329           int i;
3330                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3331                 if(!(_G.interruptvector == 1)) {
3332
3333                         /* do not save WREG,STATUS,BSR for high priority interrupts
3334                          * because they are stored in the hardware shadow registers already */
3335                          
3336                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3337                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3338                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3339                 }
3340
3341                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3342                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3343                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3344                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3345
3346 //                pic16_pBlockConvert2ISR(pb);
3347                 
3348                 /* if any registers used */
3349                 if (sym->regsUsed) {
3350                         /* save the registers used */
3351                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3352                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3353                                 if (bitVectBitValue(sym->regsUsed,i)) {
3354 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3355 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3356 //                                                      pic16_regWithIdx(i)->name);
3357
3358                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3359                                         _G.nRegsSaved++;
3360                                 }
3361                         }
3362                 }
3363         } else {
3364                 /* emit code to setup stack frame if user enabled,
3365                  * and function is not main() */
3366          
3367 //              fprintf(stderr, "function name: %s\n", sym->name);
3368                 if(strcmp(sym->name, "main")) {
3369                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3370                         /* setup the stack frame */
3371                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3372                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3373                                 if(STACK_MODEL_LARGE)
3374                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3375                         }
3376                 }
3377
3378                 /* if callee-save to be used for this function
3379                 * then save the registers being used in this function */
3380 //              if (IFFUNC_CALLEESAVES(sym->type))
3381                 {
3382                   int i;
3383
3384 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3385
3386 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3387
3388                         /* if any registers used */
3389                         if (sym->regsUsed) {
3390                                 /* save the registers used */
3391                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3392                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3393                                         if (bitVectBitValue(sym->regsUsed,i)) {
3394
3395 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3396 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3397 //                                                              pic16_regWithIdx(i)->name);
3398
3399                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3400
3401 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3402 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3403 //                                                      &pic16_pc_postdec1, 0));
3404
3405                                                 _G.nRegsSaved++;
3406                                         }
3407                                 }
3408                         }
3409                 }
3410         }
3411
3412
3413         
3414 #if 0
3415         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3416
3417                 if (options.useXstack) {
3418                         pic16_emitcode("mov","r0,%s",spname);
3419                         pic16_emitcode("mov","a,_bp");
3420                         pic16_emitcode("movx","@r0,a");
3421                         pic16_emitcode("inc","%s",spname);
3422                 } else {
3423                         /* set up the stack */
3424                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3425                 }
3426                 pic16_emitcode ("mov","_bp,%s",spname);
3427         }
3428 #endif
3429         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3430
3431         /* adjust the stack for the function */
3432         if (sym->stack) {
3433           int i = sym->stack;
3434
3435                 if (i > 127 ) 
3436                         werror(W_STACK_OVERFLOW,sym->name);
3437
3438                 if (i > 3 && sym->recvSize < 4) {              
3439                         pic16_emitcode ("mov","a,sp");
3440                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3441                         pic16_emitcode ("mov","sp,a");
3442                 } else
3443                         while(i--)
3444                                 pic16_emitcode("inc","sp");
3445         }
3446
3447         if (sym->xstack) {
3448                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3449
3450                 pic16_emitcode ("mov","a,_spx");
3451                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3452                 pic16_emitcode ("mov","_spx,a");
3453         }
3454     
3455 }
3456
3457 /*-----------------------------------------------------------------*/
3458 /* genEndFunction - generates epilogue for functions               */
3459 /*-----------------------------------------------------------------*/
3460 static void genEndFunction (iCode *ic)
3461 {
3462     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3463
3464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3465
3466     if(IFFUNC_ISNAKED(sym->type)) {
3467         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3468         return;
3469     }
3470
3471 #if 0
3472     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3473     {
3474         pic16_emitcode ("mov","%s,_bp",spname);
3475     }
3476 #endif
3477
3478     /* if use external stack but some variables were
3479     added to the local stack then decrement the
3480     local stack */
3481     if (options.useXstack && sym->stack) {      
3482         pic16_emitcode("mov","a,sp");
3483         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3484         pic16_emitcode("mov","sp,a");
3485     }
3486
3487
3488 #if 0
3489     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3490         if (options.useXstack) {
3491             pic16_emitcode("mov","r0,%s",spname);
3492             pic16_emitcode("movx","a,@r0");
3493             pic16_emitcode("mov","_bp,a");
3494             pic16_emitcode("dec","%s",spname);
3495         }
3496         else
3497         {
3498             pic16_emitcode ("pop","_bp");
3499         }
3500     }
3501 #endif
3502
3503         if (IFFUNC_ISISR(sym->type)) {
3504                 /* now we need to restore the registers */
3505                 /* if any registers used */
3506                 if (sym->regsUsed) {
3507                   int i;
3508
3509                         /* restore 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                                 }
3525                         }
3526                 }
3527         
3528                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3529                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3530                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3531                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3532
3533                 if(!(_G.interruptvector == 1)) {
3534                         /* do not restore interrupt vector for WREG,STATUS,BSR
3535                          * for high priority interrupt, see genFunction */
3536                          
3537                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3538                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3539                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3540                 }
3541         
3542                 _G.interruptvector = 0;         /* sanity check */
3543
3544 //              pic16_pBlockConvert2ISR(pb);
3545
3546
3547                 /* if debug then send end of function */
3548 /*      if (options.debug && currFunc)  */
3549                 if (currFunc) {
3550                         debugFile->writeEndFunction (currFunc, ic, 1);
3551                 }
3552         
3553                 pic16_emitpcodeNULLop(POC_RETFIE);
3554         } else {
3555                 if (IFFUNC_ISCRITICAL(sym->type))
3556                         pic16_emitcode("setb","ea");
3557         
3558
3559 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3560
3561                 /* if any registers used */
3562                 if (sym->regsUsed) {
3563                   int i;
3564                         /* save the registers used */
3565                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3566                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3567                                 if (bitVectBitValue(sym->regsUsed,i)) {
3568         
3569 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3570 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3571 //                                                      pic16_regWithIdx(i)->name);
3572         
3573                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3574                                         
3575 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3576 //                                              &pic16_pc_preinc1,
3577 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3578
3579                                         _G.nRegsSaved--;
3580                                 }
3581                         }
3582                 }
3583         
3584                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3585                 /* if debug then send end of function */
3586                 if (currFunc) {
3587                         debugFile->writeEndFunction (currFunc, ic, 1);
3588                 }
3589
3590                 /* insert code to restore stack frame, if user enabled it
3591                  * and function is not main() */
3592          
3593
3594                 if(strcmp(sym->name, "main")) {
3595                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3596                                 /* restore stack frame */
3597                                 if(STACK_MODEL_LARGE)
3598                                         pic16_emitpcode(POC_MOVFF,
3599                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3600                                 pic16_emitpcode(POC_MOVFF,
3601                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3602                         }
3603                 }
3604
3605                 pic16_emitcode ("return","");
3606                 pic16_emitpcodeNULLop(POC_RETURN);
3607
3608                 /* Mark the end of a function */
3609                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3610         }
3611
3612 }
3613
3614
3615 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3616 {
3617
3618         if(is_LitOp(op)) {
3619                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3620
3621                 if(dest->type != PO_WREG)
3622                         pic16_emitpcode(POC_MOVWF, dest);
3623         } else {
3624                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3625                         pic16_popGet(AOP(op), offset), dest));
3626         }
3627 }
3628
3629 /*-----------------------------------------------------------------*/
3630 /* genRet - generate code for return statement                     */
3631 /*-----------------------------------------------------------------*/
3632 static void genRet (iCode *ic)
3633 {
3634   int size;
3635   operand *left;
3636
3637         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3638         /* if we have no return value then
3639          * just generate the "ret" */
3640         
3641         if (!IC_LEFT(ic)) 
3642                 goto jumpret;       
3643     
3644         /* we have something to return then
3645          * move the return value into place */
3646         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3647         size = AOP_SIZE(IC_LEFT(ic));
3648
3649         if(size <= 4) {
3650                 if(size>3) {
3651                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3652 //                      pic16_emitpcode(POC_MOVFF,
3653 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3654                 }
3655                 if(size>2) {
3656                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3657 //                      pic16_emitpcode(POC_MOVFF,
3658 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3659                 }
3660                 if(size>1) {
3661                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3662 //                      pic16_emitpcode(POC_MOVFF,
3663 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3664                 }
3665
3666 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3667
3668                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3669 //              pic16_emitpcode(POC_MOVFF,
3670 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3671
3672         } else {
3673                 /* >32-bits, setup stack and FSR0 */
3674                 while (size--) {
3675 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3676 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3677
3678                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3679
3680 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3681                         GpsuedoStkPtr++;
3682                 }
3683                         
3684                 /* setup FSR0 */
3685                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3686                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3687
3688                 if(STACK_MODEL_LARGE) {
3689                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3690                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3691                 } else {
3692                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3693                 }
3694         }
3695                                 
3696 #if 0
3697         /* old code, left here for reference -- VR */    
3698         while (size--) {
3699           char *l ;
3700
3701                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3702                         /* #NOCHANGE */
3703                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3704                         pic16_emitpcomment("push %s",l);
3705                         pushed++;
3706                 } else {
3707                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3708                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3709                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3710                         
3711                         if (strcmp(fReturn[offset],l)) {
3712                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3713                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3714                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3715                                 } else {
3716                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3717                                 }
3718                                 
3719                                 if(size) {
3720                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3721                                 }
3722                                 offset++;
3723                         }
3724                 }
3725         }    
3726
3727         if (pushed) {
3728                 while(pushed) {
3729                         pushed--;
3730                         if (strcmp(fReturn[pushed],"a"))
3731                                 pic16_emitcode("pop",fReturn[pushed]);
3732                         else
3733                                 pic16_emitcode("pop","acc");
3734                 }
3735         }
3736 #endif
3737
3738
3739         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3740     
3741 jumpret:
3742         /* generate a jump to the return label
3743          * if the next is not the return statement */
3744         if (!(ic->next && ic->next->op == LABEL
3745                 && IC_LABEL(ic->next) == returnLabel)) {
3746         
3747                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3748                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3749         }
3750 }
3751
3752 /*-----------------------------------------------------------------*/
3753 /* genLabel - generates a label                                    */
3754 /*-----------------------------------------------------------------*/
3755 static void genLabel (iCode *ic)
3756 {
3757
3758
3759     /* special case never generate */
3760     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3761     if (IC_LABEL(ic) == entryLabel)
3762         return ;
3763
3764     pic16_emitpLabel(IC_LABEL(ic)->key);
3765     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3766 }
3767
3768 /*-----------------------------------------------------------------*/
3769 /* genGoto - generates a goto                                      */
3770 /*-----------------------------------------------------------------*/
3771 //tsd
3772 static void genGoto (iCode *ic)
3773 {
3774   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3775   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3776 }
3777
3778
3779 /*-----------------------------------------------------------------*/
3780 /* genMultbits :- multiplication of bits                           */
3781 /*-----------------------------------------------------------------*/
3782 static void genMultbits (operand *left, 
3783                          operand *right, 
3784                          operand *result)
3785 {
3786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3787
3788   if(!pic16_sameRegs(AOP(result),AOP(right)))
3789     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3790
3791   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3792   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3793   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3794
3795 }
3796
3797
3798 /*-----------------------------------------------------------------*/
3799 /* genMultOneByte : 8 bit multiplication & division                */
3800 /*-----------------------------------------------------------------*/
3801 static void genMultOneByte (operand *left,
3802                             operand *right,
3803                             operand *result)
3804 {
3805
3806   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3807   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3808   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3809
3810   /* (if two literals, the value is computed before) */
3811   /* if one literal, literal on the right */
3812   if (AOP_TYPE(left) == AOP_LIT){
3813     operand *t = right;
3814     right = left;
3815     left = t;
3816   }
3817
3818         /* size is already checked in genMult == 1 */
3819 //      size = AOP_SIZE(result);
3820
3821         if (AOP_TYPE(right) == AOP_LIT){
3822                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3823                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3824                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3825                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3826         } else {
3827                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3828                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3829                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3830                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3831         }
3832         
3833         pic16_genMult8X8_8 (left, right,result);
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genMultOneWord : 16 bit multiplication                          */
3838 /*-----------------------------------------------------------------*/
3839 static void genMultOneWord (operand *left,
3840                             operand *right,
3841                             operand *result)
3842 {
3843
3844         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3845         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3846         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3847
3848         /* (if two literals, the value is computed before)
3849          * if one literal, literal on the right */
3850         if (AOP_TYPE(left) == AOP_LIT){
3851           operand *t = right;
3852                 right = left;
3853                 left = t;
3854         }
3855
3856         /* size is checked already == 2 */
3857 //      size = AOP_SIZE(result);
3858
3859         if (AOP_TYPE(right) == AOP_LIT) {
3860                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3861                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3862                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3863                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3864         } else {
3865                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3866                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3867                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3868                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3869         }
3870         
3871         pic16_genMult16X16_16(left, right,result);
3872 }
3873
3874 /*-----------------------------------------------------------------*/
3875 /* genMultOneLong : 32 bit multiplication                          */
3876 /*-----------------------------------------------------------------*/
3877 static void genMultOneLong (operand *left,
3878                             operand *right,
3879                             operand *result)
3880 {
3881
3882         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3883         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3884         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3885
3886         /* (if two literals, the value is computed before)
3887          * if one literal, literal on the right */
3888         if (AOP_TYPE(left) == AOP_LIT){
3889           operand *t = right;
3890                 right = left;
3891                 left = t;
3892         }
3893
3894         /* size is checked already == 4 */
3895 //      size = AOP_SIZE(result);
3896
3897         if (AOP_TYPE(right) == AOP_LIT) {
3898                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3899                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3900                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3901                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3902         } else {
3903                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3904                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3905                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3906                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3907         }
3908         
3909         pic16_genMult32X32_32(left, right,result);
3910 }
3911
3912
3913
3914 /*-----------------------------------------------------------------*/
3915 /* genMult - generates code for multiplication                     */
3916 /*-----------------------------------------------------------------*/
3917 static void genMult (iCode *ic)
3918 {
3919   operand *left = IC_LEFT(ic);
3920   operand *right = IC_RIGHT(ic);
3921   operand *result= IC_RESULT(ic);   
3922
3923         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3924         /* assign the amsops */
3925         pic16_aopOp (left,ic,FALSE);
3926         pic16_aopOp (right,ic,FALSE);
3927         pic16_aopOp (result,ic,TRUE);
3928
3929         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3930
3931         /* special cases first *
3932         * both are bits */
3933         if (AOP_TYPE(left) == AOP_CRY
3934                 && AOP_TYPE(right)== AOP_CRY) {
3935                 genMultbits(left,right,result);
3936           goto release ;
3937         }
3938
3939         /* if both are of size == 1 */
3940         if(AOP_SIZE(left) == 1
3941                 && AOP_SIZE(right) == 1) {
3942                 genMultOneByte(left,right,result);
3943           goto release ;
3944         }
3945
3946         /* if both are of size == 2 */
3947         if(AOP_SIZE(left) == 2
3948                 && AOP_SIZE(right) == 2) {
3949                 genMultOneWord(left, right, result);
3950           goto release;
3951         }
3952         
3953         /* if both are of size == 4 */
3954         if(AOP_SIZE(left) == 4
3955                 && AOP_SIZE(right) == 4) {
3956                 genMultOneLong(left, right, result);
3957           goto release;
3958         }
3959         
3960         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3961
3962
3963         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3964         /* should have been converted to function call */
3965         assert(0) ;
3966
3967 release :
3968         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3969         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3970         pic16_freeAsmop(result,NULL,ic,TRUE); 
3971 }
3972
3973 /*-----------------------------------------------------------------*/
3974 /* genDivbits :- division of bits                                  */
3975 /*-----------------------------------------------------------------*/
3976 static void genDivbits (operand *left, 
3977                         operand *right, 
3978                         operand *result)
3979 {
3980
3981     char *l;
3982
3983     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3984     /* the result must be bit */    
3985     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3986     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3987
3988     MOVA(l);    
3989
3990     pic16_emitcode("div","ab");
3991     pic16_emitcode("rrc","a");
3992     pic16_aopPut(AOP(result),"c",0);
3993 }
3994
3995 /*-----------------------------------------------------------------*/
3996 /* genDivOneByte : 8 bit division                                  */
3997 /*-----------------------------------------------------------------*/
3998 static void genDivOneByte (operand *left,
3999                            operand *right,
4000                            operand *result)
4001 {
4002     sym_link *opetype = operandType(result);
4003     char *l ;
4004     symbol *lbl ;
4005     int size,offset;
4006
4007         /* result = divident / divisor
4008          * - divident may be a register or a literal,
4009          * - divisor may be a register or a literal,
4010          * so there are 3 cases (literal / literal is optimized
4011          * by the front-end) to handle.
4012          * In addition we must handle signed and unsigned, which
4013          * result in 6 final different cases -- VR */
4014
4015     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4016     size = AOP_SIZE(result) - 1;
4017     offset = 1;
4018     /* signed or unsigned */
4019     if (SPEC_USIGN(opetype)) {
4020       pCodeOp *pct1,    /* count */
4021                 *pct2,  /* reste */
4022                 *pct3;  /* temp */
4023       symbol *label1, *label2, *label3;;
4024
4025
4026         /* unsigned is easy */
4027
4028         pct1 = pic16_popGetTempReg();
4029         pct2 = pic16_popGetTempReg();
4030         pct3 = pic16_popGetTempReg();
4031         
4032         label1 = newiTempLabel(NULL);
4033         label2 = newiTempLabel(NULL);
4034         label3 = newiTempLabel(NULL);
4035
4036         /* the following algorithm is extracted from divuint.c */
4037
4038         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4039         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4040         
4041         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4042
4043         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4044         
4045         pic16_emitpLabel(label1->key);
4046         
4047         emitCLRC;
4048         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4049
4050
4051         emitCLRC;
4052         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4053         
4054
4055         emitSKPNC;
4056         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4057         
4058         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4059         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4060         
4061         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4062         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4063         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4064         
4065         pic16_emitpLabel( label3->key );
4066         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4067         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4068         
4069         
4070
4071         pic16_emitpLabel(label2->key);
4072         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4073         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4074         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4075         
4076         /* result is in wreg */
4077         if(AOP_TYPE(result) != AOP_ACC)
4078                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4079
4080         pic16_popReleaseTempReg( pct3 );
4081         pic16_popReleaseTempReg( pct2 );
4082         pic16_popReleaseTempReg( pct1 );
4083
4084         return ;
4085     }
4086
4087     /* signed is a little bit more difficult */
4088
4089     /* save the signs of the operands */
4090     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4091     MOVA(l);    
4092     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4093     pic16_emitcode("push","acc"); /* save it on the stack */
4094
4095     /* now sign adjust for both left & right */
4096     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4097     MOVA(l);       
4098     lbl = newiTempLabel(NULL);
4099     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4100     pic16_emitcode("cpl","a");   
4101     pic16_emitcode("inc","a");
4102     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4103     pic16_emitcode("mov","b,a");
4104
4105     /* sign adjust left side */
4106     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4107     MOVA(l);
4108
4109     lbl = newiTempLabel(NULL);
4110     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4111     pic16_emitcode("cpl","a");
4112     pic16_emitcode("inc","a");
4113     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4114
4115     /* now the division */
4116     pic16_emitcode("div","ab");
4117     /* we are interested in the lower order
4118     only */
4119     pic16_emitcode("mov","b,a");
4120     lbl = newiTempLabel(NULL);
4121     pic16_emitcode("pop","acc");   
4122     /* if there was an over flow we don't 
4123     adjust the sign of the result */
4124     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4125     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4126     CLRC;
4127     pic16_emitcode("clr","a");
4128     pic16_emitcode("subb","a,b");
4129     pic16_emitcode("mov","b,a");
4130     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4131
4132     /* now we are done */
4133     pic16_aopPut(AOP(result),"b",0);
4134     if(size > 0){
4135         pic16_emitcode("mov","c,b.7");
4136         pic16_emitcode("subb","a,acc");   
4137     }
4138     while (size--)
4139         pic16_aopPut(AOP(result),"a",offset++);
4140
4141 }
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genDiv - generates code for division                            */
4145 /*-----------------------------------------------------------------*/
4146 static void genDiv (iCode *ic)
4147 {
4148     operand *left = IC_LEFT(ic);
4149     operand *right = IC_RIGHT(ic);
4150     operand *result= IC_RESULT(ic);   
4151
4152
4153         /* Division is a very lengthy algorithm, so it is better
4154          * to call support routines than inlining algorithm.
4155          * Division functions written here just in case someone
4156          * wants to inline and not use the support libraries -- VR */
4157
4158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4159     /* assign the amsops */
4160     pic16_aopOp (left,ic,FALSE);
4161     pic16_aopOp (right,ic,FALSE);
4162     pic16_aopOp (result,ic,TRUE);
4163
4164     /* special cases first */
4165     /* both are bits */
4166     if (AOP_TYPE(left) == AOP_CRY &&
4167         AOP_TYPE(right)== AOP_CRY) {
4168         genDivbits(left,right,result);
4169         goto release ;
4170     }
4171
4172     /* if both are of size == 1 */
4173     if (AOP_SIZE(left) == 1 &&
4174         AOP_SIZE(right) == 1 ) {
4175         genDivOneByte(left,right,result);
4176         goto release ;
4177     }
4178
4179     /* should have been converted to function call */
4180     assert(0);
4181 release :
4182     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4183     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184     pic16_freeAsmop(result,NULL,ic,TRUE); 
4185 }
4186
4187 /*-----------------------------------------------------------------*/
4188 /* genModbits :- modulus of bits                                   */
4189 /*-----------------------------------------------------------------*/
4190 static void genModbits (operand *left, 
4191                         operand *right, 
4192                         operand *result)
4193 {
4194
4195     char *l;
4196
4197     /* the result must be bit */    
4198     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4199     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4200
4201     MOVA(l);       
4202
4203     pic16_emitcode("div","ab");
4204     pic16_emitcode("mov","a,b");
4205     pic16_emitcode("rrc","a");
4206     pic16_aopPut(AOP(result),"c",0);
4207 }
4208
4209 /*-----------------------------------------------------------------*/
4210 /* genModOneByte : 8 bit modulus                                   */
4211 /*-----------------------------------------------------------------*/
4212 static void genModOneByte (operand *left,
4213                            operand *right,
4214                            operand *result)
4215 {
4216     sym_link *opetype = operandType(result);
4217     char *l ;
4218     symbol *lbl ;
4219
4220     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4221     /* signed or unsigned */
4222     if (SPEC_USIGN(opetype)) {
4223         /* unsigned is easy */
4224         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4225         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4226         MOVA(l);    
4227         pic16_emitcode("div","ab");
4228         pic16_aopPut(AOP(result),"b",0);
4229         return ;
4230     }
4231
4232     /* signed is a little bit more difficult */
4233
4234     /* save the signs of the operands */
4235     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4236     MOVA(l);
4237
4238     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4239     pic16_emitcode("push","acc"); /* save it on the stack */
4240
4241     /* now sign adjust for both left & right */
4242     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4243     MOVA(l);
4244
4245     lbl = newiTempLabel(NULL);
4246     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4247     pic16_emitcode("cpl","a");   
4248     pic16_emitcode("inc","a");
4249     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4250     pic16_emitcode("mov","b,a"); 
4251
4252     /* sign adjust left side */
4253     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4254     MOVA(l);
4255
4256     lbl = newiTempLabel(NULL);
4257     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4258     pic16_emitcode("cpl","a");   
4259     pic16_emitcode("inc","a");
4260     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4261
4262     /* now the multiplication */
4263     pic16_emitcode("div","ab");
4264     /* we are interested in the lower order
4265     only */
4266     lbl = newiTempLabel(NULL);
4267     pic16_emitcode("pop","acc");   
4268     /* if there was an over flow we don't 
4269     adjust the sign of the result */
4270     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4271     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4272     CLRC ;
4273     pic16_emitcode("clr","a");
4274     pic16_emitcode("subb","a,b");
4275     pic16_emitcode("mov","b,a");
4276     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4277
4278     /* now we are done */
4279     pic16_aopPut(AOP(result),"b",0);
4280
4281 }
4282
4283 /*-----------------------------------------------------------------*/
4284 /* genMod - generates code for division                            */
4285 /*-----------------------------------------------------------------*/
4286 static void genMod (iCode *ic)
4287 {
4288     operand *left = IC_LEFT(ic);
4289     operand *right = IC_RIGHT(ic);
4290     operand *result= IC_RESULT(ic);  
4291
4292     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4293     /* assign the amsops */
4294     pic16_aopOp (left,ic,FALSE);
4295     pic16_aopOp (right,ic,FALSE);
4296     pic16_aopOp (result,ic,TRUE);
4297
4298     /* special cases first */
4299     /* both are bits */
4300     if (AOP_TYPE(left) == AOP_CRY &&
4301         AOP_TYPE(right)== AOP_CRY) {
4302         genModbits(left,right,result);
4303         goto release ;
4304     }
4305
4306     /* if both are of size == 1 */
4307     if (AOP_SIZE(left) == 1 &&
4308         AOP_SIZE(right) == 1 ) {
4309         genModOneByte(left,right,result);
4310         goto release ;
4311     }
4312
4313     /* should have been converted to function call */
4314     assert(0);
4315
4316 release :
4317     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4318     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319     pic16_freeAsmop(result,NULL,ic,TRUE); 
4320 }
4321
4322 /*-----------------------------------------------------------------*/
4323 /* genIfxJump :- will create a jump depending on the ifx           */
4324 /*-----------------------------------------------------------------*/
4325 /*
4326   note: May need to add parameter to indicate when a variable is in bit space.
4327 */
4328 static void genIfxJump (iCode *ic, char *jval)
4329 {
4330
4331     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4332     /* if true label then we jump if condition
4333     supplied is true */
4334     if ( IC_TRUE(ic) ) {
4335
4336         if(strcmp(jval,"a") == 0)
4337           emitSKPZ;
4338         else if (strcmp(jval,"c") == 0)
4339           emitSKPC;
4340         else {
4341           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4342           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4343         }
4344
4345         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4346         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4347
4348     }
4349     else {
4350         /* false label is present */
4351         if(strcmp(jval,"a") == 0)
4352           emitSKPNZ;
4353         else if (strcmp(jval,"c") == 0)
4354           emitSKPNC;
4355         else {
4356           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4357           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4358         }
4359
4360         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4361         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4362
4363     }
4364
4365
4366     /* mark the icode as generated */
4367     ic->generated = 1;
4368 }
4369
4370 #if 0
4371 // not needed ATM
4372
4373 /*-----------------------------------------------------------------*/
4374 /* genSkip                                                         */
4375 /*-----------------------------------------------------------------*/
4376 static void genSkip(iCode *ifx,int status_bit)
4377 {
4378   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4379   if(!ifx)
4380     return;
4381
4382   if ( IC_TRUE(ifx) ) {
4383     switch(status_bit) {
4384     case 'z':
4385       emitSKPNZ;
4386       break;
4387
4388     case 'c':
4389       emitSKPNC;
4390       break;
4391
4392     case 'd':
4393       emitSKPDC;
4394       break;
4395
4396     }
4397
4398     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4399     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4400
4401   } else {
4402
4403     switch(status_bit) {
4404
4405     case 'z':
4406       emitSKPZ;
4407       break;
4408
4409     case 'c':
4410       emitSKPC;
4411       break;
4412
4413     case 'd':
4414       emitSKPDC;
4415       break;
4416     }
4417     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4418     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4419
4420   }
4421
4422 }
4423 #endif
4424
4425 /*-----------------------------------------------------------------*/
4426 /* genSkipc                                                        */
4427 /*-----------------------------------------------------------------*/
4428 static void genSkipc(resolvedIfx *rifx)
4429 {
4430   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4431   
4432   if(!rifx)
4433     return;
4434
4435   if(rifx->condition)
4436     emitSKPC;
4437   else
4438     emitSKPNC;
4439
4440   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4441   rifx->generated = 1;
4442 }
4443
4444 /*-----------------------------------------------------------------*/
4445 /* genSkipz2                                                       */
4446 /*-----------------------------------------------------------------*/
4447 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4448 {
4449   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4450   
4451   if(!rifx)
4452     return;
4453
4454   if( (rifx->condition ^ invert_condition) & 1)
4455     emitSKPZ;
4456   else
4457     emitSKPNZ;
4458
4459   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4460   rifx->generated = 1;
4461 }
4462
4463 #if 0
4464 /*-----------------------------------------------------------------*/
4465 /* genSkipz                                                        */
4466 /*-----------------------------------------------------------------*/
4467 static void genSkipz(iCode *ifx, int condition)
4468 {
4469   if(!ifx)
4470     return;
4471
4472   if(condition)
4473     emitSKPNZ;
4474   else
4475     emitSKPZ;
4476
4477   if ( IC_TRUE(ifx) )
4478     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4479   else
4480     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4481
4482   if ( IC_TRUE(ifx) )
4483     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4484   else
4485     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4486
4487 }
4488 #endif
4489
4490 /*-----------------------------------------------------------------*/
4491 /* genSkipCond                                                     */
4492 /*-----------------------------------------------------------------*/
4493 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4494 {
4495   if(!rifx)
4496     return;
4497
4498   if(rifx->condition)
4499     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4500   else
4501     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4502
4503
4504   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4505   rifx->generated = 1;
4506 }
4507
4508 #if 0
4509 /*-----------------------------------------------------------------*/
4510 /* genChkZeroes :- greater or less than comparison                 */
4511 /*     For each byte in a literal that is zero, inclusive or the   */
4512 /*     the corresponding byte in the operand with W                */
4513 /*     returns true if any of the bytes are zero                   */
4514 /*-----------------------------------------------------------------*/
4515 static int genChkZeroes(operand *op, int lit,  int size)
4516 {
4517
4518   int i;
4519   int flag =1;
4520
4521   while(size--) {
4522     i = (lit >> (size*8)) & 0xff;
4523
4524     if(i==0) {
4525       if(flag) 
4526         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4527       else
4528         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4529       flag = 0;
4530     }
4531   }
4532
4533   return (flag==0);
4534 }
4535 #endif
4536
4537 /*-----------------------------------------------------------------*/
4538 /* genCmp :- greater or less than comparison                       */
4539 /*-----------------------------------------------------------------*/
4540 static void genCmp (operand *left,operand *right,
4541                     operand *result, iCode *ifx, int sign)
4542 {
4543   int size; //, offset = 0 ;
4544   unsigned long lit = 0L,i = 0;
4545   resolvedIfx rFalseIfx;
4546   //  resolvedIfx rTrueIfx;
4547   symbol *truelbl;
4548   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4549 /*
4550   if(ifx) {
4551     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4552     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4553   }
4554 */
4555
4556   resolveIfx(&rFalseIfx,ifx);
4557   truelbl  = newiTempLabel(NULL);
4558   size = max(AOP_SIZE(left),AOP_SIZE(right));
4559
4560   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4561
4562 #define _swapp
4563
4564   /* if literal is on the right then swap with left */
4565   if ((AOP_TYPE(right) == AOP_LIT)) {
4566     operand *tmp = right ;
4567     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4568     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4569 #ifdef _swapp
4570
4571     lit = (lit - 1) & mask;
4572     right = left;
4573     left = tmp;
4574     rFalseIfx.condition ^= 1;
4575 #endif
4576
4577   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4578     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4579   }
4580
4581
4582   //if(IC_TRUE(ifx) == NULL)
4583   /* if left & right are bit variables */
4584   if (AOP_TYPE(left) == AOP_CRY &&
4585       AOP_TYPE(right) == AOP_CRY ) {
4586     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4587     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4588   } else {
4589     /* subtract right from left if at the
4590        end the carry flag is set then we know that
4591        left is greater than right */
4592
4593     symbol *lbl  = newiTempLabel(NULL);
4594
4595 #if 0
4596         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4597                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4598 #endif
4599
4600 #ifndef _swapp
4601     if(AOP_TYPE(right) == AOP_LIT) {
4602
4603       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4604
4605       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4606
4607       /* special cases */
4608
4609       if(lit == 0) {
4610
4611         if(sign != 0) 
4612           genSkipCond(&rFalseIfx,left,size-1,7);
4613         else 
4614           /* no need to compare to 0...*/
4615           /* NOTE: this is a de-generate compare that most certainly 
4616            *       creates some dead code. */
4617           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4618
4619         if(ifx) ifx->generated = 1;
4620         return;
4621
4622       }
4623       size--;
4624
4625       if(size == 0) {
4626         //i = (lit >> (size*8)) & 0xff;
4627         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4628         
4629         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4630
4631         i = ((0-lit) & 0xff);
4632         if(sign) {
4633           if( i == 0x81) { 
4634             /* lit is 0x7f, all signed chars are less than
4635              * this except for 0x7f itself */
4636             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4637             genSkipz2(&rFalseIfx,0);
4638           } else {
4639             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4640             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4641             genSkipc(&rFalseIfx);
4642           }
4643
4644         } else {
4645           if(lit == 1) {
4646             genSkipz2(&rFalseIfx,1);
4647           } else {
4648             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4649             genSkipc(&rFalseIfx);
4650           }
4651         }
4652
4653         if(ifx) ifx->generated = 1;
4654         return;
4655       }
4656
4657       /* chars are out of the way. now do ints and longs */
4658
4659
4660       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4661         
4662       /* special cases */
4663
4664       if(sign) {
4665
4666         if(lit == 0) {
4667           genSkipCond(&rFalseIfx,left,size,7);
4668           if(ifx) ifx->generated = 1;
4669           return;
4670         }
4671
4672         if(lit <0x100) {
4673           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4674
4675           //rFalseIfx.condition ^= 1;
4676           //genSkipCond(&rFalseIfx,left,size,7);
4677           //rFalseIfx.condition ^= 1;
4678
4679           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4680           if(rFalseIfx.condition)
4681             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4682           else
4683             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4684
4685           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4686           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4687           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4688
4689           while(size > 1)
4690             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4691
4692           if(rFalseIfx.condition) {
4693             emitSKPZ;
4694             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4695
4696           } else {
4697             emitSKPNZ;
4698           }
4699
4700           genSkipc(&rFalseIfx);
4701           pic16_emitpLabel(truelbl->key);
4702           if(ifx) ifx->generated = 1;
4703           return;
4704
4705         }
4706
4707         if(size == 1) {
4708
4709           if( (lit & 0xff) == 0) {
4710             /* lower byte is zero */
4711             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4712             i = ((lit >> 8) & 0xff) ^0x80;
4713             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4714             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4715             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4716             genSkipc(&rFalseIfx);
4717
4718
4719             if(ifx) ifx->generated = 1;
4720             return;
4721
4722           }
4723         } else {
4724           /* Special cases for signed longs */
4725           if( (lit & 0xffffff) == 0) {
4726             /* lower byte is zero */
4727             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4728             i = ((lit >> 8*3) & 0xff) ^0x80;
4729             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4730             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4731             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4732             genSkipc(&rFalseIfx);
4733
4734
4735             if(ifx) ifx->generated = 1;
4736             return;
4737
4738           }
4739
4740         }
4741
4742
4743         if(lit & (0x80 << (size*8))) {
4744           /* lit is negative */
4745           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4746
4747           //genSkipCond(&rFalseIfx,left,size,7);
4748
4749           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4750
4751           if(rFalseIfx.condition)
4752             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4753           else
4754             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4755
4756
4757         } else {
4758           /* lit is positive */
4759           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4760           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4761           if(rFalseIfx.condition)
4762             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4763           else
4764             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4765
4766         }
4767
4768         /*
4769           This works, but is only good for ints.
4770           It also requires a "known zero" register.
4771           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4772           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4773           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4774           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4775           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4776           genSkipc(&rFalseIfx);
4777
4778           pic16_emitpLabel(truelbl->key);
4779           if(ifx) ifx->generated = 1;
4780           return;
4781         **/
4782           
4783         /* There are no more special cases, so perform a general compare */
4784   
4785         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4786         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4787
4788         while(size--) {
4789
4790           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4791           emitSKPNZ;
4792           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4793         }
4794         //rFalseIfx.condition ^= 1;
4795         genSkipc(&rFalseIfx);
4796
4797         pic16_emitpLabel(truelbl->key);
4798
4799         if(ifx) ifx->generated = 1;
4800         return;
4801
4802
4803       }
4804
4805
4806       /* sign is out of the way. So now do an unsigned compare */
4807       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4808
4809
4810       /* General case - compare to an unsigned literal on the right.*/
4811
4812       i = (lit >> (size*8)) & 0xff;
4813       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4814       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4815       while(size--) {
4816         i = (lit >> (size*8)) & 0xff;
4817
4818         if(i) {
4819           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4820           emitSKPNZ;
4821           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4822         } else {
4823           /* this byte of the lit is zero, 
4824            *if it's not the last then OR in the variable */
4825           if(size)
4826             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4827         }
4828       }
4829
4830
4831       pic16_emitpLabel(lbl->key);
4832 //      pic16_emitpLabel(truelbl->key);
4833       //if(emitFinalCheck)
4834       genSkipc(&rFalseIfx);
4835       if(sign)
4836         pic16_emitpLabel(truelbl->key);
4837
4838       if(ifx) ifx->generated = 1;
4839       return;
4840
4841
4842     }
4843 #endif  // _swapp
4844
4845     if(AOP_TYPE(left) == AOP_LIT) {
4846       //symbol *lbl = newiTempLabel(NULL);
4847
4848       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4849
4850
4851       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4852
4853       /* Special cases */
4854       if((lit == 0) && (sign == 0)){
4855
4856         size--;
4857         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4858         while(size) 
4859           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4860
4861         genSkipz2(&rFalseIfx,0);
4862         if(ifx) ifx->generated = 1;
4863         return;
4864       }
4865
4866       if(size==1) {
4867         /* Special cases */
4868         lit &= 0xff;
4869         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4870           /* degenerate compare can never be true */
4871           if(rFalseIfx.condition == 0)
4872             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4873
4874           if(ifx) ifx->generated = 1;
4875           return;
4876         }
4877
4878         if(sign) {
4879           /* signed comparisons to a literal byte */
4880
4881           int lp1 = (lit+1) & 0xff;
4882
4883           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4884           switch (lp1) {
4885           case 0:
4886             rFalseIfx.condition ^= 1;
4887             genSkipCond(&rFalseIfx,right,0,7);
4888             break;
4889           case 0x7f:
4890             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4891             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4892             genSkipz2(&rFalseIfx,1);
4893             break;
4894           default:
4895             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4896             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4897             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4898             rFalseIfx.condition ^= 1;
4899             genSkipc(&rFalseIfx);
4900             break;
4901           }
4902         } else {
4903           /* unsigned comparisons to a literal byte */
4904
4905           switch(lit & 0xff ) {
4906           case 0:
4907             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4908             genSkipz2(&rFalseIfx,0);
4909             break;
4910           case 0x7f:
4911             rFalseIfx.condition ^= 1;
4912             genSkipCond(&rFalseIfx,right,0,7);
4913             break;
4914
4915           default:
4916             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4917             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4918             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4919             rFalseIfx.condition ^= 1;
4920             if (AOP_TYPE(result) == AOP_CRY)
4921               genSkipc(&rFalseIfx);
4922             else {
4923               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4924               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4925             }         
4926             break;
4927           }
4928         }
4929
4930         if(ifx) ifx->generated = 1;
4931         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4932                 goto check_carry;
4933         return;
4934
4935       } else {
4936
4937         /* Size is greater than 1 */
4938
4939         if(sign) {
4940           int lp1 = lit+1;
4941
4942           size--;
4943
4944           if(lp1 == 0) {
4945             /* this means lit = 0xffffffff, or -1 */
4946
4947
4948             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4949             rFalseIfx.condition ^= 1;
4950             genSkipCond(&rFalseIfx,right,size,7);
4951             if(ifx) ifx->generated = 1;
4952             return;
4953           }
4954
4955           if(lit == 0) {
4956             int s = size;
4957
4958             if(rFalseIfx.condition) {
4959               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4960               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4961             }
4962
4963             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4964             while(size--)
4965               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4966
4967
4968             emitSKPZ;
4969             if(rFalseIfx.condition) {
4970               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4971               pic16_emitpLabel(truelbl->key);
4972             }else {
4973               rFalseIfx.condition ^= 1;
4974               genSkipCond(&rFalseIfx,right,s,7);
4975             }
4976
4977             if(ifx) ifx->generated = 1;
4978             return;
4979           }
4980
4981           if((size == 1) &&  (0 == (lp1&0xff))) {
4982             /* lower byte of signed word is zero */
4983             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4984             i = ((lp1 >> 8) & 0xff) ^0x80;
4985             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4986             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4987             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4988             rFalseIfx.condition ^= 1;
4989             genSkipc(&rFalseIfx);
4990
4991
4992             if(ifx) ifx->generated = 1;
4993             return;
4994           }
4995
4996           if(lit & (0x80 << (size*8))) {
4997             /* Lit is less than zero */
4998             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4999             //rFalseIfx.condition ^= 1;
5000             //genSkipCond(&rFalseIfx,left,size,7);
5001             //rFalseIfx.condition ^= 1;
5002             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5003             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5004
5005             if(rFalseIfx.condition)
5006               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5007             else
5008               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5009
5010
5011           } else {
5012             /* Lit is greater than or equal to zero */
5013             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5014             //rFalseIfx.condition ^= 1;
5015             //genSkipCond(&rFalseIfx,right,size,7);
5016             //rFalseIfx.condition ^= 1;
5017
5018             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5019             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5020
5021             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5022             if(rFalseIfx.condition)
5023               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5024             else
5025               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5026
5027           }
5028
5029
5030           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5031           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5032
5033           while(size--) {
5034
5035             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5036             emitSKPNZ;
5037             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5038           }
5039           rFalseIfx.condition ^= 1;
5040           //rFalseIfx.condition = 1;
5041           genSkipc(&rFalseIfx);
5042
5043           pic16_emitpLabel(truelbl->key);
5044
5045           if(ifx) ifx->generated = 1;
5046           return;
5047           // end of if (sign)
5048         } else {
5049
5050           /* compare word or long to an unsigned literal on the right.*/
5051
5052
5053           size--;
5054           if(lit < 0xff) {
5055             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5056             switch (lit) {
5057             case 0:
5058               break; /* handled above */
5059 /*
5060             case 0xff:
5061               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5062               while(size--)
5063                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5064               genSkipz2(&rFalseIfx,0);
5065               break;
5066 */
5067             default:
5068               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5069               while(--size)
5070                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5071
5072               emitSKPZ;
5073               if(rFalseIfx.condition)
5074                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5075               else
5076                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5077
5078
5079               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5080               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5081
5082               rFalseIfx.condition ^= 1;
5083               genSkipc(&rFalseIfx);
5084             }
5085
5086             pic16_emitpLabel(truelbl->key);
5087
5088             if(ifx) ifx->generated = 1;
5089             return;
5090           }
5091
5092
5093           lit++;
5094           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5095           i = (lit >> (size*8)) & 0xff;
5096
5097           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5098           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5099
5100           while(size--) {
5101             i = (lit >> (size*8)) & 0xff;
5102
5103             if(i) {
5104               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5105               emitSKPNZ;
5106               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5107             } else {
5108               /* this byte of the lit is zero, 
5109                * if it's not the last then OR in the variable */
5110               if(size)
5111                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5112             }
5113           }
5114
5115
5116           pic16_emitpLabel(lbl->key);
5117
5118           rFalseIfx.condition ^= 1;
5119
5120           genSkipc(&rFalseIfx);
5121         }
5122
5123         if(sign)
5124           pic16_emitpLabel(truelbl->key);
5125         if(ifx) ifx->generated = 1;
5126         return;
5127       }
5128     }
5129     /* Compare two variables */
5130
5131     DEBUGpic16_emitcode(";sign","%d",sign);
5132
5133     size--;
5134     if(sign) {
5135       /* Sigh. thus sucks... */
5136       if(size) {
5137         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5138         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5139         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5140         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5141         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5142         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5143       } else {
5144         /* Signed char comparison */
5145         /* Special thanks to Nikolai Golovchenko for this snippet */
5146         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5147         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5148         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5149         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5150         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5151         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5152
5153         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5154         genSkipc(&rFalseIfx);
5155           
5156         if(ifx) ifx->generated = 1;
5157         return;
5158       }
5159
5160     } else {
5161
5162       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5163       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5164     }
5165
5166
5167     /* The rest of the bytes of a multi-byte compare */
5168     while (size) {
5169
5170       emitSKPZ;
5171       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5172       size--;
5173
5174       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5175       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5176
5177
5178     }
5179
5180     pic16_emitpLabel(lbl->key);
5181
5182     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5183     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5184         (AOP_TYPE(result) == AOP_REG)) {
5185       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5186       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5187     } else {
5188       genSkipc(&rFalseIfx);
5189     }         
5190     //genSkipc(&rFalseIfx);
5191     if(ifx) ifx->generated = 1;
5192
5193     return;
5194
5195   }
5196
5197 check_carry:
5198   if ((AOP_TYPE(result) != AOP_CRY) 
5199         && AOP_SIZE(result)) {
5200     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5201 //    pic16_emitpLabel( rFalseIfx.lbl->key );
5202
5203     pic16_outBitC(result);
5204   } else {
5205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206     /* if the result is used in the next
5207        ifx conditional branch then generate
5208        code a little differently */
5209     if (ifx )
5210       genIfxJump (ifx,"c");
5211     else
5212       pic16_outBitC(result);
5213     /* leave the result in acc */
5214   }
5215
5216 }
5217
5218 /*-----------------------------------------------------------------*/
5219 /* genCmpGt :- greater than comparison                             */
5220 /*-----------------------------------------------------------------*/
5221 static void genCmpGt (iCode *ic, iCode *ifx)
5222 {
5223     operand *left, *right, *result;
5224     sym_link *letype , *retype;
5225     int sign ;
5226
5227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5228     left = IC_LEFT(ic);
5229     right= IC_RIGHT(ic);
5230     result = IC_RESULT(ic);
5231
5232     letype = getSpec(operandType(left));
5233     retype =getSpec(operandType(right));
5234     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5235     /* assign the amsops */
5236     pic16_aopOp (left,ic,FALSE);
5237     pic16_aopOp (right,ic,FALSE);
5238     pic16_aopOp (result,ic,TRUE);
5239
5240     genCmp(right, left, result, ifx, sign);
5241
5242     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5243     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5244     pic16_freeAsmop(result,NULL,ic,TRUE); 
5245 }
5246
5247 /*-----------------------------------------------------------------*/
5248 /* genCmpLt - less than comparisons                                */
5249 /*-----------------------------------------------------------------*/
5250 static void genCmpLt (iCode *ic, iCode *ifx)
5251 {
5252     operand *left, *right, *result;
5253     sym_link *letype , *retype;
5254     int sign ;
5255
5256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5257     left = IC_LEFT(ic);
5258     right= IC_RIGHT(ic);
5259     result = IC_RESULT(ic);
5260
5261     letype = getSpec(operandType(left));
5262     retype =getSpec(operandType(right));
5263     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5264
5265     /* assign the amsops */
5266     pic16_aopOp (left,ic,FALSE);
5267     pic16_aopOp (right,ic,FALSE);
5268     pic16_aopOp (result,ic,TRUE);
5269
5270     genCmp(left, right, result, ifx, sign);
5271
5272     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5273     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5274     pic16_freeAsmop(result,NULL,ic,TRUE); 
5275 }
5276
5277 #if 0
5278 // not needed ATM
5279 // FIXME reenable literal optimisation when the pic16 port is stable
5280
5281 /*-----------------------------------------------------------------*/
5282 /* genc16bit2lit - compare a 16 bit value to a literal             */
5283 /*-----------------------------------------------------------------*/
5284 static void genc16bit2lit(operand *op, int lit, int offset)
5285 {
5286   int i;
5287
5288   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5289   if( (lit&0xff) == 0) 
5290     i=1;
5291   else
5292     i=0;
5293
5294   switch( BYTEofLONG(lit,i)) { 
5295   case 0:
5296     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5297     break;
5298   case 1:
5299     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5300     break;
5301   case 0xff:
5302     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5303     break;
5304   default:
5305     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5306     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5307   }
5308
5309   i ^= 1;
5310
5311   switch( BYTEofLONG(lit,i)) { 
5312   case 0:
5313     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5314     break;
5315   case 1:
5316     emitSKPNZ;
5317     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5318     break;
5319   case 0xff:
5320     emitSKPNZ;
5321     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5322     break;
5323   default:
5324     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5325     emitSKPNZ;
5326     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5327
5328   }
5329
5330 }
5331 #endif
5332
5333 #if 0
5334 // not needed ATM
5335 /*-----------------------------------------------------------------*/
5336 /* gencjneshort - compare and jump if not equal                    */
5337 /*-----------------------------------------------------------------*/
5338 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5339 {
5340   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5341   int offset = 0;
5342   int res_offset = 0;  /* the result may be a different size then left or right */
5343   int res_size = AOP_SIZE(result);
5344   resolvedIfx rIfx;
5345   symbol *lbl, *lbl_done;
5346
5347   unsigned long lit = 0L;
5348   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5349
5350   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5351   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5352   if(result)
5353     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5354   resolveIfx(&rIfx,ifx);
5355   lbl =  newiTempLabel(NULL);
5356   lbl_done =  newiTempLabel(NULL);
5357
5358
5359   /* if the left side is a literal or 
5360      if the right is in a pointer register and left 
5361      is not */
5362   if ((AOP_TYPE(left) == AOP_LIT) || 
5363       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5364     operand *t = right;
5365     right = left;
5366     left = t;
5367   }
5368   if(AOP_TYPE(right) == AOP_LIT)
5369     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5370
5371   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5372     preserve_result = 1;
5373
5374   if(result && !preserve_result)
5375     {
5376       int i;
5377       for(i = 0; i < AOP_SIZE(result); i++)
5378         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5379     }
5380
5381
5382   /* if the right side is a literal then anything goes */
5383   if (AOP_TYPE(right) == AOP_LIT &&
5384       AOP_TYPE(left) != AOP_DIR ) {
5385     switch(size) {
5386     case 2:
5387       genc16bit2lit(left, lit, 0);
5388       emitSKPZ;
5389       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5390       break;
5391     default:
5392       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5393       while (size--) {
5394         if(lit & 0xff) {
5395           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5396           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5397         } else {
5398           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5399         }
5400
5401         emitSKPZ;
5402         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5403         offset++;
5404         if(res_offset < res_size-1)
5405           res_offset++;
5406         lit >>= 8;
5407       }
5408       break;
5409     }
5410   }
5411
5412   /* if the right side is in a register or in direct space or
5413      if the left is a pointer register & right is not */    
5414   else if (AOP_TYPE(right) == AOP_REG ||
5415            AOP_TYPE(right) == AOP_DIR || 
5416            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5417            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5418     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5419     int lbl_key = lbl->key;
5420
5421     if(result) {
5422       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5423       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5424     }else {
5425       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5426       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5427               __FUNCTION__,__LINE__);
5428       return;
5429     }
5430    
5431 /*     switch(size) { */
5432 /*     case 2: */
5433 /*       genc16bit2lit(left, lit, 0); */
5434 /*       emitSKPNZ; */
5435 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5436 /*       break; */
5437 /*     default: */
5438     while (size--) {
5439       int emit_skip=1;
5440       if((AOP_TYPE(left) == AOP_DIR) && 
5441          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5442
5443         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5444         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5445
5446       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5447             
5448         switch (lit & 0xff) {
5449         case 0:
5450           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5451           break;
5452         case 1:
5453           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5454           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5455           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5456           emit_skip=0;
5457           break;
5458         case 0xff:
5459           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5460           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5461           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5462           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5463           emit_skip=0;
5464           break;
5465         default:
5466           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5467           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5468         }
5469         lit >>= 8;
5470
5471       } else {
5472         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5473       }
5474       if(emit_skip) {
5475         if(AOP_TYPE(result) == AOP_CRY) {
5476           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5477           if(rIfx.condition)
5478             emitSKPNZ;
5479           else
5480             emitSKPZ;
5481           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5482         } else {
5483           /* fix me. probably need to check result size too */
5484           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5485           if(rIfx.condition)
5486             emitSKPZ;
5487           else
5488             emitSKPNZ;
5489           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5490           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5491         }
5492         if(ifx)
5493           ifx->generated=1;
5494       }
5495       emit_skip++;
5496       offset++;
5497       if(res_offset < res_size-1)
5498         res_offset++;
5499     }
5500 /*       break; */
5501 /*     } */
5502   } else if(AOP_TYPE(right) == AOP_REG &&
5503             AOP_TYPE(left) != AOP_DIR){
5504
5505     while(size--) {
5506       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5507       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5508       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5509       if(rIfx.condition)
5510         emitSKPNZ;
5511       else
5512         emitSKPZ;
5513       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5514       offset++;
5515       if(res_offset < res_size-1)
5516         res_offset++;
5517     }
5518       
5519   }else{
5520     /* right is a pointer reg need both a & b */
5521     while(size--) {
5522       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5523       if(strcmp(l,"b"))
5524         pic16_emitcode("mov","b,%s",l);
5525       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5526       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5527       offset++;
5528     }
5529   }
5530
5531   if(result && preserve_result)
5532     {
5533       int i;
5534       for(i = 0; i < AOP_SIZE(result); i++)
5535         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5536     }
5537
5538   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5539
5540   if(result && preserve_result)
5541     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5542
5543   if(!rIfx.condition)
5544     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5545
5546   pic16_emitpLabel(lbl->key);
5547
5548   if(result && preserve_result)
5549     {
5550       int i;
5551       for(i = 0; i < AOP_SIZE(result); i++)
5552         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5553
5554       pic16_emitpLabel(lbl_done->key);
5555    }
5556
5557   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5558
5559   if(ifx)
5560     ifx->generated = 1;
5561 }
5562 #endif
5563
5564 #if 0
5565 /*-----------------------------------------------------------------*/
5566 /* gencjne - compare and jump if not equal                         */
5567 /*-----------------------------------------------------------------*/
5568 static void gencjne(operand *left, operand *right, iCode *ifx)
5569 {
5570     symbol *tlbl  = newiTempLabel(NULL);
5571
5572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5573     gencjneshort(left, right, lbl);
5574
5575     pic16_emitcode("mov","a,%s",one);
5576     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5577     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5578     pic16_emitcode("clr","a");
5579     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5580
5581     pic16_emitpLabel(lbl->key);
5582     pic16_emitpLabel(tlbl->key);
5583
5584 }
5585 #endif
5586
5587
5588 /*-----------------------------------------------------------------*/
5589 /* is_LitOp - check if operand has to be treated as literal        */
5590 /*-----------------------------------------------------------------*/
5591 static bool is_LitOp(operand *op)
5592 {
5593   return (AOP_TYPE(op) == AOP_LIT)
5594       || ( (AOP_TYPE(op) == AOP_PCODE)
5595           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5596               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5597 }
5598
5599 /*-----------------------------------------------------------------*/
5600 /* is_LitAOp - check if operand has to be treated as literal        */
5601 /*-----------------------------------------------------------------*/
5602 static bool is_LitAOp(asmop *aop)
5603 {
5604   return (aop->type == AOP_LIT)
5605       || ( (aop->type == AOP_PCODE)
5606           && ( (aop->aopu.pcop->type == PO_LITERAL)
5607               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5608 }
5609
5610
5611
5612 /*-----------------------------------------------------------------*/
5613 /* genCmpEq - generates code for equal to                          */
5614 /*-----------------------------------------------------------------*/
5615 static void genCmpEq (iCode *ic, iCode *ifx)
5616 {
5617   operand *left, *right, *result;
5618   symbol *falselbl = newiTempLabel(NULL);
5619   symbol *donelbl = newiTempLabel(NULL);
5620
5621   int preserve_result = 0;
5622   int generate_result = 0;
5623   int i=0;
5624
5625   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5626   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5627   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5628  
5629   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5630   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5631
5632   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5633     {
5634       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5635       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5636       goto release;
5637     }
5638
5639   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5640     {
5641       operand *tmp = right ;
5642       right = left;
5643       left = tmp;
5644     }
5645
5646   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5647     preserve_result = 1;
5648
5649   if(result && AOP_SIZE(result))
5650     generate_result = 1;
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   for(i=0; i < AOP_SIZE(left); i++)
5659     {
5660       if(AOP_TYPE(left) != AOP_ACC)
5661         {
5662           if(is_LitOp(left))
5663             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5664           else
5665             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5666         }
5667       if(is_LitOp(right))
5668         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5669       else
5670         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5671
5672       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5673     }
5674
5675   // result == true
5676
5677   if(generate_result && preserve_result)
5678     {
5679       for(i = 0; i < AOP_SIZE(result); i++)
5680         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5681     }
5682
5683   if(generate_result)
5684     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5685
5686   if(generate_result && preserve_result)
5687     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5688
5689   if(ifx && IC_TRUE(ifx))
5690     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5691
5692   if(ifx && IC_FALSE(ifx))
5693     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5694
5695   pic16_emitpLabel(falselbl->key);
5696
5697   // result == false
5698
5699   if(ifx && IC_FALSE(ifx))
5700     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5701
5702   if(generate_result && preserve_result)
5703     {
5704       for(i = 0; i < AOP_SIZE(result); i++)
5705         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5706     }
5707
5708   pic16_emitpLabel(donelbl->key);
5709
5710   if(ifx)
5711     ifx->generated = 1;
5712
5713 release:
5714   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5715   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5716   pic16_freeAsmop(result,NULL,ic,TRUE);
5717
5718 }
5719
5720
5721 #if 0
5722 // old version kept for reference
5723
5724 /*-----------------------------------------------------------------*/
5725 /* genCmpEq - generates code for equal to                          */
5726 /*-----------------------------------------------------------------*/
5727 static void genCmpEq (iCode *ic, iCode *ifx)
5728 {
5729     operand *left, *right, *result;
5730     unsigned long lit = 0L;
5731     int size,offset=0;
5732     symbol *falselbl  = newiTempLabel(NULL);
5733
5734
5735     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5736
5737     if(ifx)
5738       DEBUGpic16_emitcode ("; ifx is non-null","");
5739     else
5740       DEBUGpic16_emitcode ("; ifx is null","");
5741
5742     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5743     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5744     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5745
5746     size = max(AOP_SIZE(left),AOP_SIZE(right));
5747
5748     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5749
5750     /* if literal, literal on the right or 
5751     if the right is in a pointer register and left 
5752     is not */
5753     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5754         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5755       operand *tmp = right ;
5756       right = left;
5757       left = tmp;
5758     }
5759
5760
5761     if(ifx && !AOP_SIZE(result)){
5762         symbol *tlbl;
5763         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5764         /* if they are both bit variables */
5765         if (AOP_TYPE(left) == AOP_CRY &&
5766             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5767                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5768             if(AOP_TYPE(right) == AOP_LIT){
5769                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5770                 if(lit == 0L){
5771                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5772                     pic16_emitcode("cpl","c");
5773                 } else if(lit == 1L) {
5774                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5775                 } else {
5776                     pic16_emitcode("clr","c");
5777                 }
5778                 /* AOP_TYPE(right) == AOP_CRY */
5779             } else {
5780                 symbol *lbl = newiTempLabel(NULL);
5781                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5782                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5783                 pic16_emitcode("cpl","c");
5784                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5785             }
5786             /* if true label then we jump if condition
5787             supplied is true */
5788             tlbl = newiTempLabel(NULL);
5789             if ( IC_TRUE(ifx) ) {
5790                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5791                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5792             } else {
5793                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5794                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5795             }
5796             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5797
5798                 {
5799                 /* left and right are both bit variables, result is carry */
5800                         resolvedIfx rIfx;
5801               
5802                         resolveIfx(&rIfx,ifx);
5803
5804                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5805                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5806                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5807                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5808                         genSkipz2(&rIfx,0);
5809                 }
5810         } else {
5811
5812                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5813
5814                         /* They're not both bit variables. Is the right a literal? */
5815                         if(AOP_TYPE(right) == AOP_LIT) {
5816                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5817             
5818                         switch(size) {
5819
5820                                 case 1:
5821                                         switch(lit & 0xff) {
5822                                                 case 1:
5823                                                                 if ( IC_TRUE(ifx) ) {
5824                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5825                                                                         emitSKPNZ;
5826                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5827                                                                 } else {
5828                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5829                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5830                                                                 }
5831                                                                 break;
5832                                                 case 0xff:
5833                                                                 if ( IC_TRUE(ifx) ) {
5834                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5835                                                                         emitSKPNZ;
5836                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5837                                                                 } else {
5838                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5839                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5840                                                                 }
5841                                                                 break;
5842                                                 default:
5843                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5844                                                                 if(lit)
5845                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5846                                                                 genSkip(ifx,'z');
5847                                         } // switch lit
5848
5849
5850                                         /* end of size == 1 */
5851                                         break;
5852               
5853                                 case 2:
5854                                         genc16bit2lit(left,lit,offset);
5855                                         genSkip(ifx,'z');
5856                                         break;
5857                                         /* end of size == 2 */
5858
5859                                 default:
5860                                         /* size is 4 */
5861                                         if(lit==0) {
5862                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5863                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5864                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5865                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5866                                                 genSkip(ifx,'z');
5867                                         } else {
5868                                                 /* search for patterns that can be optimized */
5869
5870                                                 genc16bit2lit(left,lit,0);
5871                                                 lit >>= 16;
5872                                                 if(lit) {
5873                                                                 if(IC_TRUE(ifx))
5874                                                                 emitSKPZ; // if hi word unequal
5875                                                                 else
5876                                                                 emitSKPNZ; // if hi word equal
5877                                                                 // fail early
5878                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5879                                                         genc16bit2lit(left,lit,2);
5880                                                         genSkip(ifx,'z');
5881                                                 } else {
5882                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5883                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5884                                                         genSkip(ifx,'z');
5885                                                 }
5886                                         }
5887                                                 pic16_emitpLabel(falselbl->key);
5888                                                 break;
5889
5890                         } // switch size
5891           
5892                         ifx->generated = 1;
5893                         goto release ;
5894             
5895
5896           } else if(AOP_TYPE(right) == AOP_CRY ) {
5897             /* we know the left is not a bit, but that the right is */
5898             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5899             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5900                       pic16_popGet(AOP(right),offset));
5901             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5902
5903             /* if the two are equal, then W will be 0 and the Z bit is set
5904              * we could test Z now, or go ahead and check the high order bytes if
5905              * the variable we're comparing is larger than a byte. */
5906
5907             while(--size)
5908               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5909
5910             if ( IC_TRUE(ifx) ) {
5911               emitSKPNZ;
5912               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5913               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5914             } else {
5915               emitSKPZ;
5916               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5917               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5918             }
5919
5920           } else {
5921             /* They're both variables that are larger than bits */
5922             int s = size;
5923
5924             tlbl = newiTempLabel(NULL);
5925
5926             while(size--) {
5927               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5928               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5929
5930               if ( IC_TRUE(ifx) ) {
5931                 if(size) {
5932                   emitSKPZ;
5933                 
5934                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5935
5936                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5937                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5938                 } else {
5939                   emitSKPNZ;
5940
5941                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5942
5943
5944                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5945                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5946                 }
5947               } else {
5948                 emitSKPZ;
5949
5950                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5951
5952                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5953                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5954               }
5955               offset++;
5956             }
5957             if(s>1 && IC_TRUE(ifx)) {
5958               pic16_emitpLabel(tlbl->key);
5959               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5960             }
5961           }
5962         }
5963         /* mark the icode as generated */
5964         ifx->generated = 1;
5965         goto release ;
5966     }
5967
5968     /* if they are both bit variables */
5969     if (AOP_TYPE(left) == AOP_CRY &&
5970         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5971         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5972         if(AOP_TYPE(right) == AOP_LIT){
5973             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5974             if(lit == 0L){
5975                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5976                 pic16_emitcode("cpl","c");
5977             } else if(lit == 1L) {
5978                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5979             } else {
5980                 pic16_emitcode("clr","c");
5981             }
5982             /* AOP_TYPE(right) == AOP_CRY */
5983         } else {
5984             symbol *lbl = newiTempLabel(NULL);
5985             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5986             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5987             pic16_emitcode("cpl","c");
5988             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5989         }
5990         /* c = 1 if egal */
5991         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5992             pic16_outBitC(result);
5993             goto release ;
5994         }
5995         if (ifx) {
5996             genIfxJump (ifx,"c");
5997             goto release ;
5998         }
5999         /* if the result is used in an arithmetic operation
6000         then put the result in place */
6001         pic16_outBitC(result);
6002     } else {
6003       
6004       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6005       gencjne(left,right,result,ifx);
6006 /*
6007       if(ifx) 
6008         gencjne(left,right,newiTempLabel(NULL));
6009       else {
6010         if(IC_TRUE(ifx)->key)
6011           gencjne(left,right,IC_TRUE(ifx)->key);
6012         else
6013           gencjne(left,right,IC_FALSE(ifx)->key);
6014         ifx->generated = 1;
6015         goto release ;
6016       }
6017       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6018         pic16_aopPut(AOP(result),"a",0);
6019         goto release ;
6020       }
6021
6022       if (ifx) {
6023         genIfxJump (ifx,"a");
6024         goto release ;
6025       }
6026 */
6027       /* if the result is used in an arithmetic operation
6028          then put the result in place */
6029 /*
6030       if (AOP_TYPE(result) != AOP_CRY) 
6031         pic16_outAcc(result);
6032 */
6033       /* leave the result in acc */
6034     }
6035
6036 release:
6037     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6038     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6039     pic16_freeAsmop(result,NULL,ic,TRUE);
6040 }
6041 #endif
6042
6043 /*-----------------------------------------------------------------*/
6044 /* ifxForOp - returns the icode containing the ifx for operand     */
6045 /*-----------------------------------------------------------------*/
6046 static iCode *ifxForOp ( operand *op, iCode *ic )
6047 {
6048     /* if true symbol then needs to be assigned */
6049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6050     if (IS_TRUE_SYMOP(op))
6051         return NULL ;
6052
6053     /* if this has register type condition and
6054     the next instruction is ifx with the same operand
6055     and live to of the operand is upto the ifx only then */
6056     if (ic->next
6057         && ic->next->op == IFX
6058         && IC_COND(ic->next)->key == op->key
6059         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6060         ) {
6061                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6062           return ic->next;
6063     }
6064
6065     if (ic->next &&
6066         ic->next->op == IFX &&
6067         IC_COND(ic->next)->key == op->key) {
6068       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6069       return ic->next;
6070     }
6071
6072     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6073     if (ic->next &&
6074         ic->next->op == IFX)
6075       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6076
6077     if (ic->next &&
6078         ic->next->op == IFX &&
6079         IC_COND(ic->next)->key == op->key) {
6080       DEBUGpic16_emitcode ("; "," key is okay");
6081       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6082                            OP_SYMBOL(op)->liveTo,
6083                            ic->next->seq);
6084     }
6085
6086 #if 0
6087     /* the code below is completely untested
6088      * it just allows ulong2fs.c compile -- VR */
6089          
6090     ic = ic->next;
6091     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6092                                         __FILE__, __FUNCTION__, __LINE__);
6093         
6094     /* if this has register type condition and
6095     the next instruction is ifx with the same operand
6096     and live to of the operand is upto the ifx only then */
6097     if (ic->next &&
6098         ic->next->op == IFX &&
6099         IC_COND(ic->next)->key == op->key &&
6100         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6101         return ic->next;
6102
6103     if (ic->next &&
6104         ic->next->op == IFX &&
6105         IC_COND(ic->next)->key == op->key) {
6106       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6107       return ic->next;
6108     }
6109
6110     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6111                                         __FILE__, __FUNCTION__, __LINE__);
6112
6113 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6114 #endif
6115
6116     return NULL;
6117 }
6118 /*-----------------------------------------------------------------*/
6119 /* genAndOp - for && operation                                     */
6120 /*-----------------------------------------------------------------*/
6121 static void genAndOp (iCode *ic)
6122 {
6123     operand *left,*right, *result;
6124 /*     symbol *tlbl; */
6125
6126     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6127     /* note here that && operations that are in an
6128     if statement are taken away by backPatchLabels
6129     only those used in arthmetic operations remain */
6130     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6131     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6132     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6133
6134     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6135
6136     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6137     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6138     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6139
6140     /* if both are bit variables */
6141 /*     if (AOP_TYPE(left) == AOP_CRY && */
6142 /*         AOP_TYPE(right) == AOP_CRY ) { */
6143 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6144 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6145 /*         pic16_outBitC(result); */
6146 /*     } else { */
6147 /*         tlbl = newiTempLabel(NULL); */
6148 /*         pic16_toBoolean(left);     */
6149 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6150 /*         pic16_toBoolean(right); */
6151 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6152 /*         pic16_outBitAcc(result); */
6153 /*     } */
6154
6155     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6156     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6157     pic16_freeAsmop(result,NULL,ic,TRUE);
6158 }
6159
6160
6161 /*-----------------------------------------------------------------*/
6162 /* genOrOp - for || operation                                      */
6163 /*-----------------------------------------------------------------*/
6164 /*
6165   tsd pic port -
6166   modified this code, but it doesn't appear to ever get called
6167 */
6168
6169 static void genOrOp (iCode *ic)
6170 {
6171     operand *left,*right, *result;
6172     symbol *tlbl;
6173
6174     /* note here that || operations that are in an
6175     if statement are taken away by backPatchLabels
6176     only those used in arthmetic operations remain */
6177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6178     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6179     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6180     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6181
6182     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6183
6184     /* if both are bit variables */
6185     if (AOP_TYPE(left) == AOP_CRY &&
6186         AOP_TYPE(right) == AOP_CRY ) {
6187       pic16_emitcode("clrc","");
6188       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6189                AOP(left)->aopu.aop_dir,
6190                AOP(left)->aopu.aop_dir);
6191       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6192                AOP(right)->aopu.aop_dir,
6193                AOP(right)->aopu.aop_dir);
6194       pic16_emitcode("setc","");
6195
6196     } else {
6197         tlbl = newiTempLabel(NULL);
6198         pic16_toBoolean(left);
6199         emitSKPZ;
6200         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6201         pic16_toBoolean(right);
6202         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6203
6204         pic16_outBitAcc(result);
6205     }
6206
6207     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6208     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6209     pic16_freeAsmop(result,NULL,ic,TRUE);            
6210 }
6211
6212 /*-----------------------------------------------------------------*/
6213 /* isLiteralBit - test if lit == 2^n                               */
6214 /*-----------------------------------------------------------------*/
6215 static int isLiteralBit(unsigned long lit)
6216 {
6217     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6218     0x100L,0x200L,0x400L,0x800L,
6219     0x1000L,0x2000L,0x4000L,0x8000L,
6220     0x10000L,0x20000L,0x40000L,0x80000L,
6221     0x100000L,0x200000L,0x400000L,0x800000L,
6222     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6223     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6224     int idx;
6225     
6226     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6227     for(idx = 0; idx < 32; idx++)
6228         if(lit == pw[idx])
6229             return idx+1;
6230     return 0;
6231 }
6232
6233 /*-----------------------------------------------------------------*/
6234 /* continueIfTrue -                                                */
6235 /*-----------------------------------------------------------------*/
6236 static void continueIfTrue (iCode *ic)
6237 {
6238     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6239     if(IC_TRUE(ic))
6240         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6241     ic->generated = 1;
6242 }
6243
6244 /*-----------------------------------------------------------------*/
6245 /* jmpIfTrue -                                                     */
6246 /*-----------------------------------------------------------------*/
6247 static void jumpIfTrue (iCode *ic)
6248 {
6249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6250     if(!IC_TRUE(ic))
6251         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6252     ic->generated = 1;
6253 }
6254
6255 /*-----------------------------------------------------------------*/
6256 /* jmpTrueOrFalse -                                                */
6257 /*-----------------------------------------------------------------*/
6258 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6259 {
6260     // ugly but optimized by peephole
6261     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6262     if(IC_TRUE(ic)){
6263         symbol *nlbl = newiTempLabel(NULL);
6264         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6265         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6266         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6267         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6268     }
6269     else{
6270         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6271         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6272     }
6273     ic->generated = 1;
6274 }
6275
6276 /*-----------------------------------------------------------------*/
6277 /* genAnd  - code for and                                          */
6278 /*-----------------------------------------------------------------*/
6279 static void genAnd (iCode *ic, iCode *ifx)
6280 {
6281   operand *left, *right, *result;
6282   int size, offset=0;  
6283   unsigned long lit = 0L;
6284   int bytelit = 0;
6285   resolvedIfx rIfx;
6286
6287
6288   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6289   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6290   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6291   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6292
6293   resolveIfx(&rIfx,ifx);
6294
6295   /* if left is a literal & right is not then exchange them */
6296   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6297       AOP_NEEDSACC(left)) {
6298     operand *tmp = right ;
6299     right = left;
6300     left = tmp;
6301   }
6302
6303   /* if result = right then exchange them */
6304   if(pic16_sameRegs(AOP(result),AOP(right))){
6305     operand *tmp = right ;
6306     right = left;
6307     left = tmp;
6308   }
6309
6310   /* if right is bit then exchange them */
6311   if (AOP_TYPE(right) == AOP_CRY &&
6312       AOP_TYPE(left) != AOP_CRY){
6313     operand *tmp = right ;
6314     right = left;
6315     left = tmp;
6316   }
6317   if(AOP_TYPE(right) == AOP_LIT)
6318     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6319
6320   size = AOP_SIZE(result);
6321
6322   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6323
6324   // if(bit & yy)
6325   // result = bit & yy;
6326   if (AOP_TYPE(left) == AOP_CRY){
6327     // c = bit & literal;
6328     if(AOP_TYPE(right) == AOP_LIT){
6329       if(lit & 1) {
6330         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6331           // no change
6332           goto release;
6333         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6334       } else {
6335         // bit(result) = 0;
6336         if(size && (AOP_TYPE(result) == AOP_CRY)){
6337           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6338           goto release;
6339         }
6340         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6341           jumpIfTrue(ifx);
6342           goto release;
6343         }
6344         pic16_emitcode("clr","c");
6345       }
6346     } else {
6347       if (AOP_TYPE(right) == AOP_CRY){
6348         // c = bit & bit;
6349         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6350         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6351       } else {
6352         // c = bit & val;
6353         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6354         // c = lsb
6355         pic16_emitcode("rrc","a");
6356         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6357       }
6358     }
6359     // bit = c
6360     // val = c
6361     if(size)
6362       pic16_outBitC(result);
6363     // if(bit & ...)
6364     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6365       genIfxJump(ifx, "c");           
6366     goto release ;
6367   }
6368
6369   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6370   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6371   if((AOP_TYPE(right) == AOP_LIT) &&
6372      (AOP_TYPE(result) == AOP_CRY) &&
6373      (AOP_TYPE(left) != AOP_CRY)){
6374     int posbit = isLiteralBit(lit);
6375     /* left &  2^n */
6376     if(posbit){
6377       posbit--;
6378       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6379       // bit = left & 2^n
6380       if(size)
6381         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6382       // if(left &  2^n)
6383       else{
6384         if(ifx){
6385 /*
6386           if(IC_TRUE(ifx)) {
6387             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6388             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6389           } else {
6390             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6391             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6392           }
6393 */
6394         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6395         size = AOP_SIZE(left);
6396
6397         {
6398           int bp = posbit, ofs=0;
6399           
6400             while(bp > 7) {
6401               bp -= 8;
6402               ofs++;
6403             }
6404         
6405           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6406                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6407
6408         }
6409 /*
6410           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6411                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6412 */
6413           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6414           
6415           ifx->generated = 1;
6416         }
6417         goto release;
6418       }
6419     } else {
6420       symbol *tlbl = newiTempLabel(NULL);
6421       int sizel = AOP_SIZE(left);
6422       if(size)
6423         pic16_emitcode("setb","c");
6424       while(sizel--){
6425         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6426           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6427           // byte ==  2^n ?
6428           if((posbit = isLiteralBit(bytelit)) != 0)
6429             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6430           else{
6431             if(bytelit != 0x0FFL)
6432               pic16_emitcode("anl","a,%s",
6433                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6434             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6435           }
6436         }
6437         offset++;
6438       }
6439       // bit = left & literal
6440       if(size){
6441         pic16_emitcode("clr","c");
6442         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6443       }
6444       // if(left & literal)
6445       else{
6446         if(ifx)
6447           jmpTrueOrFalse(ifx, tlbl);
6448         goto release ;
6449       }
6450     }
6451     pic16_outBitC(result);
6452     goto release ;
6453   }
6454
6455   /* if left is same as result */
6456   if(pic16_sameRegs(AOP(result),AOP(left))){
6457     int know_W = -1;
6458     for(;size--; offset++,lit>>=8) {
6459       if(AOP_TYPE(right) == AOP_LIT){
6460         switch(lit & 0xff) {
6461         case 0x00:
6462           /*  and'ing with 0 has clears the result */
6463 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6464           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6465           break;
6466         case 0xff:
6467           /* and'ing with 0xff is a nop when the result and left are the same */
6468           break;
6469
6470         default:
6471           {
6472             int p = my_powof2( (~lit) & 0xff );
6473             if(p>=0) {
6474               /* only one bit is set in the literal, so use a bcf instruction */
6475 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6476               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6477
6478             } else {
6479               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6480               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6481               if(know_W != (lit&0xff))
6482                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6483               know_W = lit &0xff;
6484               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6485             }
6486           }    
6487         }
6488       } else {
6489         if (AOP_TYPE(left) == AOP_ACC) {
6490           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6491         } else {                    
6492           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6493           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6494
6495         }
6496       }
6497     }
6498
6499   } else {
6500     // left & result in different registers
6501     if(AOP_TYPE(result) == AOP_CRY){
6502       // result = bit
6503       // if(size), result in bit
6504       // if(!size && ifx), conditional oper: if(left & right)
6505       symbol *tlbl = newiTempLabel(NULL);
6506       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6507       if(size)
6508         pic16_emitcode("setb","c");
6509       while(sizer--){
6510         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6511         pic16_emitcode("anl","a,%s",
6512                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6513         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6514         offset++;
6515       }
6516       if(size){
6517         CLRC;
6518         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6519         pic16_outBitC(result);
6520       } else if(ifx)
6521         jmpTrueOrFalse(ifx, tlbl);
6522     } else {
6523       for(;(size--);offset++) {
6524         // normal case
6525         // result = left & right
6526         if(AOP_TYPE(right) == AOP_LIT){
6527           int t = (lit >> (offset*8)) & 0x0FFL;
6528           switch(t) { 
6529           case 0x00:
6530             pic16_emitcode("clrf","%s",
6531                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6532             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6533             break;
6534           case 0xff:
6535             pic16_emitcode("movf","%s,w",
6536                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6537             pic16_emitcode("movwf","%s",
6538                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6539             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6540             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6541             break;
6542           default:
6543             pic16_emitcode("movlw","0x%x",t);
6544             pic16_emitcode("andwf","%s,w",
6545                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6546             pic16_emitcode("movwf","%s",
6547                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6548               
6549             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6550             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6551             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6552           }
6553           continue;
6554         }
6555
6556         if (AOP_TYPE(left) == AOP_ACC) {
6557           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6558           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6559         } else {
6560           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6561           pic16_emitcode("andwf","%s,w",
6562                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6563           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6564           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6565         }
6566         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6567         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6568       }
6569     }
6570   }
6571
6572   release :
6573     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6574   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6575   pic16_freeAsmop(result,NULL,ic,TRUE);     
6576 }
6577
6578 /*-----------------------------------------------------------------*/
6579 /* genOr  - code for or                                            */
6580 /*-----------------------------------------------------------------*/
6581 static void genOr (iCode *ic, iCode *ifx)
6582 {
6583     operand *left, *right, *result;
6584     int size, offset=0;
6585     unsigned long lit = 0L;
6586
6587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6588
6589     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6590     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6591     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6592
6593     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6594
6595     /* if left is a literal & right is not then exchange them */
6596     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6597         AOP_NEEDSACC(left)) {
6598         operand *tmp = right ;
6599         right = left;
6600         left = tmp;
6601     }
6602
6603     /* if result = right then exchange them */
6604     if(pic16_sameRegs(AOP(result),AOP(right))){
6605         operand *tmp = right ;
6606         right = left;
6607         left = tmp;
6608     }
6609
6610     /* if right is bit then exchange them */
6611     if (AOP_TYPE(right) == AOP_CRY &&
6612         AOP_TYPE(left) != AOP_CRY){
6613         operand *tmp = right ;
6614         right = left;
6615         left = tmp;
6616     }
6617
6618     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6619
6620     if(AOP_TYPE(right) == AOP_LIT)
6621         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6622
6623     size = AOP_SIZE(result);
6624
6625     // if(bit | yy)
6626     // xx = bit | yy;
6627     if (AOP_TYPE(left) == AOP_CRY){
6628         if(AOP_TYPE(right) == AOP_LIT){
6629             // c = bit & literal;
6630             if(lit){
6631                 // lit != 0 => result = 1
6632                 if(AOP_TYPE(result) == AOP_CRY){
6633                   if(size)
6634                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6635                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6636                   //     AOP(result)->aopu.aop_dir,
6637                   //     AOP(result)->aopu.aop_dir);
6638                     else if(ifx)
6639                         continueIfTrue(ifx);
6640                     goto release;
6641                 }
6642             } else {
6643                 // lit == 0 => result = left
6644                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6645                     goto release;
6646                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6647             }
6648         } else {
6649             if (AOP_TYPE(right) == AOP_CRY){
6650               if(pic16_sameRegs(AOP(result),AOP(left))){
6651                 // c = bit | bit;
6652                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6653                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6654                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6655
6656                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6657                          AOP(result)->aopu.aop_dir,
6658                          AOP(result)->aopu.aop_dir);
6659                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6660                          AOP(right)->aopu.aop_dir,
6661                          AOP(right)->aopu.aop_dir);
6662                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6663                          AOP(result)->aopu.aop_dir,
6664                          AOP(result)->aopu.aop_dir);
6665               } else {
6666                 if( AOP_TYPE(result) == AOP_ACC) {
6667                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6668                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6669                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6670                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6671
6672                 } else {
6673
6674                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6675                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6676                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6677                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6678
6679                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6680                                  AOP(result)->aopu.aop_dir,
6681                                  AOP(result)->aopu.aop_dir);
6682                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6683                                  AOP(right)->aopu.aop_dir,
6684                                  AOP(right)->aopu.aop_dir);
6685                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6686                                  AOP(left)->aopu.aop_dir,
6687                                  AOP(left)->aopu.aop_dir);
6688                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6689                                  AOP(result)->aopu.aop_dir,
6690                                  AOP(result)->aopu.aop_dir);
6691                 }
6692               }
6693             } else {
6694                 // c = bit | val;
6695                 symbol *tlbl = newiTempLabel(NULL);
6696                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6697
6698
6699                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6700                 if( AOP_TYPE(right) == AOP_ACC) {
6701                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6702                   emitSKPNZ;
6703                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6704                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6705                 }
6706
6707
6708
6709                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6710                     pic16_emitcode(";XXX setb","c");
6711                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6712                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6713                 pic16_toBoolean(right);
6714                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6715                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6716                     jmpTrueOrFalse(ifx, tlbl);
6717                     goto release;
6718                 } else {
6719                     CLRC;
6720                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6721                 }
6722             }
6723         }
6724         // bit = c
6725         // val = c
6726         if(size)
6727             pic16_outBitC(result);
6728         // if(bit | ...)
6729         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6730             genIfxJump(ifx, "c");           
6731         goto release ;
6732     }
6733
6734     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6735     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6736     if((AOP_TYPE(right) == AOP_LIT) &&
6737        (AOP_TYPE(result) == AOP_CRY) &&
6738        (AOP_TYPE(left) != AOP_CRY)){
6739         if(lit){
6740           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6741             // result = 1
6742             if(size)
6743                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6744             else 
6745                 continueIfTrue(ifx);
6746             goto release;
6747         } else {
6748           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6749             // lit = 0, result = boolean(left)
6750             if(size)
6751                 pic16_emitcode(";XXX setb","c");
6752             pic16_toBoolean(right);
6753             if(size){
6754                 symbol *tlbl = newiTempLabel(NULL);
6755                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6756                 CLRC;
6757                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6758             } else {
6759                 genIfxJump (ifx,"a");
6760                 goto release;
6761             }
6762         }
6763         pic16_outBitC(result);
6764         goto release ;
6765     }
6766
6767     /* if left is same as result */
6768     if(pic16_sameRegs(AOP(result),AOP(left))){
6769       int know_W = -1;
6770       for(;size--; offset++,lit>>=8) {
6771         if(AOP_TYPE(right) == AOP_LIT){
6772           if((lit & 0xff) == 0)
6773             /*  or'ing with 0 has no effect */
6774             continue;
6775           else {
6776             int p = my_powof2(lit & 0xff);
6777             if(p>=0) {
6778               /* only one bit is set in the literal, so use a bsf instruction */
6779               pic16_emitpcode(POC_BSF,
6780                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6781             } else {
6782               if(know_W != (lit & 0xff))
6783                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6784               know_W = lit & 0xff;
6785               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6786             }
6787                     
6788           }
6789         } else {
6790           if (AOP_TYPE(left) == AOP_ACC) {
6791             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6792             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6793           } else {                  
6794             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6795             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6796
6797             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6798             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6799
6800           }
6801         }
6802       }
6803     } else {
6804         // left & result in different registers
6805         if(AOP_TYPE(result) == AOP_CRY){
6806             // result = bit
6807             // if(size), result in bit
6808             // if(!size && ifx), conditional oper: if(left | right)
6809             symbol *tlbl = newiTempLabel(NULL);
6810             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6811             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6812
6813
6814             if(size)
6815                 pic16_emitcode(";XXX setb","c");
6816             while(sizer--){
6817                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6818                 pic16_emitcode(";XXX orl","a,%s",
6819                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6820                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6821                 offset++;
6822             }
6823             if(size){
6824                 CLRC;
6825                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6826                 pic16_outBitC(result);
6827             } else if(ifx)
6828                 jmpTrueOrFalse(ifx, tlbl);
6829         } else for(;(size--);offset++){
6830           // normal case
6831           // result = left & right
6832           if(AOP_TYPE(right) == AOP_LIT){
6833             int t = (lit >> (offset*8)) & 0x0FFL;
6834             switch(t) { 
6835             case 0x00:
6836               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6837               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6838
6839               pic16_emitcode("movf","%s,w",
6840                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6841               pic16_emitcode("movwf","%s",
6842                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6843               break;
6844             default:
6845               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6846               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6847               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6848
6849               pic16_emitcode("movlw","0x%x",t);
6850               pic16_emitcode("iorwf","%s,w",
6851                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6852               pic16_emitcode("movwf","%s",
6853                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6854               
6855             }
6856             continue;
6857           }
6858
6859           // faster than result <- left, anl result,right
6860           // and better if result is SFR
6861           if (AOP_TYPE(left) == AOP_ACC) {
6862             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6863             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6864           } else {
6865             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6866             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6867
6868             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6869             pic16_emitcode("iorwf","%s,w",
6870                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6871           }
6872           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6873           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6874         }
6875     }
6876
6877 release :
6878     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6879     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6880     pic16_freeAsmop(result,NULL,ic,TRUE);     
6881 }
6882
6883 /*-----------------------------------------------------------------*/
6884 /* genXor - code for xclusive or                                   */
6885 /*-----------------------------------------------------------------*/
6886 static void genXor (iCode *ic, iCode *ifx)
6887 {
6888   operand *left, *right, *result;
6889   int size, offset=0;
6890   unsigned long lit = 0L;
6891
6892   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6893
6894   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6895   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6896   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6897
6898   /* if left is a literal & right is not ||
6899      if left needs acc & right does not */
6900   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6901       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6902     operand *tmp = right ;
6903     right = left;
6904     left = tmp;
6905   }
6906
6907   /* if result = right then exchange them */
6908   if(pic16_sameRegs(AOP(result),AOP(right))){
6909     operand *tmp = right ;
6910     right = left;
6911     left = tmp;
6912   }
6913
6914   /* if right is bit then exchange them */
6915   if (AOP_TYPE(right) == AOP_CRY &&
6916       AOP_TYPE(left) != AOP_CRY){
6917     operand *tmp = right ;
6918     right = left;
6919     left = tmp;
6920   }
6921   if(AOP_TYPE(right) == AOP_LIT)
6922     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6923
6924   size = AOP_SIZE(result);
6925
6926   // if(bit ^ yy)
6927   // xx = bit ^ yy;
6928   if (AOP_TYPE(left) == AOP_CRY){
6929     if(AOP_TYPE(right) == AOP_LIT){
6930       // c = bit & literal;
6931       if(lit>>1){
6932         // lit>>1  != 0 => result = 1
6933         if(AOP_TYPE(result) == AOP_CRY){
6934           if(size)
6935             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6936             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6937           else if(ifx)
6938             continueIfTrue(ifx);
6939           goto release;
6940         }
6941         pic16_emitcode("setb","c");
6942       } else{
6943         // lit == (0 or 1)
6944         if(lit == 0){
6945           // lit == 0, result = left
6946           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6947             goto release;
6948           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6949         } else{
6950           // lit == 1, result = not(left)
6951           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6952             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6953             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6954             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6955             goto release;
6956           } else {
6957             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6958             pic16_emitcode("cpl","c");
6959           }
6960         }
6961       }
6962
6963     } else {
6964       // right != literal
6965       symbol *tlbl = newiTempLabel(NULL);
6966       if (AOP_TYPE(right) == AOP_CRY){
6967         // c = bit ^ bit;
6968         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6969       }
6970       else{
6971         int sizer = AOP_SIZE(right);
6972         // c = bit ^ val
6973         // if val>>1 != 0, result = 1
6974         pic16_emitcode("setb","c");
6975         while(sizer){
6976           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6977           if(sizer == 1)
6978             // test the msb of the lsb
6979             pic16_emitcode("anl","a,#0xfe");
6980           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6981           sizer--;
6982         }
6983         // val = (0,1)
6984         pic16_emitcode("rrc","a");
6985       }
6986       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6987       pic16_emitcode("cpl","c");
6988       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6989     }
6990     // bit = c
6991     // val = c
6992     if(size)
6993       pic16_outBitC(result);
6994     // if(bit | ...)
6995     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6996       genIfxJump(ifx, "c");           
6997     goto release ;
6998   }
6999
7000   if(pic16_sameRegs(AOP(result),AOP(left))){
7001     /* if left is same as result */
7002     for(;size--; offset++) {
7003       if(AOP_TYPE(right) == AOP_LIT){
7004         int t  = (lit >> (offset*8)) & 0x0FFL;
7005         if(t == 0x00L)
7006           continue;
7007         else
7008           if (IS_AOP_PREG(left)) {
7009             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7010             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7011             pic16_aopPut(AOP(result),"a",offset);
7012           } else {
7013             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7014             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7015             pic16_emitcode("xrl","%s,%s",
7016                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7017                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7018           }
7019       } else {
7020         if (AOP_TYPE(left) == AOP_ACC)
7021           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7022         else {
7023           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7024           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7025 /*
7026           if (IS_AOP_PREG(left)) {
7027             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7028             pic16_aopPut(AOP(result),"a",offset);
7029           } else
7030             pic16_emitcode("xrl","%s,a",
7031                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7032 */
7033         }
7034       }
7035     }
7036   } else {
7037     // left & result in different registers
7038     if(AOP_TYPE(result) == AOP_CRY){
7039       // result = bit
7040       // if(size), result in bit
7041       // if(!size && ifx), conditional oper: if(left ^ right)
7042       symbol *tlbl = newiTempLabel(NULL);
7043       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7044       if(size)
7045         pic16_emitcode("setb","c");
7046       while(sizer--){
7047         if((AOP_TYPE(right) == AOP_LIT) &&
7048            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7049           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7050         } else {
7051           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7052           pic16_emitcode("xrl","a,%s",
7053                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7054         }
7055         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7056         offset++;
7057       }
7058       if(size){
7059         CLRC;
7060         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7061         pic16_outBitC(result);
7062       } else if(ifx)
7063         jmpTrueOrFalse(ifx, tlbl);
7064     } else for(;(size--);offset++){
7065       // normal case
7066       // result = left & right
7067       if(AOP_TYPE(right) == AOP_LIT){
7068         int t = (lit >> (offset*8)) & 0x0FFL;
7069         switch(t) { 
7070         case 0x00:
7071           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7072           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7073           pic16_emitcode("movf","%s,w",
7074                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7075           pic16_emitcode("movwf","%s",
7076                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7077           break;
7078         case 0xff:
7079           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7080           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7081           pic16_emitcode("comf","%s,w",
7082                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7083           pic16_emitcode("movwf","%s",
7084                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7085           break;
7086         default:
7087           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7088           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7089           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7090           pic16_emitcode("movlw","0x%x",t);
7091           pic16_emitcode("xorwf","%s,w",
7092                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7093           pic16_emitcode("movwf","%s",
7094                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7095
7096         }
7097         continue;
7098       }
7099
7100       // faster than result <- left, anl result,right
7101       // and better if result is SFR
7102       if (AOP_TYPE(left) == AOP_ACC) {
7103         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7104         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7105       } else {
7106         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7107         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7108         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7109         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7110       }
7111       if ( AOP_TYPE(result) != AOP_ACC){
7112         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7113         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7114       }
7115     }
7116   }
7117
7118   release :
7119     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7120   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7121   pic16_freeAsmop(result,NULL,ic,TRUE);     
7122 }
7123
7124 /*-----------------------------------------------------------------*/
7125 /* genInline - write the inline code out                           */
7126 /*-----------------------------------------------------------------*/
7127 static void genInline (iCode *ic)
7128 {
7129   char *buffer, *bp, *bp1;
7130     
7131         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7132
7133         _G.inLine += (!options.asmpeep);
7134
7135         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7136         strcpy(buffer,IC_INLINE(ic));
7137
7138 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7139
7140         /* emit each line as a code */
7141         while (*bp) {
7142                 if (*bp == '\n') {
7143                         *bp++ = '\0';
7144
7145                         if(*bp1)
7146                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7147                         bp1 = bp;
7148                 } else {
7149                         if (*bp == ':') {
7150                                 bp++;
7151                                 *bp = '\0';
7152                                 bp++;
7153
7154                                 /* print label, use this special format with NULL directive
7155                                  * to denote that the argument should not be indented with tab */
7156                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7157                                 bp1 = bp;
7158                         } else
7159                                 bp++;
7160                 }
7161         }
7162
7163         if ((bp1 != bp) && *bp1)
7164                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7165
7166
7167     Safe_free(buffer);
7168
7169     _G.inLine -= (!options.asmpeep);
7170 }
7171
7172 /*-----------------------------------------------------------------*/
7173 /* genRRC - rotate right with carry                                */
7174 /*-----------------------------------------------------------------*/
7175 static void genRRC (iCode *ic)
7176 {
7177   operand *left , *result ;
7178   int size, offset = 0, same;
7179
7180   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7181
7182   /* rotate right with carry */
7183   left = IC_LEFT(ic);
7184   result=IC_RESULT(ic);
7185   pic16_aopOp (left,ic,FALSE);
7186   pic16_aopOp (result,ic,FALSE);
7187
7188   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7189
7190   same = pic16_sameRegs(AOP(result),AOP(left));
7191
7192   size = AOP_SIZE(result);    
7193
7194   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7195
7196   /* get the lsb and put it into the carry */
7197   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7198
7199   offset = 0 ;
7200
7201   while(size--) {
7202
7203     if(same) {
7204       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7205     } else {
7206       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7207       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7208     }
7209
7210     offset++;
7211   }
7212
7213   pic16_freeAsmop(left,NULL,ic,TRUE);
7214   pic16_freeAsmop(result,NULL,ic,TRUE);
7215 }
7216
7217 /*-----------------------------------------------------------------*/
7218 /* genRLC - generate code for rotate left with carry               */
7219 /*-----------------------------------------------------------------*/
7220 static void genRLC (iCode *ic)
7221 {    
7222   operand *left , *result ;
7223   int size, offset = 0;
7224   int same;
7225
7226   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7227   /* rotate right with carry */
7228   left = IC_LEFT(ic);
7229   result=IC_RESULT(ic);
7230   pic16_aopOp (left,ic,FALSE);
7231   pic16_aopOp (result,ic,FALSE);
7232
7233   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7234
7235   same = pic16_sameRegs(AOP(result),AOP(left));
7236
7237   /* move it to the result */
7238   size = AOP_SIZE(result);    
7239
7240   /* get the msb and put it into the carry */
7241   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7242
7243   offset = 0 ;
7244
7245   while(size--) {
7246
7247     if(same) {
7248       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7249     } else {
7250       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7251       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7252     }
7253
7254     offset++;
7255   }
7256
7257
7258   pic16_freeAsmop(left,NULL,ic,TRUE);
7259   pic16_freeAsmop(result,NULL,ic,TRUE);
7260 }
7261
7262
7263 /* gpasm can get the highest order bit with HIGH/UPPER
7264  * so the following probably is not needed -- VR */
7265  
7266 /*-----------------------------------------------------------------*/
7267 /* genGetHbit - generates code get highest order bit               */
7268 /*-----------------------------------------------------------------*/
7269 static void genGetHbit (iCode *ic)
7270 {
7271     operand *left, *result;
7272     left = IC_LEFT(ic);
7273     result=IC_RESULT(ic);
7274     pic16_aopOp (left,ic,FALSE);
7275     pic16_aopOp (result,ic,FALSE);
7276
7277     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7278     /* get the highest order byte into a */
7279     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7280     if(AOP_TYPE(result) == AOP_CRY){
7281         pic16_emitcode("rlc","a");
7282         pic16_outBitC(result);
7283     }
7284     else{
7285         pic16_emitcode("rl","a");
7286         pic16_emitcode("anl","a,#0x01");
7287         pic16_outAcc(result);
7288     }
7289
7290
7291     pic16_freeAsmop(left,NULL,ic,TRUE);
7292     pic16_freeAsmop(result,NULL,ic,TRUE);
7293 }
7294
7295 #if 0
7296 /*-----------------------------------------------------------------*/
7297 /* AccRol - rotate left accumulator by known count                 */
7298 /*-----------------------------------------------------------------*/
7299 static void AccRol (int shCount)
7300 {
7301     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7302     shCount &= 0x0007;              // shCount : 0..7
7303     switch(shCount){
7304         case 0 :
7305             break;
7306         case 1 :
7307             pic16_emitcode("rl","a");
7308             break;
7309         case 2 :
7310             pic16_emitcode("rl","a");
7311             pic16_emitcode("rl","a");
7312             break;
7313         case 3 :
7314             pic16_emitcode("swap","a");
7315             pic16_emitcode("rr","a");
7316             break;
7317         case 4 :
7318             pic16_emitcode("swap","a");
7319             break;
7320         case 5 :
7321             pic16_emitcode("swap","a");
7322             pic16_emitcode("rl","a");
7323             break;
7324         case 6 :
7325             pic16_emitcode("rr","a");
7326             pic16_emitcode("rr","a");
7327             break;
7328         case 7 :
7329             pic16_emitcode("rr","a");
7330             break;
7331     }
7332 }
7333 #endif
7334
7335 /*-----------------------------------------------------------------*/
7336 /* AccLsh - left shift accumulator by known count                  */
7337 /*-----------------------------------------------------------------*/
7338 static void AccLsh (int shCount)
7339 {
7340         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7341         switch(shCount){
7342                 case 0 :
7343                         return;
7344                         break;
7345                 case 1 :
7346                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7347                         break;
7348                 case 2 :
7349                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7350                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7351                         break;
7352                 case 3 :
7353                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7354                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7355                         break;
7356                 case 4 :
7357                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7358                         break;
7359                 case 5 :
7360                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7361                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7362                         break;
7363                 case 6 :
7364                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7365                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7366                         break;
7367                 case 7 :
7368                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7369                         break;
7370         }
7371
7372         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7373 }
7374
7375 /*-----------------------------------------------------------------*/
7376 /* AccRsh - right shift accumulator by known count                 */
7377 /*-----------------------------------------------------------------*/
7378 static void AccRsh (int shCount, int andmask)
7379 {
7380         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7381         switch(shCount){
7382                 case 0 :
7383                         return; break;
7384                 case 1 :
7385                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7386 //                      andmask = 0;    /* no need */
7387                         break;
7388                 case 2 :
7389                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7390                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7391 //                      andmask = 0;    /* no need */
7392                         break;
7393                 case 3 :
7394                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7395                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7396                         break;
7397                 case 4 :
7398                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7399                         break;
7400                 case 5 :
7401                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7402                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7403                         break;
7404                 case 6 :
7405                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7406                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7407                         break;
7408                 case 7 :
7409                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7410                         break;
7411         }
7412         
7413         if(andmask)
7414                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7415         else
7416                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7417 }
7418
7419 #if 0
7420 /*-----------------------------------------------------------------*/
7421 /* AccSRsh - signed right shift accumulator by known count                 */
7422 /*-----------------------------------------------------------------*/
7423 static void AccSRsh (int shCount)
7424 {
7425     symbol *tlbl ;
7426     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7427     if(shCount != 0){
7428         if(shCount == 1){
7429             pic16_emitcode("mov","c,acc.7");
7430             pic16_emitcode("rrc","a");
7431         } else if(shCount == 2){
7432             pic16_emitcode("mov","c,acc.7");
7433             pic16_emitcode("rrc","a");
7434             pic16_emitcode("mov","c,acc.7");
7435             pic16_emitcode("rrc","a");
7436         } else {
7437             tlbl = newiTempLabel(NULL);
7438             /* rotate right accumulator */
7439             AccRol(8 - shCount);
7440             /* and kill the higher order bits */
7441             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7442             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7443             pic16_emitcode("orl","a,#0x%02x",
7444                      (unsigned char)~SRMask[shCount]);
7445             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7446         }
7447     }
7448 }
7449 #endif
7450 /*-----------------------------------------------------------------*/
7451 /* shiftR1Left2Result - shift right one byte from left to result   */
7452 /*-----------------------------------------------------------------*/
7453 static void shiftR1Left2ResultSigned (operand *left, int offl,
7454                                 operand *result, int offr,
7455                                 int shCount)
7456 {
7457   int same;
7458
7459   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7460
7461   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7462
7463   switch(shCount) {
7464   case 1:
7465     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7466     if(same) 
7467       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7468     else {
7469       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7470       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7471     }
7472
7473     break;
7474   case 2:
7475
7476     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7477     if(same) 
7478       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7479     else {
7480       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7481       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7482     }
7483     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7484     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7485
7486     break;
7487
7488   case 3:
7489     if(same)
7490       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7491     else {
7492       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7493       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7494     }
7495
7496     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7497     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7498     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7499
7500     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7501     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7502
7503     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7504     break;
7505
7506   case 4:
7507     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7508     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7509     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7510     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7511     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7512     break;
7513   case 5:
7514     if(same) {
7515       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7516     } else {
7517       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7518       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7519     }
7520     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7521     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7522     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7523     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7524     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7525     break;
7526
7527   case 6:
7528     if(same) {
7529       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7530       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7531       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7532       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7533       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7534       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7535     } else {
7536       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7537       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7538       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7539       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7540       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7541     }
7542     break;
7543
7544   case 7:
7545     if(same) {
7546       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7547       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7548       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7549       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7550     } else {
7551       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7552       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7553       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7554     }
7555
7556   default:
7557     break;
7558   }
7559 }
7560
7561 /*-----------------------------------------------------------------*/
7562 /* shiftR1Left2Result - shift right one byte from left to result   */
7563 /*-----------------------------------------------------------------*/
7564 static void shiftR1Left2Result (operand *left, int offl,
7565                                 operand *result, int offr,
7566                                 int shCount, int sign)
7567 {
7568   int same;
7569
7570   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7571
7572   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7573
7574   /* Copy the msb into the carry if signed. */
7575   if(sign) {
7576     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7577     return;
7578   }
7579
7580
7581
7582   switch(shCount) {
7583   case 1:
7584     emitCLRC;
7585     if(same) 
7586       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7587     else {
7588       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7589       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7590     }
7591     break;
7592   case 2:
7593     emitCLRC;
7594     if(same) {
7595       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7596     } else {
7597       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7598       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7599     }
7600     emitCLRC;
7601     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7602
7603     break;
7604   case 3:
7605     if(same)
7606       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7607     else {
7608       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7609       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7610     }
7611
7612     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7613     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7614     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7615     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7616     break;
7617       
7618   case 4:
7619     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7620     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7621     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7622     break;
7623
7624   case 5:
7625     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7626     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7627     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7628     emitCLRC;
7629     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7630
7631     break;
7632   case 6:
7633
7634     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7635     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7636     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7637     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7638     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7639     break;
7640
7641   case 7:
7642
7643     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7644     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7645     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7646
7647     break;
7648
7649   default:
7650     break;
7651   }
7652 }
7653
7654 /*-----------------------------------------------------------------*/
7655 /* shiftL1Left2Result - shift left one byte from left to result    */
7656 /*-----------------------------------------------------------------*/
7657 static void shiftL1Left2Result (operand *left, int offl,
7658                                 operand *result, int offr, int shCount)
7659 {
7660   int same;
7661
7662   //    char *l;
7663   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7664
7665   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7666   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7667     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7668     //    MOVA(l);
7669     /* shift left accumulator */
7670     //AccLsh(shCount); // don't comment out just yet...
7671   //    pic16_aopPut(AOP(result),"a",offr);
7672
7673   switch(shCount) {
7674   case 1:
7675     /* Shift left 1 bit position */
7676     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7677     if(same) {
7678       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7679     } else {
7680       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7681       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7682     }
7683     break;
7684   case 2:
7685     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7686     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7687     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7688     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7689     break;
7690   case 3:
7691     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7692     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7693     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7694     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7695     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7696     break;
7697   case 4:
7698     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7699     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7700     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7701     break;
7702   case 5:
7703     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7704     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7705     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7706     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7707     break;
7708   case 6:
7709     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7710     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7711     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7712     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7713     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7714     break;
7715   case 7:
7716     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7717     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7718     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7719     break;
7720
7721   default:
7722     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7723   }
7724
7725 }
7726
7727 /*-----------------------------------------------------------------*/
7728 /* movLeft2Result - move byte from left to result                  */
7729 /*-----------------------------------------------------------------*/
7730 static void movLeft2Result (operand *left, int offl,
7731                             operand *result, int offr)
7732 {
7733   char *l;
7734   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7735   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7736     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7737
7738     if (*l == '@' && (IS_AOP_PREG(result))) {
7739       pic16_emitcode("mov","a,%s",l);
7740       pic16_aopPut(AOP(result),"a",offr);
7741     } else {
7742       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7743       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7744     }
7745   }
7746 }
7747
7748 /*-----------------------------------------------------------------*/
7749 /* shiftL2Left2Result - shift left two bytes from left to result   */
7750 /*-----------------------------------------------------------------*/
7751 static void shiftL2Left2Result (operand *left, int offl,
7752                                 operand *result, int offr, int shCount)
7753 {
7754   int same = pic16_sameRegs(AOP(result), AOP(left));
7755   int i;
7756
7757   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7758
7759   if (same && (offl != offr)) { // shift bytes
7760     if (offr > offl) {
7761        for(i=1;i>-1;i--) {
7762          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7763          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7764        }
7765     } else { // just treat as different later on
7766                 same = 0;
7767     }
7768   }
7769
7770   if(same) {
7771     switch(shCount) {
7772     case 0:
7773       break;
7774     case 1:
7775     case 2:
7776     case 3:
7777
7778       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7779       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7780       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7781
7782       while(--shCount) {
7783                 emitCLRC;
7784                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7785                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7786       }
7787
7788       break;
7789     case 4:
7790     case 5:
7791       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7792       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7793       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7794       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7795       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7796       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7797       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7798       if(shCount >=5) {
7799                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7800                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7801       }
7802       break;
7803     case 6:
7804       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7805       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7806       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7807       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7808       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7809       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7810       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7811       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7812       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7813       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7814       break;
7815     case 7:
7816       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7817       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7818       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7819       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7820       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7821     }
7822
7823   } else {
7824     switch(shCount) {
7825     case 0:
7826       break;
7827     case 1:
7828     case 2:
7829     case 3:
7830       /* note, use a mov/add for the shift since the mov has a
7831          chance of getting optimized out */
7832       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7833       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7834       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7835       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7836       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7837
7838       while(--shCount) {
7839                 emitCLRC;
7840                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7841                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7842       }
7843       break;
7844
7845     case 4:
7846     case 5:
7847       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7848       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7849       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7850       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7851       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7852       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7853       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7854       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7855
7856
7857       if(shCount == 5) {
7858                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7859                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7860       }
7861       break;
7862     case 6:
7863       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7864       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7865       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7866       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7867
7868       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7869       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7870       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7871       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7872       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7873       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7874       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7875       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7876       break;
7877     case 7:
7878       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7879       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7880       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7881       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7882       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7883     }
7884   }
7885
7886 }
7887 /*-----------------------------------------------------------------*/
7888 /* shiftR2Left2Result - shift right two bytes from left to result  */
7889 /*-----------------------------------------------------------------*/
7890 static void shiftR2Left2Result (operand *left, int offl,
7891                                 operand *result, int offr,
7892                                 int shCount, int sign)
7893 {
7894   int same = pic16_sameRegs(AOP(result), AOP(left));
7895   int i;
7896   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7897
7898   if (same && (offl != offr)) { // shift right bytes
7899     if (offr < offl) {
7900        for(i=0;i<2;i++) {
7901          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7902          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7903        }
7904     } else { // just treat as different later on
7905                 same = 0;
7906     }
7907   }
7908
7909   switch(shCount) {
7910   case 0:
7911     break;
7912   case 1:
7913   case 2:
7914   case 3:
7915     if(sign)
7916       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7917     else
7918       emitCLRC;
7919
7920     if(same) {
7921       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7922       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7923     } else {
7924       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7925       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7926       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7927       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7928     }
7929
7930     while(--shCount) {
7931       if(sign)
7932                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7933       else
7934                 emitCLRC;
7935       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7936       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7937     }
7938     break;
7939   case 4:
7940   case 5:
7941     if(same) {
7942
7943       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7944       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7945       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7946
7947       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7948       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7949       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7950       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7951     } else {
7952       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7953       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7954       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7955
7956       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7957       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7958       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7959       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7960       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7961     }
7962
7963     if(shCount >=5) {
7964       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7965       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7966     }
7967
7968     if(sign) {
7969       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7970       pic16_emitpcode(POC_BTFSC, 
7971                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7972       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7973     }
7974
7975     break;
7976
7977   case 6:
7978     if(same) {
7979
7980       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7981       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7982
7983       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7984       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7985       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7986       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7987       if(sign) {
7988         pic16_emitpcode(POC_BTFSC, 
7989                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7990         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7991       }
7992       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7993       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7994       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7995       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7996     } else {
7997       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7998       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7999       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8000       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8001       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8002       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8003       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8004       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8005       if(sign) {
8006         pic16_emitpcode(POC_BTFSC, 
8007                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8008         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8009       }
8010       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8011       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8012
8013         
8014     }
8015
8016     break;
8017   case 7:
8018     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8019     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8020     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8021     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8022     if(sign) {
8023       emitSKPNC;
8024       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8025     } else 
8026       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8027   }
8028 }
8029
8030
8031 /*-----------------------------------------------------------------*/
8032 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8033 /*-----------------------------------------------------------------*/
8034 static void shiftLLeftOrResult (operand *left, int offl,
8035                                 operand *result, int offr, int shCount)
8036 {
8037     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8038
8039     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8040     /* shift left accumulator */
8041     AccLsh(shCount);
8042     /* or with result */
8043     /* back to result */
8044     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8045 }
8046
8047 /*-----------------------------------------------------------------*/
8048 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8049 /*-----------------------------------------------------------------*/
8050 static void shiftRLeftOrResult (operand *left, int offl,
8051                                 operand *result, int offr, int shCount)
8052 {
8053     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8054     
8055     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8056     /* shift right accumulator */
8057     AccRsh(shCount, 1);
8058     /* or with result */
8059     /* back to result */
8060     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8061 }
8062
8063 /*-----------------------------------------------------------------*/
8064 /* genlshOne - left shift a one byte quantity by known count       */
8065 /*-----------------------------------------------------------------*/
8066 static void genlshOne (operand *result, operand *left, int shCount)
8067 {       
8068     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8069     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8070 }
8071
8072 /*-----------------------------------------------------------------*/
8073 /* genlshTwo - left shift two bytes by known amount != 0           */
8074 /*-----------------------------------------------------------------*/
8075 static void genlshTwo (operand *result,operand *left, int shCount)
8076 {
8077     int size;
8078     
8079     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8080     size = pic16_getDataSize(result);
8081
8082     /* if shCount >= 8 */
8083     if (shCount >= 8) {
8084         shCount -= 8 ;
8085
8086         if (size > 1){
8087             if (shCount)
8088                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8089             else 
8090                 movLeft2Result(left, LSB, result, MSB16);
8091         }
8092         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8093     }
8094
8095     /*  1 <= shCount <= 7 */
8096     else {  
8097         if(size == 1)
8098             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8099         else 
8100             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8101     }
8102 }
8103
8104 /*-----------------------------------------------------------------*/
8105 /* shiftLLong - shift left one long from left to result            */
8106 /* offr = LSB or MSB16                                             */
8107 /*-----------------------------------------------------------------*/
8108 static void shiftLLong (operand *left, operand *result, int offr )
8109 {
8110     int size = AOP_SIZE(result);
8111     int same = pic16_sameRegs(AOP(left),AOP(result));
8112         int i;
8113
8114     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8115
8116         if (same && (offr == MSB16)) { //shift one byte
8117                 for(i=size-1;i>=MSB16;i--) {
8118                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8119                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8120                 }
8121         } else {
8122                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8123         }
8124         
8125     if (size >= LSB+offr ){
8126                 if (same) {
8127                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8128                 } else {
8129                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8130                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8131                 }
8132          }
8133
8134     if(size >= MSB16+offr){
8135                 if (same) {
8136                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8137                 } else {
8138                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8139                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8140                 }
8141     }
8142
8143     if(size >= MSB24+offr){
8144                 if (same) {
8145                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8146                 } else {
8147                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8148                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8149                 }
8150     }
8151
8152     if(size > MSB32+offr){
8153                 if (same) {
8154                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8155                 } else {
8156                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8157                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8158                 }
8159     }
8160     if(offr != LSB)
8161                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8162
8163 }
8164
8165 /*-----------------------------------------------------------------*/
8166 /* genlshFour - shift four byte by a known amount != 0             */
8167 /*-----------------------------------------------------------------*/
8168 static void genlshFour (operand *result, operand *left, int shCount)
8169 {
8170     int size;
8171
8172     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8173     size = AOP_SIZE(result);
8174
8175     /* if shifting more that 3 bytes */
8176     if (shCount >= 24 ) {
8177         shCount -= 24;
8178         if (shCount)
8179             /* lowest order of left goes to the highest
8180             order of the destination */
8181             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8182         else
8183             movLeft2Result(left, LSB, result, MSB32);
8184
8185                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8186                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8187                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8188
8189         return;
8190     }
8191
8192     /* more than two bytes */
8193     else if ( shCount >= 16 ) {
8194         /* lower order two bytes goes to higher order two bytes */
8195         shCount -= 16;
8196         /* if some more remaining */
8197         if (shCount)
8198             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8199         else {
8200             movLeft2Result(left, MSB16, result, MSB32);
8201             movLeft2Result(left, LSB, result, MSB24);
8202         }
8203                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8204                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8205         return;
8206     }    
8207
8208     /* if more than 1 byte */
8209     else if ( shCount >= 8 ) {
8210         /* lower order three bytes goes to higher order  three bytes */
8211         shCount -= 8;
8212         if(size == 2){
8213             if(shCount)
8214                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8215             else
8216                 movLeft2Result(left, LSB, result, MSB16);
8217         }
8218         else{   /* size = 4 */
8219             if(shCount == 0){
8220                 movLeft2Result(left, MSB24, result, MSB32);
8221                 movLeft2Result(left, MSB16, result, MSB24);
8222                 movLeft2Result(left, LSB, result, MSB16);
8223                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8224             }
8225             else if(shCount == 1)
8226                 shiftLLong(left, result, MSB16);
8227             else{
8228                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8229                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8230                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8231                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8232             }
8233         }
8234     }
8235
8236     /* 1 <= shCount <= 7 */
8237     else if(shCount <= 3)
8238     { 
8239         shiftLLong(left, result, LSB);
8240         while(--shCount >= 1)
8241             shiftLLong(result, result, LSB);
8242     }
8243     /* 3 <= shCount <= 7, optimize */
8244     else{
8245         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8246         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8247         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8248     }
8249 }
8250
8251 /*-----------------------------------------------------------------*/
8252 /* genLeftShiftLiteral - left shifting by known count              */
8253 /*-----------------------------------------------------------------*/
8254 static void genLeftShiftLiteral (operand *left,
8255                                  operand *right,
8256                                  operand *result,
8257                                  iCode *ic)
8258 {    
8259     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8260     int size;
8261
8262     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8263     pic16_freeAsmop(right,NULL,ic,TRUE);
8264
8265     pic16_aopOp(left,ic,FALSE);
8266     pic16_aopOp(result,ic,FALSE);
8267
8268     size = getSize(operandType(result));
8269
8270 #if VIEW_SIZE
8271     pic16_emitcode("; shift left ","result %d, left %d",size,
8272              AOP_SIZE(left));
8273 #endif
8274
8275     /* I suppose that the left size >= result size */
8276     if(shCount == 0){
8277         while(size--){
8278             movLeft2Result(left, size, result, size);
8279         }
8280     }
8281
8282     else if(shCount >= (size * 8))
8283         while(size--)
8284             pic16_aopPut(AOP(result),zero,size);
8285     else{
8286         switch (size) {
8287             case 1:
8288                 genlshOne (result,left,shCount);
8289                 break;
8290
8291             case 2:
8292             case 3:
8293                 genlshTwo (result,left,shCount);
8294                 break;
8295
8296             case 4:
8297                 genlshFour (result,left,shCount);
8298                 break;
8299         }
8300     }
8301     pic16_freeAsmop(left,NULL,ic,TRUE);
8302     pic16_freeAsmop(result,NULL,ic,TRUE);
8303 }
8304
8305 /*-----------------------------------------------------------------*
8306  * genMultiAsm - repeat assembly instruction for size of register.
8307  * if endian == 1, then the high byte (i.e base address + size of 
8308  * register) is used first else the low byte is used first;
8309  *-----------------------------------------------------------------*/
8310 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8311 {
8312
8313   int offset = 0;
8314
8315   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8316
8317   if(!reg)
8318     return;
8319
8320   if(!endian) {
8321     endian = 1;
8322   } else {
8323     endian = -1;
8324     offset = size-1;
8325   }
8326
8327   while(size--) {
8328     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8329     offset += endian;
8330   }
8331
8332 }
8333 /*-----------------------------------------------------------------*/
8334 /* genLeftShift - generates code for left shifting                 */
8335 /*-----------------------------------------------------------------*/
8336 static void genLeftShift (iCode *ic)
8337 {
8338   operand *left,*right, *result;
8339   int size, offset;
8340   char *l;
8341   symbol *tlbl , *tlbl1;
8342   pCodeOp *pctemp;
8343
8344   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8345
8346   right = IC_RIGHT(ic);
8347   left  = IC_LEFT(ic);
8348   result = IC_RESULT(ic);
8349
8350   pic16_aopOp(right,ic,FALSE);
8351
8352   /* if the shift count is known then do it 
8353      as efficiently as possible */
8354   if (AOP_TYPE(right) == AOP_LIT) {
8355     genLeftShiftLiteral (left,right,result,ic);
8356     return ;
8357   }
8358
8359   /* shift count is unknown then we have to form 
8360      a loop get the loop count in B : Note: we take
8361      only the lower order byte since shifting
8362      more that 32 bits make no sense anyway, ( the
8363      largest size of an object can be only 32 bits ) */  
8364
8365     
8366   pic16_aopOp(left,ic,FALSE);
8367   pic16_aopOp(result,ic,FALSE);
8368
8369   /* now move the left to the result if they are not the
8370      same */
8371   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8372       AOP_SIZE(result) > 1) {
8373
8374     size = AOP_SIZE(result);
8375     offset=0;
8376     while (size--) {
8377       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8378       if (*l == '@' && (IS_AOP_PREG(result))) {
8379
8380         pic16_emitcode("mov","a,%s",l);
8381         pic16_aopPut(AOP(result),"a",offset);
8382       } else {
8383         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8384         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8385         //pic16_aopPut(AOP(result),l,offset);
8386       }
8387       offset++;
8388     }
8389   }
8390
8391   size = AOP_SIZE(result);
8392
8393   /* if it is only one byte then */
8394   if (size == 1) {
8395     if(optimized_for_speed) {
8396       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8397       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8398       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8399       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8400       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8401       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8402       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8403       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8404       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8405       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8406       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8407       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8408     } else {
8409
8410       tlbl = newiTempLabel(NULL);
8411       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8412                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8413                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8414       }
8415
8416       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8417       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8418       pic16_emitpLabel(tlbl->key);
8419       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8420       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8421       emitSKPC;
8422       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8423     }
8424     goto release ;
8425   }
8426     
8427   if (pic16_sameRegs(AOP(left),AOP(result))) {
8428
8429     tlbl = newiTempLabel(NULL);
8430     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8431     genMultiAsm(POC_RRCF, result, size,1);
8432     pic16_emitpLabel(tlbl->key);
8433     genMultiAsm(POC_RLCF, result, size,0);
8434     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8435     emitSKPC;
8436     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8437     goto release;
8438   }
8439
8440   //tlbl = newiTempLabel(NULL);
8441   //offset = 0 ;   
8442   //tlbl1 = newiTempLabel(NULL);
8443
8444   //reAdjustPreg(AOP(result));    
8445     
8446   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8447   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8448   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8449   //MOVA(l);
8450   //pic16_emitcode("add","a,acc");         
8451   //pic16_aopPut(AOP(result),"a",offset++);
8452   //while (--size) {
8453   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8454   //  MOVA(l);
8455   //  pic16_emitcode("rlc","a");         
8456   //  pic16_aopPut(AOP(result),"a",offset++);
8457   //}
8458   //reAdjustPreg(AOP(result));
8459
8460   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8461   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8462
8463
8464   tlbl = newiTempLabel(NULL);
8465   tlbl1= newiTempLabel(NULL);
8466
8467   size = AOP_SIZE(result);
8468   offset = 1;
8469
8470   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8471
8472   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8473
8474   /* offset should be 0, 1 or 3 */
8475   
8476   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8477   emitSKPNZ;
8478   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8479
8480   pic16_emitpcode(POC_MOVWF, pctemp);
8481
8482
8483   pic16_emitpLabel(tlbl->key);
8484
8485   emitCLRC;
8486   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8487   while(--size)
8488     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8489
8490   pic16_emitpcode(POC_DECFSZ,  pctemp);
8491   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8492   pic16_emitpLabel(tlbl1->key);
8493
8494   pic16_popReleaseTempReg(pctemp);
8495
8496
8497  release:
8498   pic16_freeAsmop (right,NULL,ic,TRUE);
8499   pic16_freeAsmop(left,NULL,ic,TRUE);
8500   pic16_freeAsmop(result,NULL,ic,TRUE);
8501 }
8502
8503 /*-----------------------------------------------------------------*/
8504 /* genrshOne - right shift a one byte quantity by known count      */
8505 /*-----------------------------------------------------------------*/
8506 static void genrshOne (operand *result, operand *left,
8507                        int shCount, int sign)
8508 {
8509     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8510     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8511 }
8512
8513 /*-----------------------------------------------------------------*/
8514 /* genrshTwo - right shift two bytes by known amount != 0          */
8515 /*-----------------------------------------------------------------*/
8516 static void genrshTwo (operand *result,operand *left,
8517                        int shCount, int sign)
8518 {
8519   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8520   /* if shCount >= 8 */
8521   if (shCount >= 8) {
8522     shCount -= 8 ;
8523     if (shCount)
8524       shiftR1Left2Result(left, MSB16, result, LSB,
8525                          shCount, sign);
8526     else
8527       movLeft2Result(left, MSB16, result, LSB);
8528
8529     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8530
8531     if(sign) {
8532       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8533       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8534     }
8535   }
8536
8537   /*  1 <= shCount <= 7 */
8538   else
8539     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8540 }
8541
8542 /*-----------------------------------------------------------------*/
8543 /* shiftRLong - shift right one long from left to result           */
8544 /* offl = LSB or MSB16                                             */
8545 /*-----------------------------------------------------------------*/
8546 static void shiftRLong (operand *left, int offl,
8547                         operand *result, int sign)
8548 {
8549     int size = AOP_SIZE(result);
8550     int same = pic16_sameRegs(AOP(left),AOP(result));
8551     int i;
8552     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8553
8554         if (same && (offl == MSB16)) { //shift one byte right
8555                 for(i=MSB16;i<size;i++) {
8556                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8557                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8558                 }
8559         }
8560
8561     if(sign)
8562                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8563         else
8564                 emitCLRC;
8565
8566         if (same) {
8567                 if (offl == LSB)
8568                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8569         } else {
8570         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8571         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8572         }
8573
8574     if(offl == MSB16) {
8575         /* add sign of "a" */
8576         pic16_addSign(result, MSB32, sign);
8577         }
8578
8579         if (same) {
8580         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8581         } else {
8582         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8583         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8584         }
8585         
8586         if (same) {
8587         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8588         } else {
8589         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8590         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8591         }
8592
8593         if (same) {
8594         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8595         } else {
8596         if(offl == LSB){
8597                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8598                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8599         }
8600         }
8601 }
8602
8603 /*-----------------------------------------------------------------*/
8604 /* genrshFour - shift four byte by a known amount != 0             */
8605 /*-----------------------------------------------------------------*/
8606 static void genrshFour (operand *result, operand *left,
8607                         int shCount, int sign)
8608 {
8609   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8610   /* if shifting more that 3 bytes */
8611   if(shCount >= 24 ) {
8612     shCount -= 24;
8613     if(shCount)
8614       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8615     else
8616       movLeft2Result(left, MSB32, result, LSB);
8617
8618     pic16_addSign(result, MSB16, sign);
8619   }
8620   else if(shCount >= 16){
8621     shCount -= 16;
8622     if(shCount)
8623       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8624     else{
8625       movLeft2Result(left, MSB24, result, LSB);
8626       movLeft2Result(left, MSB32, result, MSB16);
8627     }
8628     pic16_addSign(result, MSB24, sign);
8629   }
8630   else if(shCount >= 8){
8631     shCount -= 8;
8632     if(shCount == 1)
8633       shiftRLong(left, MSB16, result, sign);
8634     else if(shCount == 0){
8635       movLeft2Result(left, MSB16, result, LSB);
8636       movLeft2Result(left, MSB24, result, MSB16);
8637       movLeft2Result(left, MSB32, result, MSB24);
8638       pic16_addSign(result, MSB32, sign);
8639     }
8640     else{ //shcount >= 2
8641       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8642       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8643       /* the last shift is signed */
8644       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8645       pic16_addSign(result, MSB32, sign);
8646     }
8647   }
8648   else{   /* 1 <= shCount <= 7 */
8649     if(shCount <= 2){
8650       shiftRLong(left, LSB, result, sign);
8651       if(shCount == 2)
8652         shiftRLong(result, LSB, result, sign);
8653     }
8654     else{
8655       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8656       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8657       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8658     }
8659   }
8660 }
8661
8662 /*-----------------------------------------------------------------*/
8663 /* genRightShiftLiteral - right shifting by known count            */
8664 /*-----------------------------------------------------------------*/
8665 static void genRightShiftLiteral (operand *left,
8666                                   operand *right,
8667                                   operand *result,
8668                                   iCode *ic,
8669                                   int sign)
8670 {    
8671   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8672   int lsize,res_size;
8673
8674   pic16_freeAsmop(right,NULL,ic,TRUE);
8675
8676   pic16_aopOp(left,ic,FALSE);
8677   pic16_aopOp(result,ic,FALSE);
8678
8679   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8680
8681 #if VIEW_SIZE
8682   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8683                  AOP_SIZE(left));
8684 #endif
8685
8686   lsize = pic16_getDataSize(left);
8687   res_size = pic16_getDataSize(result);
8688   /* test the LEFT size !!! */
8689
8690   /* I suppose that the left size >= result size */
8691   if(shCount == 0){
8692     while(res_size--)
8693       movLeft2Result(left, lsize, result, res_size);
8694   }
8695
8696   else if(shCount >= (lsize * 8)){
8697
8698     if(res_size == 1) {
8699       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8700       if(sign) {
8701         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8702         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8703       }
8704     } else {
8705
8706       if(sign) {
8707         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8708         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8709         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8710         while(res_size--)
8711           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8712
8713       } else {
8714
8715         while(res_size--)
8716           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8717       }
8718     }
8719   } else {
8720
8721     switch (res_size) {
8722     case 1:
8723       genrshOne (result,left,shCount,sign);
8724       break;
8725
8726     case 2:
8727       genrshTwo (result,left,shCount,sign);
8728       break;
8729
8730     case 4:
8731       genrshFour (result,left,shCount,sign);
8732       break;
8733     default :
8734       break;
8735     }
8736
8737   }
8738
8739   pic16_freeAsmop(left,NULL,ic,TRUE);
8740   pic16_freeAsmop(result,NULL,ic,TRUE);
8741 }
8742
8743 /*-----------------------------------------------------------------*/
8744 /* genSignedRightShift - right shift of signed number              */
8745 /*-----------------------------------------------------------------*/
8746 static void genSignedRightShift (iCode *ic)
8747 {
8748   operand *right, *left, *result;
8749   int size, offset;
8750   //  char *l;
8751   symbol *tlbl, *tlbl1 ;
8752   pCodeOp *pctemp;
8753
8754   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8755
8756   /* we do it the hard way put the shift count in b
8757      and loop thru preserving the sign */
8758   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8759
8760   right = IC_RIGHT(ic);
8761   left  = IC_LEFT(ic);
8762   result = IC_RESULT(ic);
8763
8764   pic16_aopOp(right,ic,FALSE);  
8765   pic16_aopOp(left,ic,FALSE);
8766   pic16_aopOp(result,ic,FALSE);
8767
8768
8769   if ( AOP_TYPE(right) == AOP_LIT) {
8770     genRightShiftLiteral (left,right,result,ic,1);
8771     return ;
8772   }
8773   /* shift count is unknown then we have to form 
8774      a loop get the loop count in B : Note: we take
8775      only the lower order byte since shifting
8776      more that 32 bits make no sense anyway, ( the
8777      largest size of an object can be only 32 bits ) */  
8778
8779   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8780   //pic16_emitcode("inc","b");
8781   //pic16_freeAsmop (right,NULL,ic,TRUE);
8782   //pic16_aopOp(left,ic,FALSE);
8783   //pic16_aopOp(result,ic,FALSE);
8784
8785   /* now move the left to the result if they are not the
8786      same */
8787   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8788       AOP_SIZE(result) > 1) {
8789
8790     size = AOP_SIZE(result);
8791     offset=0;
8792     while (size--) { 
8793       /*
8794         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8795         if (*l == '@' && IS_AOP_PREG(result)) {
8796
8797         pic16_emitcode("mov","a,%s",l);
8798         pic16_aopPut(AOP(result),"a",offset);
8799         } else
8800         pic16_aopPut(AOP(result),l,offset);
8801       */
8802       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8803       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8804
8805       offset++;
8806     }
8807   }
8808
8809   /* mov the highest order bit to OVR */    
8810   tlbl = newiTempLabel(NULL);
8811   tlbl1= newiTempLabel(NULL);
8812
8813   size = AOP_SIZE(result);
8814   offset = size - 1;
8815
8816   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8817
8818   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8819
8820   /* offset should be 0, 1 or 3 */
8821   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8822   emitSKPNZ;
8823   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8824
8825   pic16_emitpcode(POC_MOVWF, pctemp);
8826
8827
8828   pic16_emitpLabel(tlbl->key);
8829
8830   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8831   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8832
8833   while(--size) {
8834     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8835   }
8836
8837   pic16_emitpcode(POC_DECFSZ,  pctemp);
8838   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8839   pic16_emitpLabel(tlbl1->key);
8840
8841   pic16_popReleaseTempReg(pctemp);
8842 #if 0
8843   size = AOP_SIZE(result);
8844   offset = size - 1;
8845   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8846   pic16_emitcode("rlc","a");
8847   pic16_emitcode("mov","ov,c");
8848   /* if it is only one byte then */
8849   if (size == 1) {
8850     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8851     MOVA(l);
8852     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8853     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8854     pic16_emitcode("mov","c,ov");
8855     pic16_emitcode("rrc","a");
8856     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8857     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8858     pic16_aopPut(AOP(result),"a",0);
8859     goto release ;
8860   }
8861
8862   reAdjustPreg(AOP(result));
8863   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8864   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8865   pic16_emitcode("mov","c,ov");
8866   while (size--) {
8867     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8868     MOVA(l);
8869     pic16_emitcode("rrc","a");         
8870     pic16_aopPut(AOP(result),"a",offset--);
8871   }
8872   reAdjustPreg(AOP(result));
8873   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8874   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8875
8876  release:
8877 #endif
8878
8879   pic16_freeAsmop(left,NULL,ic,TRUE);
8880   pic16_freeAsmop(result,NULL,ic,TRUE);
8881   pic16_freeAsmop(right,NULL,ic,TRUE);
8882 }
8883
8884 /*-----------------------------------------------------------------*/
8885 /* genRightShift - generate code for right shifting                */
8886 /*-----------------------------------------------------------------*/
8887 static void genRightShift (iCode *ic)
8888 {
8889     operand *right, *left, *result;
8890     sym_link *letype ;
8891     int size, offset;
8892     char *l;
8893     symbol *tlbl, *tlbl1 ;
8894
8895     /* if signed then we do it the hard way preserve the
8896     sign bit moving it inwards */
8897     letype = getSpec(operandType(IC_LEFT(ic)));
8898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8899
8900     if (!SPEC_USIGN(letype)) {
8901         genSignedRightShift (ic);
8902         return ;
8903     }
8904
8905     /* signed & unsigned types are treated the same : i.e. the
8906     signed is NOT propagated inwards : quoting from the
8907     ANSI - standard : "for E1 >> E2, is equivalent to division
8908     by 2**E2 if unsigned or if it has a non-negative value,
8909     otherwise the result is implementation defined ", MY definition
8910     is that the sign does not get propagated */
8911
8912     right = IC_RIGHT(ic);
8913     left  = IC_LEFT(ic);
8914     result = IC_RESULT(ic);
8915
8916     pic16_aopOp(right,ic,FALSE);
8917
8918     /* if the shift count is known then do it 
8919     as efficiently as possible */
8920     if (AOP_TYPE(right) == AOP_LIT) {
8921         genRightShiftLiteral (left,right,result,ic, 0);
8922         return ;
8923     }
8924
8925     /* shift count is unknown then we have to form 
8926     a loop get the loop count in B : Note: we take
8927     only the lower order byte since shifting
8928     more that 32 bits make no sense anyway, ( the
8929     largest size of an object can be only 32 bits ) */  
8930
8931     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8932     pic16_emitcode("inc","b");
8933     pic16_aopOp(left,ic,FALSE);
8934     pic16_aopOp(result,ic,FALSE);
8935
8936     /* now move the left to the result if they are not the
8937     same */
8938     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8939         AOP_SIZE(result) > 1) {
8940
8941         size = AOP_SIZE(result);
8942         offset=0;
8943         while (size--) {
8944             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8945             if (*l == '@' && IS_AOP_PREG(result)) {
8946
8947                 pic16_emitcode("mov","a,%s",l);
8948                 pic16_aopPut(AOP(result),"a",offset);
8949             } else
8950                 pic16_aopPut(AOP(result),l,offset);
8951             offset++;
8952         }
8953     }
8954
8955     tlbl = newiTempLabel(NULL);
8956     tlbl1= newiTempLabel(NULL);
8957     size = AOP_SIZE(result);
8958     offset = size - 1;
8959
8960     /* if it is only one byte then */
8961     if (size == 1) {
8962
8963       tlbl = newiTempLabel(NULL);
8964       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8965         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8966         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8967       }
8968
8969       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8970       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8971       pic16_emitpLabel(tlbl->key);
8972       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8973       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8974       emitSKPC;
8975       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8976
8977       goto release ;
8978     }
8979
8980     reAdjustPreg(AOP(result));
8981     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8982     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8983     CLRC;
8984     while (size--) {
8985         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8986         MOVA(l);
8987         pic16_emitcode("rrc","a");         
8988         pic16_aopPut(AOP(result),"a",offset--);
8989     }
8990     reAdjustPreg(AOP(result));
8991
8992     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8993     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8994
8995 release:
8996     pic16_freeAsmop(left,NULL,ic,TRUE);
8997     pic16_freeAsmop (right,NULL,ic,TRUE);
8998     pic16_freeAsmop(result,NULL,ic,TRUE);
8999 }
9000
9001 /*-----------------------------------------------------------------*/
9002 /* genUnpackBits - generates code for unpacking bits               */
9003 /*-----------------------------------------------------------------*/
9004 static void genUnpackBits (operand *result, char *rname, int ptype)
9005 {    
9006     int shCnt ;
9007     int rlen = 0 ;
9008     sym_link *etype;
9009     int offset = 0 ;
9010
9011         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9012         etype = getSpec(operandType(result));
9013
9014         /* read the first byte  */
9015         switch (ptype) {
9016                 case POINTER:
9017                 case IPOINTER:
9018                 case PPOINTER:
9019                 case FPOINTER:
9020                 case GPOINTER:
9021                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9022                         break;
9023                 case CPOINTER:
9024                         pic16_emitcode("clr","a");
9025                         pic16_emitcode("movc","a","@a+dptr");
9026                         break;
9027         }
9028         
9029
9030         /* if we have bitdisplacement then it fits   */
9031         /* into this byte completely or if length is */
9032         /* less than a byte                          */
9033         if ((shCnt = SPEC_BSTR(etype)) || 
9034                 (SPEC_BLEN(etype) <= 8))  {
9035
9036                 /* shift right acc */
9037                 AccRsh(shCnt, 0);
9038
9039                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9040                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9041
9042 /* VR -- normally I would use the following, but since we use the hack,
9043  * to avoid the masking from AccRsh, why not mask it right now? */
9044
9045 /*
9046                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9047 */
9048
9049                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9050           return ;
9051         }
9052
9053
9054
9055         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9056         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9057         exit(-1);
9058
9059     /* bit field did not fit in a byte  */
9060     rlen = SPEC_BLEN(etype) - 8;
9061     pic16_aopPut(AOP(result),"a",offset++);
9062
9063     while (1)  {
9064
9065         switch (ptype) {
9066         case POINTER:
9067         case IPOINTER:
9068             pic16_emitcode("inc","%s",rname);
9069             pic16_emitcode("mov","a,@%s",rname);
9070             break;
9071             
9072         case PPOINTER:
9073             pic16_emitcode("inc","%s",rname);
9074             pic16_emitcode("movx","a,@%s",rname);
9075             break;
9076
9077         case FPOINTER:
9078             pic16_emitcode("inc","dptr");
9079             pic16_emitcode("movx","a,@dptr");
9080             break;
9081             
9082         case CPOINTER:
9083             pic16_emitcode("clr","a");
9084             pic16_emitcode("inc","dptr");
9085             pic16_emitcode("movc","a","@a+dptr");
9086             break;
9087             
9088         case GPOINTER:
9089             pic16_emitcode("inc","dptr");
9090             pic16_emitcode("lcall","__gptrget");
9091             break;
9092         }
9093
9094         rlen -= 8;            
9095         /* if we are done */
9096         if ( rlen <= 0 )
9097             break ;
9098         
9099         pic16_aopPut(AOP(result),"a",offset++);
9100                               
9101     }
9102     
9103     if (rlen) {
9104         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9105         pic16_aopPut(AOP(result),"a",offset);          
9106     }
9107     
9108     return ;
9109 }
9110
9111
9112 static void genDataPointerGet(operand *left,
9113                               operand *result,
9114                               iCode *ic)
9115 {
9116   int size, offset = 0, leoffset=0 ;
9117
9118         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9119         pic16_aopOp(result, ic, FALSE);
9120
9121         size = AOP_SIZE(result);
9122 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9123
9124
9125 #if 0
9126         /* The following tests may save a redudant movff instruction when
9127          * accessing unions */
9128          
9129         /* if they are the same */
9130         if (operandsEqu (left, result)) {
9131                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9132                 goto release;
9133         }
9134 #endif
9135
9136 #if 0
9137         /* if they are the same registers */
9138         if (pic16_sameRegs(AOP(left),AOP(result))) {
9139                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9140                 goto release;
9141         }
9142 #endif
9143
9144 #if 1
9145         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9146                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9147                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9148                 goto release;
9149         }
9150 #endif
9151
9152
9153 #if 0
9154         if ( AOP_TYPE(left) == AOP_PCODE) {
9155                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9156                                 AOP(left)->aopu.pcop->name,
9157                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9158                                 PCOR(AOP(left)->aopu.pcop)->instance:
9159                                 PCOI(AOP(left)->aopu.pcop)->offset);
9160         }
9161 #endif
9162
9163         if(AOP(left)->aopu.pcop->type == PO_DIR)
9164                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9165
9166         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9167
9168         while (size--) {
9169                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9170                 
9171                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9172                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9173                         mov2w(AOP(left), offset); // patch 8
9174                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9175                 } else {
9176                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9177                                 pic16_popGet(AOP(left), offset), //patch 8
9178                                 pic16_popGet(AOP(result), offset)));
9179                 }
9180
9181                 offset++;
9182                 leoffset++;
9183         }
9184
9185 release:
9186     pic16_freeAsmop(result,NULL,ic,TRUE);
9187 }
9188
9189 void pic16_loadFSR0(operand *op)
9190 {
9191         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9192 }
9193
9194
9195 /*-----------------------------------------------------------------*/
9196 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9197 /*-----------------------------------------------------------------*/
9198 static void genNearPointerGet (operand *left, 
9199                                operand *result, 
9200                                iCode *ic)
9201 {
9202     asmop *aop = NULL;
9203     //regs *preg = NULL ;
9204     sym_link *rtype, *retype;
9205     sym_link *ltype = operandType(left);    
9206
9207         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9208         rtype = operandType(result);
9209         retype= getSpec(rtype);
9210     
9211         pic16_aopOp(left,ic,FALSE);
9212
9213 //      pic16_DumpOp("(left)",left);
9214 //      pic16_DumpOp("(result)",result);
9215
9216         /* if left is rematerialisable and
9217          * result is not bit variable type and
9218          * the left is pointer to data space i.e
9219          * lower 128 bytes of space */
9220         if (AOP_TYPE(left) == AOP_PCODE
9221                 && !IS_BITFIELD(retype)
9222                 && DCL_TYPE(ltype) == POINTER) {
9223
9224                 genDataPointerGet (left,result,ic);
9225                 pic16_freeAsmop(left, NULL, ic, TRUE);
9226           return ;
9227         }
9228     
9229         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9230
9231         /* if the value is already in a pointer register
9232          * then don't need anything more */
9233         if (!AOP_INPREG(AOP(left))) {
9234                 /* otherwise get a free pointer register */
9235                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9236                 
9237                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9238                 if( (AOP_TYPE(left) == AOP_PCODE) 
9239                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9240                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9241                 {
9242                         pic16_loadFSR0( left );  // patch 10
9243                 } else {
9244                         // set up FSR0 with address from left
9245                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9246                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9247                 }
9248         }
9249 //       else
9250 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9251     
9252         pic16_aopOp (result,ic,FALSE);
9253     
9254       /* if bitfield then unpack the bits */
9255     if (IS_BITFIELD(retype)) 
9256         genUnpackBits (result, NULL, POINTER);
9257     else {
9258         /* we have can just get the values */
9259       int size = AOP_SIZE(result);
9260       int offset = 0;   
9261         
9262       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9263
9264
9265         /* fsr0 is loaded already -- VR */
9266 //      pic16_loadFSR0( left );
9267
9268 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9269 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9270       while(size--) {
9271
9272         if(size) {
9273                 pic16_emitpcode(POC_MOVFF,
9274                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9275                                 pic16_popGet(AOP(result), offset++)));
9276         } else {
9277                 pic16_emitpcode(POC_MOVFF,
9278                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9279                                 pic16_popGet(AOP(result), offset++)));
9280         }
9281       }
9282 #if 0
9283 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9284 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9285         if(size)
9286           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9287 #endif
9288 /*
9289         while (size--) {
9290             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9291
9292                 pic16_emitcode("mov","a,@%s",rname);
9293                 pic16_aopPut(AOP(result),"a",offset);
9294             } else {
9295                 sprintf(buffer,"@%s",rname);
9296                 pic16_aopPut(AOP(result),buffer,offset);
9297             }
9298             offset++ ;
9299             if (size)
9300                 pic16_emitcode("inc","%s",rname);
9301         }
9302 */
9303     }
9304
9305     /* now some housekeeping stuff */
9306     if (aop) {
9307         /* we had to allocate for this iCode */
9308     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9309         pic16_freeAsmop(NULL,aop,ic,TRUE);
9310     } else { 
9311         /* we did not allocate which means left
9312            already in a pointer register, then
9313            if size > 0 && this could be used again
9314            we have to point it back to where it 
9315            belongs */
9316     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9317         if (AOP_SIZE(result) > 1 &&
9318             !OP_SYMBOL(left)->remat &&
9319             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9320               ic->depth )) {
9321 //          int size = AOP_SIZE(result) - 1;
9322 //          while (size--)
9323 //              pic16_emitcode("dec","%s",rname);
9324         }
9325     }
9326
9327     /* done */
9328     pic16_freeAsmop(left,NULL,ic,TRUE);
9329     pic16_freeAsmop(result,NULL,ic,TRUE);
9330      
9331 }
9332
9333 /*-----------------------------------------------------------------*/
9334 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9335 /*-----------------------------------------------------------------*/
9336 static void genPagedPointerGet (operand *left, 
9337                                operand *result, 
9338                                iCode *ic)
9339 {
9340     asmop *aop = NULL;
9341     regs *preg = NULL ;
9342     char *rname ;
9343     sym_link *rtype, *retype;    
9344
9345     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9346
9347     rtype = operandType(result);
9348     retype= getSpec(rtype);
9349     
9350     pic16_aopOp(left,ic,FALSE);
9351
9352   /* if the value is already in a pointer register
9353        then don't need anything more */
9354     if (!AOP_INPREG(AOP(left))) {
9355         /* otherwise get a free pointer register */
9356         aop = newAsmop(0);
9357         preg = getFreePtr(ic,&aop,FALSE);
9358         pic16_emitcode("mov","%s,%s",
9359                 preg->name,
9360                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9361         rname = preg->name ;
9362     } else
9363         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9364     
9365     pic16_freeAsmop(left,NULL,ic,TRUE);
9366     pic16_aopOp (result,ic,FALSE);
9367
9368     /* if bitfield then unpack the bits */
9369     if (IS_BITFIELD(retype)) 
9370         genUnpackBits (result,rname,PPOINTER);
9371     else {
9372         /* we have can just get the values */
9373         int size = AOP_SIZE(result);
9374         int offset = 0 ;        
9375         
9376         while (size--) {
9377             
9378             pic16_emitcode("movx","a,@%s",rname);
9379             pic16_aopPut(AOP(result),"a",offset);
9380             
9381             offset++ ;
9382             
9383             if (size)
9384                 pic16_emitcode("inc","%s",rname);
9385         }
9386     }
9387
9388     /* now some housekeeping stuff */
9389     if (aop) {
9390         /* we had to allocate for this iCode */
9391         pic16_freeAsmop(NULL,aop,ic,TRUE);
9392     } else { 
9393         /* we did not allocate which means left
9394            already in a pointer register, then
9395            if size > 0 && this could be used again
9396            we have to point it back to where it 
9397            belongs */
9398         if (AOP_SIZE(result) > 1 &&
9399             !OP_SYMBOL(left)->remat &&
9400             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9401               ic->depth )) {
9402             int size = AOP_SIZE(result) - 1;
9403             while (size--)
9404                 pic16_emitcode("dec","%s",rname);
9405         }
9406     }
9407
9408     /* done */
9409     pic16_freeAsmop(result,NULL,ic,TRUE);
9410     
9411         
9412 }
9413
9414 /*-----------------------------------------------------------------*/
9415 /* genFarPointerGet - gget value from far space                    */
9416 /*-----------------------------------------------------------------*/
9417 static void genFarPointerGet (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",FPOINTER);
9449     else {
9450         size = AOP_SIZE(result);
9451         offset = 0 ;
9452
9453         while (size--) {
9454             pic16_emitcode("movx","a,@dptr");
9455             pic16_aopPut(AOP(result),"a",offset++);
9456             if (size)
9457                 pic16_emitcode("inc","dptr");
9458         }
9459     }
9460
9461     pic16_freeAsmop(result,NULL,ic,TRUE);
9462 }
9463 #if 0
9464 /*-----------------------------------------------------------------*/
9465 /* genCodePointerGet - get value from code space                  */
9466 /*-----------------------------------------------------------------*/
9467 static void genCodePointerGet (operand *left,
9468                                 operand *result, iCode *ic)
9469 {
9470     int size, offset ;
9471     sym_link *retype = getSpec(operandType(result));
9472
9473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9474
9475     pic16_aopOp(left,ic,FALSE);
9476
9477     /* if the operand is already in dptr 
9478     then we do nothing else we move the value to dptr */
9479     if (AOP_TYPE(left) != AOP_STR) {
9480         /* if this is remateriazable */
9481         if (AOP_TYPE(left) == AOP_IMMD)
9482             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9483         else { /* we need to get it byte by byte */
9484             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9485             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9486             if (options.model == MODEL_FLAT24)
9487             {
9488                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9489             }
9490         }
9491     }
9492     /* so dptr know contains the address */
9493     pic16_freeAsmop(left,NULL,ic,TRUE);
9494     pic16_aopOp(result,ic,FALSE);
9495
9496     /* if bit then unpack */
9497     if (IS_BITFIELD(retype)) 
9498         genUnpackBits(result,"dptr",CPOINTER);
9499     else {
9500         size = AOP_SIZE(result);
9501         offset = 0 ;
9502
9503         while (size--) {
9504             pic16_emitcode("clr","a");
9505             pic16_emitcode("movc","a,@a+dptr");
9506             pic16_aopPut(AOP(result),"a",offset++);
9507             if (size)
9508                 pic16_emitcode("inc","dptr");
9509         }
9510     }
9511
9512     pic16_freeAsmop(result,NULL,ic,TRUE);
9513 }
9514 #endif
9515 /*-----------------------------------------------------------------*/
9516 /* genGenPointerGet - gget value from generic pointer space        */
9517 /*-----------------------------------------------------------------*/
9518 static void genGenPointerGet (operand *left,
9519                               operand *result, iCode *ic)
9520 {
9521   int size, offset, lit;
9522   sym_link *retype = getSpec(operandType(result));
9523
9524         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9525         pic16_aopOp(left,ic,FALSE);
9526         pic16_aopOp(result,ic,FALSE);
9527         size = AOP_SIZE(result);
9528
9529         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9530
9531         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9532
9533                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9534                 // load FSR0 from immediate
9535                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9536
9537 //              pic16_loadFSR0( left );
9538
9539                 offset = 0;
9540                 while(size--) {
9541                         if(size) {
9542                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9543                         } else {
9544                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9545                         }
9546                         offset++;
9547                 }
9548                 goto release;
9549
9550         }
9551         else { /* we need to get it byte by byte */
9552                 // set up FSR0 with address from left
9553                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9554                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9555
9556                 offset = 0 ;
9557
9558                 while(size--) {
9559                         if(size) {
9560                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9561                         } else {
9562                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9563                         }
9564                         offset++;
9565                 }
9566                 goto release;
9567         }
9568
9569   /* if bit then unpack */
9570         if (IS_BITFIELD(retype)) 
9571                 genUnpackBits(result,"BAD",GPOINTER);
9572
9573         release:
9574         pic16_freeAsmop(left,NULL,ic,TRUE);
9575         pic16_freeAsmop(result,NULL,ic,TRUE);
9576
9577 }
9578
9579 /*-----------------------------------------------------------------*/
9580 /* genConstPointerGet - get value from const generic pointer space */
9581 /*-----------------------------------------------------------------*/
9582 static void genConstPointerGet (operand *left,
9583                                 operand *result, iCode *ic)
9584 {
9585   //sym_link *retype = getSpec(operandType(result));
9586   // symbol *albl = newiTempLabel(NULL);        // patch 15
9587   // symbol *blbl = newiTempLabel(NULL);        //
9588   // PIC_OPCODE poc;                            // patch 15
9589   int size;
9590   int offset = 0;
9591
9592   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9593   pic16_aopOp(left,ic,FALSE);
9594   pic16_aopOp(result,ic,TRUE);
9595   size = AOP_SIZE(result);
9596
9597   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9598
9599   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9600 #if 0                                                                   // patch 15
9601   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9602   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9603   pic16_emitpLabel(albl->key);
9604
9605   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9606     
9607   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9608   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9609   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9610   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9611   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9612
9613   pic16_emitpLabel(blbl->key);
9614
9615   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9616 #endif                                                                  // patch 15
9617
9618
9619   // set up table pointer
9620   if( (AOP_TYPE(left) == AOP_PCODE) 
9621       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9622           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9623     {
9624       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9625       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9626       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9627       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9628       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9629       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9630     }
9631   else
9632     {
9633       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9634       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9635       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9636     }
9637
9638
9639   while(size--)
9640     {
9641       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9642       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9643       offset++;
9644     }
9645     
9646   pic16_freeAsmop(left,NULL,ic,TRUE);
9647   pic16_freeAsmop(result,NULL,ic,TRUE);
9648
9649 }
9650
9651
9652 /*-----------------------------------------------------------------*/
9653 /* genPointerGet - generate code for pointer get                   */
9654 /*-----------------------------------------------------------------*/
9655 static void genPointerGet (iCode *ic)
9656 {
9657     operand *left, *result ;
9658     sym_link *type, *etype;
9659     int p_type;
9660
9661     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9662
9663     left = IC_LEFT(ic);
9664     result = IC_RESULT(ic) ;
9665
9666     /* depending on the type of pointer we need to
9667     move it to the correct pointer register */
9668     type = operandType(left);
9669     etype = getSpec(type);
9670
9671 #if 0
9672     if (IS_PTR_CONST(type))
9673 #else
9674     if (IS_CODEPTR(type))
9675 #endif
9676       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9677
9678     /* if left is of type of pointer then it is simple */
9679     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9680         p_type = DCL_TYPE(type);
9681     else {
9682         /* we have to go by the storage class */
9683         p_type = PTR_TYPE(SPEC_OCLS(etype));
9684
9685         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9686
9687         if (SPEC_OCLS(etype)->codesp ) {
9688           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9689           //p_type = CPOINTER ; 
9690         }
9691         else
9692             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9693               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9694                /*p_type = FPOINTER ;*/ 
9695             else
9696                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9697                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9698 /*                  p_type = PPOINTER; */
9699                 else
9700                     if (SPEC_OCLS(etype) == idata )
9701                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9702 /*                      p_type = IPOINTER; */
9703                     else
9704                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9705 /*                      p_type = POINTER ; */
9706     }
9707
9708     /* now that we have the pointer type we assign
9709     the pointer values */
9710     switch (p_type) {
9711
9712     case POINTER:       
9713     case IPOINTER:
9714         genNearPointerGet (left,result,ic);
9715         break;
9716
9717     case PPOINTER:
9718         genPagedPointerGet(left,result,ic);
9719         break;
9720
9721     case FPOINTER:
9722         genFarPointerGet (left,result,ic);
9723         break;
9724
9725     case CPOINTER:
9726         genConstPointerGet (left,result,ic);
9727         //pic16_emitcodePointerGet (left,result,ic);
9728         break;
9729
9730     case GPOINTER:
9731 #if 0
9732       if (IS_PTR_CONST(type))
9733         genConstPointerGet (left,result,ic);
9734       else
9735 #endif
9736         genGenPointerGet (left,result,ic);
9737       break;
9738
9739     default:
9740       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9741               "genPointerGet: illegal pointer type");
9742     
9743     }
9744
9745 }
9746
9747 /*-----------------------------------------------------------------*/
9748 /* genPackBits - generates code for packed bit storage             */
9749 /*-----------------------------------------------------------------*/
9750 static void genPackBits (sym_link    *etype ,
9751                          operand *right ,
9752                          char *rname, int p_type)
9753 {
9754   int shCnt = 0 ;
9755   int offset = 0  ;
9756   int rLen = 0 ;
9757   int blen, bstr ;   
9758   char *l ;
9759
9760         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9761         blen = SPEC_BLEN(etype);
9762         bstr = SPEC_BSTR(etype);
9763
9764         if(AOP_TYPE(right) == AOP_LIT) {
9765                 if((blen == 1) && (bstr < 8)) {
9766                   unsigned long lit;
9767                         /* it is a single bit, so use the appropriate bit instructions */
9768
9769                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9770
9771                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9772 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9773                         if(lit) {
9774                                 pic16_emitpcode(POC_BSF,
9775                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9776                         } else {
9777                                 pic16_emitpcode(POC_BCF,
9778                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9779                         }
9780         
9781                   return;
9782                 }
9783
9784                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9785                 offset++;
9786         } else
9787                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9788
9789         /* if the bit lenth is less than or    */
9790         /* it exactly fits a byte then         */
9791         if((shCnt=SPEC_BSTR(etype))
9792                 || SPEC_BLEN(etype) <= 8 )  {
9793
9794                 /* shift left acc */
9795                 AccLsh(shCnt);
9796
9797                 /* using PRODL as a temporary register here */
9798                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9799
9800                 switch (p_type) {
9801                         case FPOINTER:
9802                         case POINTER:
9803                         case GPOINTER:
9804                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9805 //                              pic16_emitcode ("mov","b,a");
9806 //                              pic16_emitcode("mov","a,@%s",rname);
9807                                 break;
9808                 }
9809 #if 1
9810                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9811                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9812                                         (unsigned char)(0xff >> (8-bstr))) ));
9813                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9814                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9815 #endif
9816
9817           return;
9818         }
9819
9820
9821         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9822         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9823         exit(-1);
9824
9825
9826     /* if we r done */
9827     if ( SPEC_BLEN(etype) <= 8 )
9828         return ;
9829
9830     pic16_emitcode("inc","%s",rname);
9831     rLen = SPEC_BLEN(etype) ;     
9832
9833
9834
9835     /* now generate for lengths greater than one byte */
9836     while (1) {
9837
9838         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9839
9840         rLen -= 8 ;
9841         if (rLen <= 0 )
9842             break ;
9843
9844         switch (p_type) {
9845             case POINTER:
9846                 if (*l == '@') {
9847                     MOVA(l);
9848                     pic16_emitcode("mov","@%s,a",rname);
9849                 } else
9850                     pic16_emitcode("mov","@%s,%s",rname,l);
9851                 break;
9852
9853             case FPOINTER:
9854                 MOVA(l);
9855                 pic16_emitcode("movx","@dptr,a");
9856                 break;
9857
9858             case GPOINTER:
9859                 MOVA(l);
9860                 DEBUGpic16_emitcode(";lcall","__gptrput");
9861                 break;  
9862         }   
9863         pic16_emitcode ("inc","%s",rname);
9864     }
9865
9866     MOVA(l);
9867
9868     /* last last was not complete */
9869     if (rLen)   {
9870         /* save the byte & read byte */
9871         switch (p_type) {
9872             case POINTER:
9873                 pic16_emitcode ("mov","b,a");
9874                 pic16_emitcode("mov","a,@%s",rname);
9875                 break;
9876
9877             case FPOINTER:
9878                 pic16_emitcode ("mov","b,a");
9879                 pic16_emitcode("movx","a,@dptr");
9880                 break;
9881
9882             case GPOINTER:
9883                 pic16_emitcode ("push","b");
9884                 pic16_emitcode ("push","acc");
9885                 pic16_emitcode ("lcall","__gptrget");
9886                 pic16_emitcode ("pop","b");
9887                 break;
9888         }
9889
9890         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9891         pic16_emitcode ("orl","a,b");
9892     }
9893
9894     if (p_type == GPOINTER)
9895         pic16_emitcode("pop","b");
9896
9897     switch (p_type) {
9898
9899     case POINTER:
9900         pic16_emitcode("mov","@%s,a",rname);
9901         break;
9902         
9903     case FPOINTER:
9904         pic16_emitcode("movx","@dptr,a");
9905         break;
9906         
9907     case GPOINTER:
9908         DEBUGpic16_emitcode(";lcall","__gptrput");
9909         break;                  
9910     }
9911 }
9912 /*-----------------------------------------------------------------*/
9913 /* genDataPointerSet - remat pointer to data space                 */
9914 /*-----------------------------------------------------------------*/
9915 static void genDataPointerSet(operand *right,
9916                               operand *result,
9917                               iCode *ic)
9918 {
9919     int size, offset = 0, resoffset=0 ;
9920
9921     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9922     pic16_aopOp(right,ic,FALSE);
9923
9924     size = AOP_SIZE(right);
9925
9926 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9927
9928 #if 0
9929     if ( AOP_TYPE(result) == AOP_PCODE) {
9930       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9931               AOP(result)->aopu.pcop->name,
9932                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9933               PCOR(AOP(result)->aopu.pcop)->instance:
9934               PCOI(AOP(result)->aopu.pcop)->offset);
9935     }
9936 #endif
9937
9938         if(AOP(result)->aopu.pcop->type == PO_DIR)
9939                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9940
9941         while (size--) {
9942                 if (AOP_TYPE(right) == AOP_LIT) {
9943                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9944
9945                         lit = lit >> (8*offset);
9946                         if(lit&0xff) {
9947                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9948                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9949                         } else {
9950                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9951                         }
9952                 } else {
9953                         mov2w(AOP(right), offset);
9954                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9955                 }
9956                 offset++;
9957                 resoffset++;
9958         }
9959
9960     pic16_freeAsmop(right,NULL,ic,TRUE);
9961 }
9962
9963
9964
9965 /*-----------------------------------------------------------------*/
9966 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9967 /*-----------------------------------------------------------------*/
9968 static void genNearPointerSet (operand *right,
9969                                operand *result, 
9970                                iCode *ic)
9971 {
9972   asmop *aop = NULL;
9973   char *l;
9974   sym_link *retype;
9975   sym_link *ptype = operandType(result);
9976   sym_link *resetype;
9977     
9978         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9979         retype= getSpec(operandType(right));
9980         resetype = getSpec(operandType(result));
9981   
9982         pic16_aopOp(result,ic,FALSE);
9983     
9984         /* if the result is rematerializable &
9985          * in data space & not a bit variable */
9986         
9987         /* and result is not a bit variable */
9988         if (AOP_TYPE(result) == AOP_PCODE
9989 //              && AOP_TYPE(result) == AOP_IMMD
9990                 && DCL_TYPE(ptype) == POINTER
9991                 && !IS_BITFIELD(retype)
9992                 && !IS_BITFIELD(resetype)) {
9993
9994                 genDataPointerSet (right,result,ic);
9995                 pic16_freeAsmop(result,NULL,ic,TRUE);
9996           return;
9997         }
9998
9999         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10000         pic16_aopOp(right,ic,FALSE);
10001         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10002
10003         /* if the value is already in a pointer register
10004          * then don't need anything more */
10005         if (!AOP_INPREG(AOP(result))) {
10006                 /* otherwise get a free pointer register */
10007                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10008
10009                 if( (AOP_TYPE(result) == AOP_PCODE) 
10010                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10011                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10012                 {
10013                         pic16_loadFSR0( result );  // patch 10
10014                 } else {
10015                         // set up FSR0 with address of result
10016                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10017                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10018                 }
10019
10020         }
10021 //      else
10022 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10023
10024         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10025
10026         /* if bitfield then unpack the bits */
10027         if (IS_BITFIELD(resetype)) {
10028                 genPackBits (resetype, right, NULL, POINTER);
10029         } else {
10030                 /* we have can just get the values */
10031           int size = AOP_SIZE(right);
10032           int offset = 0 ;    
10033
10034                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10035                 while (size--) {
10036                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10037                         if (*l == '@' ) {
10038                                 //MOVA(l);
10039                                 //pic16_emitcode("mov","@%s,a",rname);
10040                                 pic16_emitcode("movf","indf0,w ;1");
10041                         } else {
10042
10043                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10044                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10045                                         if (size) {                                                                     // 
10046                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10047                                         } else {                                                                        // 
10048                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10049                                         }                                                                               // 
10050                                 } else { // no literal                                                                  // 
10051                                         if(size) {                                                                      // 
10052                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10053                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10054                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10055                                         } else {                                                                        // 
10056                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10057                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10058                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10059                                         }                                                                               //
10060                                 }                                                                                       // patch 10
10061                         }
10062                         offset++;
10063                 }
10064         }
10065
10066         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10067         /* now some housekeeping stuff */
10068         if (aop) {
10069                 /* we had to allocate for this iCode */
10070                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10071         } else { 
10072                 /* we did not allocate which means left
10073                  * already in a pointer register, then
10074                  * if size > 0 && this could be used again
10075                  * we have to point it back to where it 
10076                  * belongs */
10077                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10078                 if (AOP_SIZE(right) > 1
10079                         && !OP_SYMBOL(result)->remat
10080                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10081                                 || ic->depth )) {
10082
10083                   int size = AOP_SIZE(right) - 1;
10084
10085                         while (size--)
10086                                 pic16_emitcode("decf","fsr0,f");
10087                         //pic16_emitcode("dec","%s",rname);
10088                 }
10089         }
10090
10091         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10092         /* done */
10093 //release:
10094         pic16_freeAsmop(right,NULL,ic,TRUE);
10095         pic16_freeAsmop(result,NULL,ic,TRUE);
10096 }
10097
10098 /*-----------------------------------------------------------------*/
10099 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10100 /*-----------------------------------------------------------------*/
10101 static void genPagedPointerSet (operand *right,
10102                                operand *result, 
10103                                iCode *ic)
10104 {
10105     asmop *aop = NULL;
10106     regs *preg = NULL ;
10107     char *rname , *l;
10108     sym_link *retype;
10109        
10110     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10111
10112     retype= getSpec(operandType(right));
10113     
10114     pic16_aopOp(result,ic,FALSE);
10115     
10116     /* if the value is already in a pointer register
10117        then don't need anything more */
10118     if (!AOP_INPREG(AOP(result))) {
10119         /* otherwise get a free pointer register */
10120         aop = newAsmop(0);
10121         preg = getFreePtr(ic,&aop,FALSE);
10122         pic16_emitcode("mov","%s,%s",
10123                 preg->name,
10124                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10125         rname = preg->name ;
10126     } else
10127         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10128     
10129     pic16_freeAsmop(result,NULL,ic,TRUE);
10130     pic16_aopOp (right,ic,FALSE);
10131
10132     /* if bitfield then unpack the bits */
10133     if (IS_BITFIELD(retype)) 
10134         genPackBits (retype,right,rname,PPOINTER);
10135     else {
10136         /* we have can just get the values */
10137         int size = AOP_SIZE(right);
10138         int offset = 0 ;        
10139         
10140         while (size--) {
10141             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10142             
10143             MOVA(l);
10144             pic16_emitcode("movx","@%s,a",rname);
10145
10146             if (size)
10147                 pic16_emitcode("inc","%s",rname);
10148
10149             offset++;
10150         }
10151     }
10152     
10153     /* now some housekeeping stuff */
10154     if (aop) {
10155         /* we had to allocate for this iCode */
10156         pic16_freeAsmop(NULL,aop,ic,TRUE);
10157     } else { 
10158         /* we did not allocate which means left
10159            already in a pointer register, then
10160            if size > 0 && this could be used again
10161            we have to point it back to where it 
10162            belongs */
10163         if (AOP_SIZE(right) > 1 &&
10164             !OP_SYMBOL(result)->remat &&
10165             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10166               ic->depth )) {
10167             int size = AOP_SIZE(right) - 1;
10168             while (size--)
10169                 pic16_emitcode("dec","%s",rname);
10170         }
10171     }
10172
10173     /* done */
10174     pic16_freeAsmop(right,NULL,ic,TRUE);
10175     
10176         
10177 }
10178
10179 /*-----------------------------------------------------------------*/
10180 /* genFarPointerSet - set value from far space                     */
10181 /*-----------------------------------------------------------------*/
10182 static void genFarPointerSet (operand *right,
10183                               operand *result, iCode *ic)
10184 {
10185     int size, offset ;
10186     sym_link *retype = getSpec(operandType(right));
10187
10188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10189     pic16_aopOp(result,ic,FALSE);
10190
10191     /* if the operand is already in dptr 
10192     then we do nothing else we move the value to dptr */
10193     if (AOP_TYPE(result) != AOP_STR) {
10194         /* if this is remateriazable */
10195         if (AOP_TYPE(result) == AOP_IMMD)
10196             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10197         else { /* we need to get it byte by byte */
10198             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10199             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10200             if (options.model == MODEL_FLAT24)
10201             {
10202                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10203             }
10204         }
10205     }
10206     /* so dptr know contains the address */
10207     pic16_freeAsmop(result,NULL,ic,TRUE);
10208     pic16_aopOp(right,ic,FALSE);
10209
10210     /* if bit then unpack */
10211     if (IS_BITFIELD(retype)) 
10212         genPackBits(retype,right,"dptr",FPOINTER);
10213     else {
10214         size = AOP_SIZE(right);
10215         offset = 0 ;
10216
10217         while (size--) {
10218             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10219             MOVA(l);
10220             pic16_emitcode("movx","@dptr,a");
10221             if (size)
10222                 pic16_emitcode("inc","dptr");
10223         }
10224     }
10225
10226     pic16_freeAsmop(right,NULL,ic,TRUE);
10227 }
10228
10229 /*-----------------------------------------------------------------*/
10230 /* genGenPointerSet - set value from generic pointer space         */
10231 /*-----------------------------------------------------------------*/
10232 static void genGenPointerSet (operand *right,
10233                               operand *result, iCode *ic)
10234 {
10235         int i, size, offset, lit;
10236         sym_link *retype = getSpec(operandType(right));
10237
10238         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10239
10240         pic16_aopOp(result,ic,FALSE);
10241         pic16_aopOp(right,ic,FALSE);
10242         size = AOP_SIZE(right);
10243         offset = 0;
10244
10245         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10246
10247         /* if the operand is already in dptr 
10248                 then we do nothing else we move the value to dptr */
10249         if (AOP_TYPE(result) != AOP_STR) {
10250                 /* if this is remateriazable */
10251                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10252                 // WARNING: anythig until "else" is untested!
10253                 if (AOP_TYPE(result) == AOP_IMMD) {
10254                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10255                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10256                         // load FSR0 from immediate
10257                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10258                         offset = 0;
10259                         while(size--) {
10260                                 if(size) {
10261                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10262                                 } else {
10263                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10264                                 }
10265                                 offset++;
10266                         }
10267                         goto release;
10268                 }
10269                 else { /* we need to get it byte by byte */
10270                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10271                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10272
10273                         // set up FSR0 with address of result
10274                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10275                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10276
10277                         /* hack hack! see if this the FSR. If so don't load W */
10278                         if(AOP_TYPE(right) != AOP_ACC) {
10279
10280                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10281
10282                                 if(AOP_TYPE(right) == AOP_LIT)
10283                                 {
10284                                         // copy literal
10285                                         // note: pic16_popGet handles sign extension
10286                                         for(i=0;i<size;i++) {
10287                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10288                                                 if(i < size-1)
10289                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10290                                                 else
10291                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10292                                         }
10293                                 } else {
10294                                         // copy regs
10295
10296                                         for(i=0;i<size;i++) {
10297                                                 if(i < size-1)
10298                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10299                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10300                                                 else
10301                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10302                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10303                                         }
10304                                 }
10305                                 goto release;
10306                         } 
10307                         // right = ACC
10308                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10309                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10310                         goto release;
10311         } // if (AOP_TYPE(result) != AOP_IMMD)
10312
10313         } // if (AOP_TYPE(result) != AOP_STR)
10314         /* so dptr know contains the address */
10315
10316
10317         /* if bit then unpack */
10318         if (IS_BITFIELD(retype)) 
10319                 genPackBits(retype,right,"dptr",GPOINTER);
10320         else {
10321                 size = AOP_SIZE(right);
10322                 offset = 0 ;
10323
10324                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10325
10326                 // set up FSR0 with address of result
10327                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10328                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10329         
10330                 while (size--) {
10331                         if (AOP_TYPE(right) == AOP_LIT) {
10332                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10333                                 if (size) {
10334                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10335                                 } else {
10336                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10337                                 }
10338                         } else { // no literal
10339                                 if(size) {
10340                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10341                                 } else {
10342                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10343                                 }
10344                         }
10345                         offset++;
10346                 }
10347         }
10348
10349         release:
10350         pic16_freeAsmop(right,NULL,ic,TRUE);
10351         pic16_freeAsmop(result,NULL,ic,TRUE);
10352 }
10353
10354 /*-----------------------------------------------------------------*/
10355 /* genPointerSet - stores the value into a pointer location        */
10356 /*-----------------------------------------------------------------*/
10357 static void genPointerSet (iCode *ic)
10358 {    
10359     operand *right, *result ;
10360     sym_link *type, *etype;
10361     int p_type;
10362
10363     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10364
10365     right = IC_RIGHT(ic);
10366     result = IC_RESULT(ic) ;
10367
10368     /* depending on the type of pointer we need to
10369     move it to the correct pointer register */
10370     type = operandType(result);
10371     etype = getSpec(type);
10372     /* if left is of type of pointer then it is simple */
10373     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10374         p_type = DCL_TYPE(type);
10375     }
10376     else {
10377         /* we have to go by the storage class */
10378         p_type = PTR_TYPE(SPEC_OCLS(etype));
10379
10380 /*      if (SPEC_OCLS(etype)->codesp ) { */
10381 /*          p_type = CPOINTER ;  */
10382 /*      } */
10383 /*      else */
10384 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10385 /*              p_type = FPOINTER ; */
10386 /*          else */
10387 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10388 /*                  p_type = PPOINTER ; */
10389 /*              else */
10390 /*                  if (SPEC_OCLS(etype) == idata ) */
10391 /*                      p_type = IPOINTER ; */
10392 /*                  else */
10393 /*                      p_type = POINTER ; */
10394     }
10395
10396     /* now that we have the pointer type we assign
10397     the pointer values */
10398     switch (p_type) {
10399
10400     case POINTER:
10401     case IPOINTER:
10402         genNearPointerSet (right,result,ic);
10403         break;
10404
10405     case PPOINTER:
10406         genPagedPointerSet (right,result,ic);
10407         break;
10408
10409     case FPOINTER:
10410         genFarPointerSet (right,result,ic);
10411         break;
10412
10413     case GPOINTER:
10414         genGenPointerSet (right,result,ic);
10415         break;
10416
10417     default:
10418       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10419               "genPointerSet: illegal pointer type");
10420     }
10421 }
10422
10423 /*-----------------------------------------------------------------*/
10424 /* genIfx - generate code for Ifx statement                        */
10425 /*-----------------------------------------------------------------*/
10426 static void genIfx (iCode *ic, iCode *popIc)
10427 {
10428   operand *cond = IC_COND(ic);
10429   int isbit =0;
10430
10431   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10432
10433   pic16_aopOp(cond,ic,FALSE);
10434
10435   /* get the value into acc */
10436   if (AOP_TYPE(cond) != AOP_CRY)
10437     pic16_toBoolean(cond);
10438   else
10439     isbit = 1;
10440   /* the result is now in the accumulator */
10441   pic16_freeAsmop(cond,NULL,ic,TRUE);
10442
10443   /* if there was something to be popped then do it */
10444   if (popIc)
10445     genIpop(popIc);
10446
10447   /* if the condition is  a bit variable */
10448   if (isbit && IS_ITEMP(cond) && 
10449       SPIL_LOC(cond)) {
10450     genIfxJump(ic,SPIL_LOC(cond)->rname);
10451     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10452   }
10453   else {
10454     if (isbit && !IS_ITEMP(cond))
10455       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10456     else
10457       genIfxJump(ic,"a");
10458   }
10459   ic->generated = 1;
10460
10461 }
10462
10463 /*-----------------------------------------------------------------*/
10464 /* genAddrOf - generates code for address of                       */
10465 /*-----------------------------------------------------------------*/
10466 static void genAddrOf (iCode *ic)
10467 {
10468   operand *result, *left;
10469   int size;
10470   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10471   pCodeOp *pcop0, *pcop1, *pcop2;
10472
10473         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10474
10475         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10476         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10477
10478         sym = OP_SYMBOL( left );
10479
10480         size = AOP_SIZE(IC_RESULT(ic));
10481
10482 //      if(pic16_debug_verbose) {
10483 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10484 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10485 //      }
10486         
10487         /* Assume that what we want the address of is in data space
10488          * since there is no stack on the PIC, yet! -- VR */
10489         /* low */
10490         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10491
10492         /* high */
10493         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10494         
10495         /* upper */
10496         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10497         
10498
10499         if (size == 3) {
10500                 pic16_emitpcode(POC_MOVLW, pcop0);
10501                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10502                 pic16_emitpcode(POC_MOVLW, pcop1);
10503                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10504                 pic16_emitpcode(POC_MOVLW, pcop2);
10505                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10506         } else
10507         if (size == 2) {
10508                 pic16_emitpcode(POC_MOVLW, pcop0);
10509                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10510                 pic16_emitpcode(POC_MOVLW, pcop1);
10511                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10512         } else {
10513                 pic16_emitpcode(POC_MOVLW, pcop0);
10514                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10515         }
10516
10517         pic16_freeAsmop(result,NULL,ic,TRUE);
10518         pic16_freeAsmop(left, NULL, ic, FALSE);
10519 }
10520
10521
10522 #if 0
10523 /*-----------------------------------------------------------------*/
10524 /* genFarFarAssign - assignment when both are in far space         */
10525 /*-----------------------------------------------------------------*/
10526 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10527 {
10528     int size = AOP_SIZE(right);
10529     int offset = 0;
10530     char *l ;
10531     /* first push the right side on to the stack */
10532     while (size--) {
10533         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10534         MOVA(l);
10535         pic16_emitcode ("push","acc");
10536     }
10537     
10538     pic16_freeAsmop(right,NULL,ic,FALSE);
10539     /* now assign DPTR to result */
10540     pic16_aopOp(result,ic,FALSE);
10541     size = AOP_SIZE(result);
10542     while (size--) {
10543         pic16_emitcode ("pop","acc");
10544         pic16_aopPut(AOP(result),"a",--offset);
10545     }
10546     pic16_freeAsmop(result,NULL,ic,FALSE);
10547         
10548 }
10549 #endif
10550
10551 /*-----------------------------------------------------------------*/
10552 /* genAssign - generate code for assignment                        */
10553 /*-----------------------------------------------------------------*/
10554 static void genAssign (iCode *ic)
10555 {
10556   operand *result, *right;
10557   int size, offset,know_W;
10558   unsigned long lit = 0L;
10559
10560   result = IC_RESULT(ic);
10561   right  = IC_RIGHT(ic) ;
10562
10563   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10564   
10565   /* if they are the same */
10566   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10567     return ;
10568
10569   pic16_aopOp(right,ic,FALSE);
10570   pic16_aopOp(result,ic,TRUE);
10571
10572   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10573
10574   /* if they are the same registers */
10575   if (pic16_sameRegs(AOP(right),AOP(result)))
10576     goto release;
10577
10578   /* if the result is a bit */
10579   if (AOP_TYPE(result) == AOP_CRY) {
10580     /* if the right size is a literal then
10581        we know what the value is */
10582     if (AOP_TYPE(right) == AOP_LIT) {
10583           
10584       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10585                   pic16_popGet(AOP(result),0));
10586
10587       if (((int) operandLitValue(right))) 
10588         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10589                        AOP(result)->aopu.aop_dir,
10590                        AOP(result)->aopu.aop_dir);
10591       else
10592         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10593                        AOP(result)->aopu.aop_dir,
10594                        AOP(result)->aopu.aop_dir);
10595       goto release;
10596     }
10597
10598     /* the right is also a bit variable */
10599     if (AOP_TYPE(right) == AOP_CRY) {
10600       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10601       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10602       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10603
10604       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10605                      AOP(result)->aopu.aop_dir,
10606                      AOP(result)->aopu.aop_dir);
10607       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10608                      AOP(right)->aopu.aop_dir,
10609                      AOP(right)->aopu.aop_dir);
10610       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10611                      AOP(result)->aopu.aop_dir,
10612                      AOP(result)->aopu.aop_dir);
10613       goto release ;
10614     }
10615
10616     /* we need to or */
10617     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10618     pic16_toBoolean(right);
10619     emitSKPZ;
10620     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10621     //pic16_aopPut(AOP(result),"a",0);
10622     goto release ;
10623   }
10624
10625   /* bit variables done */
10626   /* general case */
10627   size = AOP_SIZE(result);
10628   offset = 0 ;
10629
10630   if(AOP_TYPE(right) == AOP_LIT) {
10631         if(!IS_FLOAT(operandType( right )))
10632                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10633         else {
10634            union {
10635               unsigned long lit_int;
10636               float lit_float;
10637             } info;
10638         
10639                 /* take care if literal is a float */
10640                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10641                 lit = info.lit_int;
10642         }
10643   }
10644
10645 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10646 //                      sizeof(unsigned long int), sizeof(float));
10647
10648   if(AOP_TYPE(right) != AOP_LIT
10649         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10650         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10651
10652         // set up table pointer
10653         if( (AOP_TYPE(right) == AOP_PCODE)
10654                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10655                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10656         {
10657                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10658                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10659                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10660                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10661                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10662                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10663         } else {
10664                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10665                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10666                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10667                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10668                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10669                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10670         }
10671
10672         size = min(AOP_SIZE(right), AOP_SIZE(result));
10673         while(size--) {
10674                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10675                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10676                         pic16_popGet(AOP(result),offset)));
10677                 offset++;
10678         }
10679
10680         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10681                 size = AOP_SIZE(result) - AOP_SIZE(right);
10682                 while(size--) {
10683                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10684                         offset++;
10685                 }
10686         }
10687         goto release;
10688   }
10689
10690
10691
10692 /* VR - What is this?! */
10693   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10694   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10695     if(aopIdx(AOP(result),0) == 4) {
10696   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10697         assert(0);
10698       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10699       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10700       goto release;
10701     } else
10702 //      assert(0);
10703       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10704   }
10705
10706   know_W=-1;
10707   while (size--) {
10708   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10709     if(AOP_TYPE(right) == AOP_LIT) {
10710       if(lit&0xff) {
10711         if(know_W != (lit&0xff))
10712           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10713         know_W = lit&0xff;
10714         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10715       } else
10716         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10717
10718       lit >>= 8;
10719
10720     } else if (AOP_TYPE(right) == AOP_CRY) {
10721       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10722       if(offset == 0) {
10723         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10724         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10725       }
10726     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10727         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10728         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10729     } else {
10730   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10731
10732 #if 1
10733         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10734            normally should work, but mind that the W register live range
10735            is not checked, so if the code generator assumes that the W
10736            is already loaded after such a pair, wrong code will be generated.
10737            
10738            Checking the live range is the next step.
10739            This is experimental code yet and has not been fully tested yet.
10740            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10741            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10742            
10743         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10744 #else   
10745         /* This is the old code, which is assumed(?!) that works fine(!?) */
10746
10747         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10748         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10749 #endif
10750     }
10751             
10752     offset++;
10753   }
10754
10755     
10756  release:
10757   pic16_freeAsmop (right,NULL,ic,FALSE);
10758   pic16_freeAsmop (result,NULL,ic,TRUE);
10759 }   
10760
10761 /*-----------------------------------------------------------------*/
10762 /* genJumpTab - generates code for jump table                       */
10763 /*-----------------------------------------------------------------*/
10764 static void genJumpTab (iCode *ic)
10765 {
10766     symbol *jtab;
10767     char *l;
10768
10769     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10770
10771     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10772     /* get the condition into accumulator */
10773     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10774     MOVA(l);
10775     /* multiply by three */
10776     pic16_emitcode("add","a,acc");
10777     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10778
10779     jtab = newiTempLabel(NULL);
10780     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10781     pic16_emitcode("jmp","@a+dptr");
10782     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10783
10784     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10785     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10786     emitSKPNC;
10787     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10788     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10789     pic16_emitpLabel(jtab->key);
10790
10791     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10792
10793     /* now generate the jump labels */
10794     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10795          jtab = setNextItem(IC_JTLABELS(ic))) {
10796         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10797         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10798         
10799     }
10800
10801 }
10802
10803 /*-----------------------------------------------------------------*/
10804 /* genMixedOperation - gen code for operators between mixed types  */
10805 /*-----------------------------------------------------------------*/
10806 /*
10807   TSD - Written for the PIC port - but this unfortunately is buggy.
10808   This routine is good in that it is able to efficiently promote 
10809   types to different (larger) sizes. Unfortunately, the temporary
10810   variables that are optimized out by this routine are sometimes
10811   used in other places. So until I know how to really parse the 
10812   iCode tree, I'm going to not be using this routine :(.
10813 */
10814 static int genMixedOperation (iCode *ic)
10815 {
10816 #if 0
10817   operand *result = IC_RESULT(ic);
10818   sym_link *ctype = operandType(IC_LEFT(ic));
10819   operand *right = IC_RIGHT(ic);
10820   int ret = 0;
10821   int big,small;
10822   int offset;
10823
10824   iCode *nextic;
10825   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10826
10827   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10828
10829   nextic = ic->next;
10830   if(!nextic)
10831     return 0;
10832
10833   nextright = IC_RIGHT(nextic);
10834   nextleft  = IC_LEFT(nextic);
10835   nextresult = IC_RESULT(nextic);
10836
10837   pic16_aopOp(right,ic,FALSE);
10838   pic16_aopOp(result,ic,FALSE);
10839   pic16_aopOp(nextright,  nextic, FALSE);
10840   pic16_aopOp(nextleft,   nextic, FALSE);
10841   pic16_aopOp(nextresult, nextic, FALSE);
10842
10843   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10844
10845     operand *t = right;
10846     right = nextright;
10847     nextright = t; 
10848
10849     pic16_emitcode(";remove right +","");
10850
10851   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10852 /*
10853     operand *t = right;
10854     right = nextleft;
10855     nextleft = t; 
10856 */
10857     pic16_emitcode(";remove left +","");
10858   } else
10859     return 0;
10860
10861   big = AOP_SIZE(nextleft);
10862   small = AOP_SIZE(nextright);
10863
10864   switch(nextic->op) {
10865
10866   case '+':
10867     pic16_emitcode(";optimize a +","");
10868     /* if unsigned or not an integral type */
10869     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10870       pic16_emitcode(";add a bit to something","");
10871     } else {
10872
10873       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10874
10875       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10876         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10877         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10878       } else
10879         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10880
10881       offset = 0;
10882       while(--big) {
10883
10884         offset++;
10885
10886         if(--small) {
10887           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10888             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10889             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10890           }
10891
10892           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10893           emitSKPNC;
10894           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10895                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10896                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10897           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10898           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10899
10900         } else {
10901           pic16_emitcode("rlf","known_zero,w");
10902
10903           /*
10904             if right is signed
10905               btfsc  right,7
10906                addlw ff
10907           */
10908           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10909             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10910             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10911           } else {
10912             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10913           }
10914         }
10915       }
10916       ret = 1;
10917     }
10918   }
10919   ret = 1;
10920
10921 release:
10922   pic16_freeAsmop(right,NULL,ic,TRUE);
10923   pic16_freeAsmop(result,NULL,ic,TRUE);
10924   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10925   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10926   if(ret)
10927     nextic->generated = 1;
10928
10929   return ret;
10930 #else
10931   return 0;
10932 #endif
10933 }
10934 /*-----------------------------------------------------------------*/
10935 /* genCast - gen code for casting                                  */
10936 /*-----------------------------------------------------------------*/
10937 static void genCast (iCode *ic)
10938 {
10939   operand *result = IC_RESULT(ic);
10940   sym_link *ctype = operandType(IC_LEFT(ic));
10941   sym_link *rtype = operandType(IC_RIGHT(ic));
10942   operand *right = IC_RIGHT(ic);
10943   int size, offset ;
10944
10945         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10946         /* if they are equivalent then do nothing */
10947         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10948                 return ;
10949
10950         pic16_aopOp(right,ic,FALSE) ;
10951         pic16_aopOp(result,ic,FALSE);
10952
10953         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10954
10955         /* if the result is a bit */
10956         if (AOP_TYPE(result) == AOP_CRY) {
10957         
10958                 /* if the right size is a literal then
10959                  * we know what the value is */
10960                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10961
10962                 if (AOP_TYPE(right) == AOP_LIT) {
10963                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10964                                 pic16_popGet(AOP(result),0));
10965
10966                         if (((int) operandLitValue(right))) 
10967                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10968                                         AOP(result)->aopu.aop_dir,
10969                                         AOP(result)->aopu.aop_dir);
10970                         else
10971                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10972                                         AOP(result)->aopu.aop_dir,
10973                                         AOP(result)->aopu.aop_dir);
10974                         goto release;
10975                 }
10976
10977                 /* the right is also a bit variable */
10978                 if (AOP_TYPE(right) == AOP_CRY) {
10979                         emitCLRC;
10980                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10981
10982                         pic16_emitcode("clrc","");
10983                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10984                                 AOP(right)->aopu.aop_dir,
10985                                 AOP(right)->aopu.aop_dir);
10986                         pic16_aopPut(AOP(result),"c",0);
10987                         goto release ;
10988                 }
10989
10990                 /* we need to or */
10991                 if (AOP_TYPE(right) == AOP_REG) {
10992                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10993                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10994                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10995                 }
10996                 pic16_toBoolean(right);
10997                 pic16_aopPut(AOP(result),"a",0);
10998                 goto release ;
10999         }
11000
11001         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11002           int offset = 1;
11003
11004                 size = AOP_SIZE(result);
11005
11006                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11007
11008                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11009                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11010                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11011
11012                 while (size--)
11013                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11014
11015                 goto release;
11016         }
11017
11018         /* if they are the same size : or less */
11019         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11020
11021                 /* if they are in the same place */
11022                 if (pic16_sameRegs(AOP(right),AOP(result)))
11023                         goto release;
11024
11025                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11026 #if 0
11027                 if (IS_PTR_CONST(rtype))
11028 #else
11029                 if (IS_CODEPTR(rtype))
11030 #endif
11031                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11032
11033 #if 0
11034                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11035 #else
11036                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11037 #endif
11038                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11039
11040 #if 0
11041                 if(AOP_TYPE(right) == AOP_IMMD) {
11042                   pCodeOp *pcop0, *pcop1, *pcop2;
11043                   symbol *sym = OP_SYMBOL( right );
11044
11045                         size = AOP_SIZE(result);
11046                         /* low */
11047                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11048                         /* high */
11049                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11050                         /* upper */
11051                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11052         
11053                         if (size == 3) {
11054                                 pic16_emitpcode(POC_MOVLW, pcop0);
11055                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11056                                 pic16_emitpcode(POC_MOVLW, pcop1);
11057                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11058                                 pic16_emitpcode(POC_MOVLW, pcop2);
11059                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11060                         } else
11061                         if (size == 2) {
11062                                 pic16_emitpcode(POC_MOVLW, pcop0);
11063                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11064                                 pic16_emitpcode(POC_MOVLW, pcop1);
11065                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11066                         } else {
11067                                 pic16_emitpcode(POC_MOVLW, pcop0);
11068                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11069                         }
11070                 } else
11071 #endif
11072                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11073                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11074                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11075                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11076                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11077                         if(AOP_SIZE(result) <2)
11078                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11079                 } else {
11080                         /* if they in different places then copy */
11081                         size = AOP_SIZE(result);
11082                         offset = 0 ;
11083                         while (size--) {
11084                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11085                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11086                                 offset++;
11087                         }
11088                 }
11089                 goto release;
11090         }
11091
11092         /* if the result is of type pointer */
11093         if (IS_PTR(ctype)) {
11094           int p_type;
11095           sym_link *type = operandType(right);
11096           sym_link *etype = getSpec(type);
11097
11098                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11099
11100                 /* pointer to generic pointer */
11101                 if (IS_GENPTR(ctype)) {
11102                   char *l = zero;
11103             
11104                         if (IS_PTR(type)) 
11105                                 p_type = DCL_TYPE(type);
11106                         else {
11107                 /* we have to go by the storage class */
11108                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11109
11110 /*              if (SPEC_OCLS(etype)->codesp )  */
11111 /*                  p_type = CPOINTER ;  */
11112 /*              else */
11113 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11114 /*                      p_type = FPOINTER ; */
11115 /*                  else */
11116 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11117 /*                          p_type = PPOINTER; */
11118 /*                      else */
11119 /*                          if (SPEC_OCLS(etype) == idata ) */
11120 /*                              p_type = IPOINTER ; */
11121 /*                          else */
11122 /*                              p_type = POINTER ; */
11123             }
11124                 
11125             /* the first two bytes are known */
11126       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11127             size = GPTRSIZE - 1; 
11128             offset = 0 ;
11129             while (size--) {
11130               if(offset < AOP_SIZE(right)) {
11131       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11132                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11133                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11134                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11135                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11136                 } else { 
11137                   pic16_aopPut(AOP(result),
11138                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11139                          offset);
11140                 }
11141               } else 
11142                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11143               offset++;
11144             }
11145             /* the last byte depending on type */
11146             switch (p_type) {
11147             case IPOINTER:
11148             case POINTER:
11149                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11150                 break;
11151             case FPOINTER:
11152               pic16_emitcode(";BUG!? ","%d",__LINE__);
11153                 l = one;
11154                 break;
11155             case CPOINTER:
11156               pic16_emitcode(";BUG!? ","%d",__LINE__);
11157                 l = "#0x02";
11158                 break;                          
11159             case PPOINTER:
11160               pic16_emitcode(";BUG!? ","%d",__LINE__);
11161                 l = "#0x03";
11162                 break;
11163                 
11164             default:
11165                 /* this should never happen */
11166                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11167                        "got unknown pointer type");
11168                 exit(1);
11169             }
11170             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11171             goto release ;
11172         }
11173         
11174         /* just copy the pointers */
11175         size = AOP_SIZE(result);
11176         offset = 0 ;
11177         while (size--) {
11178             pic16_aopPut(AOP(result),
11179                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11180                    offset);
11181             offset++;
11182         }
11183         goto release ;
11184     }
11185     
11186
11187
11188     /* so we now know that the size of destination is greater
11189     than the size of the source.
11190     Now, if the next iCode is an operator then we might be
11191     able to optimize the operation without performing a cast.
11192     */
11193     if(genMixedOperation(ic))
11194       goto release;
11195
11196     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11197     
11198     /* we move to result for the size of source */
11199     size = AOP_SIZE(right);
11200     offset = 0 ;
11201     while (size--) {
11202       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11203       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11204       offset++;
11205     }
11206
11207     /* now depending on the sign of the destination */
11208     size = AOP_SIZE(result) - AOP_SIZE(right);
11209     /* if unsigned or not an integral type */
11210     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11211       while (size--)
11212         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11213     } else {
11214       /* we need to extend the sign :( */
11215
11216       if(size == 1) {
11217         /* Save one instruction of casting char to int */
11218         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11219         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11220         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11221       } else {
11222         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11223
11224         if(offset)
11225           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11226         else
11227           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11228         
11229         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11230
11231         while (size--)
11232           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11233       }
11234     }
11235
11236 release:
11237     pic16_freeAsmop(right,NULL,ic,TRUE);
11238     pic16_freeAsmop(result,NULL,ic,TRUE);
11239
11240 }
11241
11242 /*-----------------------------------------------------------------*/
11243 /* genDjnz - generate decrement & jump if not zero instrucion      */
11244 /*-----------------------------------------------------------------*/
11245 static int genDjnz (iCode *ic, iCode *ifx)
11246 {
11247     symbol *lbl, *lbl1;
11248     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11249
11250     if (!ifx)
11251         return 0;
11252     
11253     /* if the if condition has a false label
11254        then we cannot save */
11255     if (IC_FALSE(ifx))
11256         return 0;
11257
11258     /* if the minus is not of the form 
11259        a = a - 1 */
11260     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11261         !IS_OP_LITERAL(IC_RIGHT(ic)))
11262         return 0;
11263
11264     if (operandLitValue(IC_RIGHT(ic)) != 1)
11265         return 0;
11266
11267     /* if the size of this greater than one then no
11268        saving */
11269     if (getSize(operandType(IC_RESULT(ic))) > 1)
11270         return 0;
11271
11272     /* otherwise we can save BIG */
11273     lbl = newiTempLabel(NULL);
11274     lbl1= newiTempLabel(NULL);
11275
11276     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11277     
11278     if (IS_AOP_PREG(IC_RESULT(ic))) {
11279         pic16_emitcode("dec","%s",
11280                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11281         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11282         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11283     } else {    
11284
11285
11286       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11287       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11288
11289       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11290       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11291
11292     }
11293 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11294 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11295 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11296 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11297
11298     
11299     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11300     ifx->generated = 1;
11301     return 1;
11302 }
11303
11304 /*-----------------------------------------------------------------*/
11305 /* genReceive - generate code for a receive iCode                  */
11306 /*-----------------------------------------------------------------*/
11307 static void genReceive (iCode *ic)
11308 {    
11309         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11310
11311         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11312                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11313                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11314
11315           int size = getSize(operandType(IC_RESULT(ic)));
11316           int offset =  pic16_fReturnSizePic - size;
11317
11318                 while (size--) {
11319                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11320                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11321                         offset++;
11322                 }
11323
11324                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11325
11326                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11327                 size = AOP_SIZE(IC_RESULT(ic));
11328                 offset = 0;
11329                 while (size--) {
11330                         pic16_emitcode ("pop","acc");
11331                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11332                 }
11333         } else {
11334                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11335
11336                 _G.accInUse++;
11337                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11338                 _G.accInUse--;
11339                 assignResultValue(IC_RESULT(ic), 0);
11340         }
11341
11342         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11343 }
11344
11345 /*-----------------------------------------------------------------*/
11346 /* genDummyRead - generate code for dummy read of volatiles        */
11347 /*-----------------------------------------------------------------*/
11348 static void
11349 genDummyRead (iCode * ic)
11350 {
11351   pic16_emitcode ("; genDummyRead","");
11352   pic16_emitcode ("; not implemented","");
11353
11354   ic = ic;
11355 }
11356
11357 /*-----------------------------------------------------------------*/
11358 /* genpic16Code - generate code for pic16 based controllers        */
11359 /*-----------------------------------------------------------------*/
11360 /*
11361  * At this point, ralloc.c has gone through the iCode and attempted
11362  * to optimize in a way suitable for a PIC. Now we've got to generate
11363  * PIC instructions that correspond to the iCode.
11364  *
11365  * Once the instructions are generated, we'll pass through both the
11366  * peep hole optimizer and the pCode optimizer.
11367  *-----------------------------------------------------------------*/
11368
11369 void genpic16Code (iCode *lic)
11370 {
11371     iCode *ic;
11372     int cln = 0;
11373
11374     lineHead = lineCurr = NULL;
11375
11376     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11377     pic16_addpBlock(pb);
11378
11379 #if 0
11380     /* if debug information required */
11381     if (options.debug && currFunc) {
11382       if (currFunc) {
11383         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11384       }
11385     }
11386 #endif
11387
11388     for (ic = lic ; ic ; ic = ic->next ) {
11389
11390       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11391         if ( cln != ic->lineno ) {
11392             if ( options.debug ) {
11393               debugFile->writeCLine (ic);
11394             }
11395             
11396             if(!options.noCcodeInAsm) {
11397                 pic16_addpCode2pBlock(pb,
11398                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11399                                 printCLine(ic->filename, ic->lineno)));
11400             }
11401
11402             cln = ic->lineno ;
11403         }
11404         
11405         if(options.iCodeInAsm) {
11406                 char *l;
11407                 /* insert here code to print iCode as comment */
11408                 l = Safe_strdup(printILine(ic));
11409                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11410         }
11411         
11412         /* if the result is marked as
11413            spilt and rematerializable or code for
11414            this has already been generated then
11415            do nothing */
11416         if (resultRemat(ic) || ic->generated ) 
11417             continue ;
11418         
11419         /* depending on the operation */
11420         switch (ic->op) {
11421         case '!' :
11422             pic16_genNot(ic);
11423             break;
11424             
11425         case '~' :
11426             pic16_genCpl(ic);
11427             break;
11428             
11429         case UNARYMINUS:
11430             genUminus (ic);
11431             break;
11432             
11433         case IPUSH:
11434             genIpush (ic);
11435             break;
11436             
11437         case IPOP:
11438             /* IPOP happens only when trying to restore a 
11439                spilt live range, if there is an ifx statement
11440                following this pop then the if statement might
11441                be using some of the registers being popped which
11442                would destroy the contents of the register so
11443                we need to check for this condition and handle it */
11444             if (ic->next            && 
11445                 ic->next->op == IFX &&
11446                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11447                 genIfx (ic->next,ic);
11448             else
11449                 genIpop (ic);
11450             break; 
11451             
11452         case CALL:
11453             genCall (ic);
11454             break;
11455             
11456         case PCALL:
11457             genPcall (ic);
11458             break;
11459             
11460         case FUNCTION:
11461             genFunction (ic);
11462             break;
11463             
11464         case ENDFUNCTION:
11465             genEndFunction (ic);
11466             break;
11467             
11468         case RETURN:
11469             genRet (ic);
11470             break;
11471             
11472         case LABEL:
11473             genLabel (ic);
11474             break;
11475             
11476         case GOTO:
11477             genGoto (ic);
11478             break;
11479             
11480         case '+' :
11481             pic16_genPlus (ic) ;
11482             break;
11483             
11484         case '-' :
11485             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11486                 pic16_genMinus (ic);
11487             break;
11488             
11489         case '*' :
11490             genMult (ic);
11491             break;
11492             
11493         case '/' :
11494             genDiv (ic) ;
11495             break;
11496             
11497         case '%' :
11498             genMod (ic);
11499             break;
11500             
11501         case '>' :
11502             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11503             break;
11504             
11505         case '<' :
11506             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11507             break;
11508             
11509         case LE_OP:
11510         case GE_OP:
11511         case NE_OP:
11512             
11513             /* note these two are xlated by algebraic equivalence
11514                during parsing SDCC.y */
11515             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11516                    "got '>=' or '<=' shouldn't have come here");
11517             break;      
11518             
11519         case EQ_OP:
11520             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11521             break;          
11522             
11523         case AND_OP:
11524             genAndOp (ic);
11525             break;
11526             
11527         case OR_OP:
11528             genOrOp (ic);
11529             break;
11530             
11531         case '^' :
11532             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11533             break;
11534             
11535         case '|' :
11536                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11537             break;
11538             
11539         case BITWISEAND:
11540             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11541             break;
11542             
11543         case INLINEASM:
11544             genInline (ic);
11545             break;
11546             
11547         case RRC:
11548             genRRC (ic);
11549             break;
11550             
11551         case RLC:
11552             genRLC (ic);
11553             break;
11554             
11555         case GETHBIT:
11556             genGetHbit (ic);
11557             break;
11558             
11559         case LEFT_OP:
11560             genLeftShift (ic);
11561             break;
11562             
11563         case RIGHT_OP:
11564             genRightShift (ic);
11565             break;
11566             
11567         case GET_VALUE_AT_ADDRESS:
11568             genPointerGet(ic);
11569             break;
11570             
11571         case '=' :
11572             if (POINTER_SET(ic))
11573                 genPointerSet(ic);
11574             else
11575                 genAssign(ic);
11576             break;
11577             
11578         case IFX:
11579             genIfx (ic,NULL);
11580             break;
11581             
11582         case ADDRESS_OF:
11583             genAddrOf (ic);
11584             break;
11585             
11586         case JUMPTABLE:
11587             genJumpTab (ic);
11588             break;
11589             
11590         case CAST:
11591             genCast (ic);
11592             break;
11593             
11594         case RECEIVE:
11595             genReceive(ic);
11596             break;
11597             
11598         case SEND:
11599             addSet(&_G.sendSet,ic);
11600             break;
11601
11602         case DUMMY_READ_VOLATILE:
11603           genDummyRead (ic);
11604           break;
11605
11606         default :
11607             ic = ic;
11608         }
11609     }
11610
11611
11612     /* now we are ready to call the
11613        peep hole optimizer */
11614     if (!options.nopeep) {
11615       peepHole (&lineHead);
11616     }
11617     /* now do the actual printing */
11618     printLine (lineHead,codeOutFile);
11619
11620 #ifdef PCODE_DEBUG
11621     DFPRINTF((stderr,"printing pBlock\n\n"));
11622     pic16_printpBlock(stdout,pb);
11623 #endif
11624
11625     return;
11626 }
11627