* src/mcs51/gen.c (genCmp): fixed bug #975903
[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 (sym1->rname[0] && sym2->rname[0]
850         && strcmp (sym1->rname, sym2->rname) == 0)
851         return TRUE;
852
853
854     /* if left is a tmp & right is not */
855     if (IS_ITEMP(op1)  && 
856         !IS_ITEMP(op2) &&
857         sym1->isspilt  &&
858         (sym1->usl.spillLoc == sym2))
859         return TRUE;
860
861     if (IS_ITEMP(op2)  && 
862         !IS_ITEMP(op1) &&
863         sym2->isspilt  &&
864         sym1->level > 0 &&
865         (sym2->usl.spillLoc == sym1))
866         return TRUE ;
867
868     return FALSE ;
869 }
870
871 /*-----------------------------------------------------------------*/
872 /* pic16_sameRegs - two asmops have the same registers                   */
873 /*-----------------------------------------------------------------*/
874 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
875 {
876     int i;
877
878     if (aop1 == aop2)
879         return TRUE ;
880
881     if (aop1->type != AOP_REG ||
882         aop2->type != AOP_REG )
883         return FALSE ;
884
885     if (aop1->size != aop2->size )
886         return FALSE ;
887
888     for (i = 0 ; i < aop1->size ; i++ )
889         if (aop1->aopu.aop_reg[i] !=
890             aop2->aopu.aop_reg[i] )
891             return FALSE ;
892
893     return TRUE ;
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* pic16_aopOp - allocates an asmop for an operand  :                    */
898 /*-----------------------------------------------------------------*/
899 void pic16_aopOp (operand *op, iCode *ic, bool result)
900 {
901     asmop *aop;
902     symbol *sym;
903     int i;
904
905     if (!op)
906         return ;
907
908 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
909
910     /* if this a literal */
911     if (IS_OP_LITERAL(op)) {
912         op->aop = aop = newAsmop(AOP_LIT);
913         aop->aopu.aop_lit = op->operand.valOperand;
914         aop->size = getSize(operandType(op));
915         return;
916     }
917
918     {
919       sym_link *type = operandType(op);
920 #if 0
921       if(IS_PTR_CONST(type))
922 #else
923       if(IS_CODEPTR(type))
924 #endif
925         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
926     }
927
928     /* if already has a asmop then continue */
929     if (op->aop)
930         return ;
931
932     /* if the underlying symbol has a aop */
933     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
934       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
935         op->aop = OP_SYMBOL(op)->aop;
936         return;
937     }
938
939     /* if this is a true symbol */
940     if (IS_TRUE_SYMOP(op)) {    
941         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
942       op->aop = aopForSym(ic, op, result);
943       return ;
944     }
945
946     /* this is a temporary : this has
947     only four choices :
948     a) register
949     b) spillocation
950     c) rematerialize 
951     d) conditional   
952     e) can be a return use only */
953
954     sym = OP_SYMBOL(op);
955
956         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
957     /* if the type is a conditional */
958     if (sym->regType == REG_CND) {
959         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
960         aop->size = 0;
961         return;
962     }
963
964     /* if it is spilt then two situations
965     a) is rematerialize 
966     b) has a spill location */
967     if (sym->isspilt || sym->nRegs == 0) {
968
969       DEBUGpic16_emitcode(";","%d",__LINE__);
970         /* rematerialize it NOW */
971         if (sym->remat) {
972
973             sym->aop = op->aop = aop =
974                                       aopForRemat (op);
975             aop->size = getSize(sym->type);
976             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
977             return;
978         }
979
980 #if 1
981         if (sym->accuse) {
982             int i;
983             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
984             aop->size = getSize(sym->type);
985             for ( i = 0 ; i < 1 ; i++ ) {
986                 aop->aopu.aop_str[i] = accUse[i];
987 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
988             }
989             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
990             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
991             return;  
992         }
993 #endif
994
995 #if 1
996         if (sym->ruonly ) {
997           /*
998           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
999           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1000           //pic16_allocDirReg (IC_LEFT(ic));
1001           aop->size = getSize(sym->type);
1002           */
1003
1004           unsigned i;
1005
1006           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1007           aop->size = getSize(sym->type);
1008           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1009             aop->aopu.aop_str[i] = fReturn[i];
1010
1011           DEBUGpic16_emitcode(";","%d",__LINE__);
1012           return;
1013         }
1014 #endif
1015         /* else spill location  */
1016         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1017             /* force a new aop if sizes differ */
1018             sym->usl.spillLoc->aop = NULL;
1019         }
1020         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1021                             __FUNCTION__,__LINE__,
1022                             sym->usl.spillLoc->rname,
1023                             sym->rname, sym->usl.spillLoc->offset);
1024
1025         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1026         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1027         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1028                                           getSize(sym->type), 
1029                                           sym->usl.spillLoc->offset, op);
1030         aop->size = getSize(sym->type);
1031
1032         return;
1033     }
1034
1035     {
1036       sym_link *type = operandType(op);
1037 #if 0
1038       if(IS_PTR_CONST(type)) 
1039 #else
1040       if(IS_CODEPTR(type)) 
1041 #endif
1042         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1043     }
1044
1045     /* must be in a register */
1046     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1047     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1048     aop->size = sym->nRegs;
1049     for ( i = 0 ; i < sym->nRegs ;i++)
1050         aop->aopu.aop_reg[i] = sym->regs[i];
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_freeAsmop - free up the asmop given to an operand               */
1055 /*----------------------------------------------------------------*/
1056 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1057 {   
1058     asmop *aop ;
1059
1060     if (!op)
1061         aop = aaop;
1062     else 
1063         aop = op->aop;
1064
1065     if (!aop)
1066         return ;
1067
1068     if (aop->freed)
1069         goto dealloc; 
1070
1071     aop->freed = 1;
1072
1073     /* depending on the asmop type only three cases need work AOP_RO
1074        , AOP_R1 && AOP_STK */
1075 #if 0
1076     switch (aop->type) {
1077         case AOP_R0 :
1078             if (_G.r0Pushed ) {
1079                 if (pop) {
1080                     pic16_emitcode ("pop","ar0");     
1081                     _G.r0Pushed--;
1082                 }
1083             }
1084             bitVectUnSetBit(ic->rUsed,R0_IDX);
1085             break;
1086
1087         case AOP_R1 :
1088             if (_G.r1Pushed ) {
1089                 if (pop) {
1090                     pic16_emitcode ("pop","ar1");
1091                     _G.r1Pushed--;
1092                 }
1093             }
1094             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1095             break;
1096
1097         case AOP_STK :
1098         {
1099             int sz = aop->size;    
1100             int stk = aop->aopu.aop_stk + aop->size;
1101             bitVectUnSetBit(ic->rUsed,R0_IDX);
1102             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1103
1104             getFreePtr(ic,&aop,FALSE);
1105             
1106             if (options.stack10bit)
1107             {
1108                 /* I'm not sure what to do here yet... */
1109                 /* #STUB */
1110                 fprintf(stderr, 
1111                         "*** Warning: probably generating bad code for "
1112                         "10 bit stack mode.\n");
1113             }
1114             
1115             if (stk) {
1116                 pic16_emitcode ("mov","a,_bp");
1117                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1118                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1119             } else {
1120                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1121             }
1122
1123             while (sz--) {
1124                 pic16_emitcode("pop","acc");
1125                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1126                 if (!sz) break;
1127                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1128             }
1129             op->aop = aop;
1130             pic16_freeAsmop(op,NULL,ic,TRUE);
1131             if (_G.r0Pushed) {
1132                 pic16_emitcode("pop","ar0");
1133                 _G.r0Pushed--;
1134             }
1135
1136             if (_G.r1Pushed) {
1137                 pic16_emitcode("pop","ar1");
1138                 _G.r1Pushed--;
1139             }       
1140         }
1141     }
1142 #endif
1143
1144 dealloc:
1145     /* all other cases just dealloc */
1146     if (op ) {
1147         op->aop = NULL;
1148         if (IS_SYMOP(op)) {
1149             OP_SYMBOL(op)->aop = NULL;    
1150             /* if the symbol has a spill */
1151             if (SPIL_LOC(op))
1152                 SPIL_LOC(op)->aop = NULL;
1153         }
1154     }
1155 }
1156
1157 /*-----------------------------------------------------------------*/
1158 /* pic16_aopGet - for fetching value of the aop                          */
1159 /*-----------------------------------------------------------------*/
1160 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1161 {
1162     char *s = buffer ;
1163     char *rs;
1164
1165     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1166
1167     /* offset is greater than size then zero */
1168     if (offset > (aop->size - 1) &&
1169         aop->type != AOP_LIT)
1170         return zero;
1171
1172     /* depending on type */
1173     switch (aop->type) {
1174         
1175     case AOP_R0:
1176     case AOP_R1:
1177         DEBUGpic16_emitcode(";","%d",__LINE__);
1178         /* if we need to increment it */       
1179         while (offset > aop->coff) {        
1180             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1181             aop->coff++;
1182         }
1183         
1184         while (offset < aop->coff) {
1185             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1186             aop->coff--;
1187         }
1188         
1189         aop->coff = offset ;
1190         if (aop->paged) {
1191             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1192             return (dname ? "acc" : "a");
1193         }       
1194         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1195         rs = Safe_calloc(1,strlen(s)+1);
1196         strcpy(rs,s);   
1197         return rs;
1198         
1199     case AOP_DPTR:
1200     case AOP_DPTR2:
1201         DEBUGpic16_emitcode(";","%d",__LINE__);
1202     if (aop->type == AOP_DPTR2)
1203     {
1204         genSetDPTR(1);
1205     }
1206     
1207         while (offset > aop->coff) {
1208             pic16_emitcode ("inc","dptr");
1209             aop->coff++;
1210         }
1211         
1212         while (offset < aop->coff) {        
1213             pic16_emitcode("lcall","__decdptr");
1214             aop->coff--;
1215         }
1216         
1217         aop->coff = offset;
1218         if (aop->code) {
1219             pic16_emitcode("clr","a");
1220             pic16_emitcode("movc","a,@a+dptr");
1221         }
1222     else {
1223             pic16_emitcode("movx","a,@dptr");
1224     }
1225             
1226     if (aop->type == AOP_DPTR2)
1227     {
1228         genSetDPTR(0);
1229     }
1230             
1231     return (dname ? "acc" : "a");
1232         
1233         
1234     case AOP_IMMD:
1235         if (bit16) 
1236             sprintf (s,"%s",aop->aopu.aop_immd);
1237         else
1238             if (offset) 
1239                 sprintf(s,"(%s >> %d)",
1240                         aop->aopu.aop_immd,
1241                         offset*8);
1242             else
1243                 sprintf(s,"%s",
1244                         aop->aopu.aop_immd);
1245         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1246         rs = Safe_calloc(1,strlen(s)+1);
1247         strcpy(rs,s);   
1248         return rs;
1249         
1250     case AOP_DIR:
1251       if (offset) {
1252         sprintf(s,"(%s + %d)",
1253                 aop->aopu.aop_dir,
1254                 offset);
1255         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1256       } else
1257             sprintf(s,"%s",aop->aopu.aop_dir);
1258         rs = Safe_calloc(1,strlen(s)+1);
1259         strcpy(rs,s);   
1260         return rs;
1261         
1262     case AOP_REG:
1263       //if (dname) 
1264       //    return aop->aopu.aop_reg[offset]->dname;
1265       //else
1266             return aop->aopu.aop_reg[offset]->name;
1267         
1268     case AOP_CRY:
1269       //pic16_emitcode(";","%d",__LINE__);
1270       return aop->aopu.aop_dir;
1271         
1272     case AOP_ACC:
1273         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1274 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1275 //        assert( 0 );
1276         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1277
1278     case AOP_LIT:
1279         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1280         rs = Safe_calloc(1,strlen(s)+1);
1281         strcpy(rs,s);   
1282         return rs;
1283         
1284     case AOP_STR:
1285         aop->coff = offset ;
1286         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1287             dname)
1288             return "acc";
1289         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1290         
1291         return aop->aopu.aop_str[offset];
1292         
1293     case AOP_PCODE:
1294       {
1295         pCodeOp *pcop = aop->aopu.pcop;
1296         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1297         if(pcop->name) {
1298           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1299           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1300           sprintf(s,"%s", pcop->name);
1301         } else
1302           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1303
1304       }
1305       rs = Safe_calloc(1,strlen(s)+1);
1306       strcpy(rs,s);   
1307       return rs;
1308
1309     }
1310
1311     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1312            "aopget got unsupported aop->type");
1313     exit(0);
1314 }
1315
1316
1317 /*-----------------------------------------------------------------*/
1318 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1319 /*-----------------------------------------------------------------*/
1320 pCodeOp *pic16_popGetTempReg(void)
1321 {
1322   pCodeOp *pcop;
1323   symbol *cfunc;
1324
1325 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1326
1327         cfunc = currFunc;
1328         currFunc = NULL;
1329
1330         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1331         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1332                 PCOR(pcop)->r->wasUsed=1;
1333                 PCOR(pcop)->r->isFree=0;
1334
1335                 /* push value on stack */
1336                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1337         }
1338
1339         currFunc = cfunc;
1340
1341   return pcop;
1342 }
1343
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1346 /*-----------------------------------------------------------------*/
1347 void pic16_popReleaseTempReg(pCodeOp *pcop)
1348 {
1349         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1350
1351         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1352                 PCOR(pcop)->r->isFree = 1;
1353                 
1354                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1355         }
1356 }
1357 /*-----------------------------------------------------------------*/
1358 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1359 /*-----------------------------------------------------------------*/
1360 pCodeOp *pic16_popGetLabel(unsigned int key)
1361 {
1362
1363   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1364
1365   if(key>max_key)
1366     max_key = key;
1367
1368   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1369 }
1370
1371 /*-----------------------------------------------------------------*/
1372 /* pic16_popCopyReg - copy a pcode operator                              */
1373 /*-----------------------------------------------------------------*/
1374 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1375 {
1376   pCodeOpReg *pcor;
1377
1378   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1379   pcor->pcop.type = pc->pcop.type;
1380   if(pc->pcop.name) {
1381     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1382       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1383   } else
1384     pcor->pcop.name = NULL;
1385
1386   pcor->r = pc->r;
1387   pcor->rIdx = pc->rIdx;
1388   pcor->r->wasUsed=1;
1389
1390 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1391
1392   return PCOP(pcor);
1393 }
1394
1395 /*-----------------------------------------------------------------*/
1396 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1397 /*-----------------------------------------------------------------*/
1398 pCodeOp *pic16_popGetLit(unsigned int lit)
1399 {
1400   return pic16_newpCodeOpLit(lit);
1401 }
1402
1403 /*-----------------------------------------------------------------*/
1404 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1405 /*-----------------------------------------------------------------*/
1406 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1407 {
1408   return pic16_newpCodeOpLit2(lit, arg2);
1409 }
1410
1411
1412 /*-----------------------------------------------------------------*/
1413 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1414 /*-----------------------------------------------------------------*/
1415 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1416 {
1417   return pic16_newpCodeOpImmd(name, offset,index, 0);
1418 }
1419
1420
1421 /*-----------------------------------------------------------------*/
1422 /* pic16_popGet - asm operator to pcode operator conversion              */
1423 /*-----------------------------------------------------------------*/
1424 pCodeOp *pic16_popGetWithString(char *str)
1425 {
1426   pCodeOp *pcop;
1427
1428
1429   if(!str) {
1430     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1431     exit (1);
1432   }
1433
1434   pcop = pic16_newpCodeOp(str,PO_STR);
1435
1436   return pcop;
1437 }
1438
1439 /*-----------------------------------------------------------------*/
1440 /* pic16_popRegFromString -                                        */
1441 /*-----------------------------------------------------------------*/
1442 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1443 {
1444
1445   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1446   pcop->type = PO_DIR;
1447
1448   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1449   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1450
1451   if(!str)
1452     str = "BAD_STRING";
1453
1454   pcop->name = Safe_calloc(1,strlen(str)+1);
1455   strcpy(pcop->name,str);
1456
1457   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1458
1459   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1460   if(PCOR(pcop)->r == NULL) {
1461 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1462 //              __FUNCTION__, __LINE__, str, size, offset);
1463     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1464
1465         //fprintf(stderr, "allocating new register -> %s\n", str);
1466
1467 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1468   } else {
1469 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1470   }
1471   PCOR(pcop)->instance = offset;
1472
1473   return pcop;
1474 }
1475
1476 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1477 {
1478   pCodeOp *pcop;
1479
1480 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1481
1482         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1483         PCOR(pcop)->rIdx = rIdx;
1484         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1485         PCOR(pcop)->r->isFree = 0;
1486         PCOR(pcop)->r->wasUsed = 1;
1487
1488         pcop->type = PCOR(pcop)->r->pc_type;
1489
1490   return pcop;
1491 }
1492
1493 /*---------------------------------------------------------------------------------*/
1494 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1495 /*                 VR 030601                                                       */
1496 /*---------------------------------------------------------------------------------*/
1497 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1498 {
1499   pCodeOpReg2 *pcop2;
1500   pCodeOp *temp;
1501   
1502         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1503
1504         /* comment the following check, so errors to throw up */
1505 //      if(!pcop2)return NULL;
1506
1507         temp = pic16_popGet(aop_dst, offset);
1508         pcop2->pcop2 = temp;
1509         
1510   return PCOP(pcop2);
1511 }
1512
1513
1514
1515 /*--------------------------------------------------------------------------------.-*/
1516 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1517 /*                  VR 030601 , adapted by Hans Dorn                                */
1518 /*--------------------------------------------------------------------------------.-*/
1519 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1520 {
1521   pCodeOpReg2 *pcop2;
1522  
1523         pcop2 = (pCodeOpReg2 *)src;
1524         pcop2->pcop2 = dst;
1525         
1526         return PCOP(pcop2);
1527 }
1528
1529
1530
1531 /*---------------------------------------------------------------------------------*/
1532 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1533 /*                     movff instruction                                           */
1534 /*---------------------------------------------------------------------------------*/
1535 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1536 {
1537   pCodeOpReg2 *pcop2;
1538
1539         if(!noalloc) {
1540                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1541                 pcop2->pcop2 = pic16_popCopyReg(dst);
1542         } else {
1543                 /* the pCodeOp may be already allocated */
1544                 pcop2 = (pCodeOpReg2 *)(src);
1545                 pcop2->pcop2 = (pCodeOp *)(dst);
1546         }
1547
1548   return PCOP(pcop2);
1549 }
1550
1551
1552 /*-----------------------------------------------------------------*/
1553 /* pic16_popGet - asm operator to pcode operator conversion              */
1554 /*-----------------------------------------------------------------*/
1555 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1556 {
1557   //char *s = buffer ;
1558   char *rs;
1559   pCodeOp *pcop;
1560
1561     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1562     /* offset is greater than
1563     size then zero */
1564
1565 //    if (offset > (aop->size - 1) &&
1566 //        aop->type != AOP_LIT)
1567 //      return NULL;  //zero;
1568
1569     /* depending on type */
1570     switch (aop->type) {
1571         
1572     case AOP_R0:
1573     case AOP_R1:
1574     case AOP_DPTR:
1575     case AOP_DPTR2:
1576         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1577         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1578         assert( 0 );
1579         return NULL;
1580
1581
1582
1583     case AOP_IMMD:
1584       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1585       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1586
1587     case AOP_ACC:
1588       {
1589         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1590
1591         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1592
1593         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1594         
1595         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1596         PCOR(pcop)->rIdx = rIdx;
1597         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1598         PCOR(pcop)->r->wasUsed=1;
1599         PCOR(pcop)->r->isFree=0;
1600
1601         PCOR(pcop)->instance = offset;
1602         pcop->type = PCOR(pcop)->r->pc_type;
1603 //      rs = aop->aopu.aop_reg[offset]->name;
1604 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1605         return pcop;
1606
1607
1608 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1609 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1610
1611 //      assert( 0 );
1612       }
1613         
1614     case AOP_DIR:
1615       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1616       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1617         
1618     case AOP_REG:
1619       {
1620         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1621
1622         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1623         
1624         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1625         PCOR(pcop)->rIdx = rIdx;
1626         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1627         PCOR(pcop)->r->wasUsed=1;
1628         PCOR(pcop)->r->isFree=0;
1629
1630         PCOR(pcop)->instance = offset;
1631         pcop->type = PCOR(pcop)->r->pc_type;
1632         rs = aop->aopu.aop_reg[offset]->name;
1633         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1634         return pcop;
1635       }
1636
1637     case AOP_CRY:
1638         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1639
1640       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1641       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1642       //if(PCOR(pcop)->r == NULL)
1643       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1644       return pcop;
1645         
1646     case AOP_LIT:
1647         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1648       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1649
1650     case AOP_STR:
1651       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1652       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1653
1654       /*
1655       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1656       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1657       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1658       pcop->type = PCOR(pcop)->r->pc_type;
1659       pcop->name = PCOR(pcop)->r->name;
1660
1661       return pcop;
1662       */
1663
1664     case AOP_PCODE:
1665       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1666                           __LINE__, 
1667                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1668       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1669 #if 1
1670         switch( aop->aopu.pcop->type ) {
1671                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1672                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1673                 default:
1674                         assert( 0 );    /* should never reach here */;
1675         }
1676 #else
1677       PCOI(pcop)->offset = offset;
1678 #endif
1679       return pcop;
1680     }
1681
1682     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1683            "pic16_popGet got unsupported aop->type");
1684     exit(0);
1685 }
1686 /*-----------------------------------------------------------------*/
1687 /* pic16_aopPut - puts a string for a aop                                */
1688 /*-----------------------------------------------------------------*/
1689 void pic16_aopPut (asmop *aop, char *s, int offset)
1690 {
1691     char *d = buffer ;
1692     symbol *lbl ;
1693
1694     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1695
1696     if (aop->size && offset > ( aop->size - 1)) {
1697         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1698                "pic16_aopPut got offset > aop->size");
1699         exit(0);
1700     }
1701
1702     /* will assign value to value */
1703     /* depending on where it is ofcourse */
1704     switch (aop->type) {
1705     case AOP_DIR:
1706       if (offset) {
1707         sprintf(d,"(%s + %d)",
1708                 aop->aopu.aop_dir,offset);
1709         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1710
1711       } else
1712             sprintf(d,"%s",aop->aopu.aop_dir);
1713         
1714         if (strcmp(d,s)) {
1715           DEBUGpic16_emitcode(";","%d",__LINE__);
1716           if(strcmp(s,"W"))
1717             pic16_emitcode("movf","%s,w",s);
1718           pic16_emitcode("movwf","%s",d);
1719
1720           if(strcmp(s,"W")) {
1721             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1722             if(offset >= aop->size) {
1723               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1724               break;
1725             } else
1726               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1727           }
1728
1729           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1730
1731
1732         }
1733         break;
1734         
1735     case AOP_REG:
1736       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1737         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1738           /*
1739             if (*s == '@'           ||
1740                 strcmp(s,"r0") == 0 ||
1741                 strcmp(s,"r1") == 0 ||
1742                 strcmp(s,"r2") == 0 ||
1743                 strcmp(s,"r3") == 0 ||
1744                 strcmp(s,"r4") == 0 ||
1745                 strcmp(s,"r5") == 0 ||
1746                 strcmp(s,"r6") == 0 || 
1747                 strcmp(s,"r7") == 0 )
1748                 pic16_emitcode("mov","%s,%s  ; %d",
1749                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1750             else
1751           */
1752
1753           if(strcmp(s,"W")==0 )
1754             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1755
1756           pic16_emitcode("movwf","%s",
1757                    aop->aopu.aop_reg[offset]->name);
1758
1759           if(strcmp(s,zero)==0) {
1760             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1761
1762           } else if(strcmp(s,"W")==0) {
1763             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1764             pcop->type = PO_GPR_REGISTER;
1765
1766             PCOR(pcop)->rIdx = -1;
1767             PCOR(pcop)->r = NULL;
1768
1769             DEBUGpic16_emitcode(";","%d",__LINE__);
1770             pcop->name = Safe_strdup(s);
1771             pic16_emitpcode(POC_MOVFW,pcop);
1772             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1773           } else if(strcmp(s,one)==0) {
1774             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1775             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1776           } else {
1777             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1778           }
1779         }
1780         break;
1781         
1782     case AOP_DPTR:
1783     case AOP_DPTR2:
1784     
1785     if (aop->type == AOP_DPTR2)
1786     {
1787         genSetDPTR(1);
1788     }
1789     
1790         if (aop->code) {
1791             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1792                    "pic16_aopPut writting to code space");
1793             exit(0);
1794         }
1795         
1796         while (offset > aop->coff) {
1797             aop->coff++;
1798             pic16_emitcode ("inc","dptr");
1799         }
1800         
1801         while (offset < aop->coff) {
1802             aop->coff-- ;
1803             pic16_emitcode("lcall","__decdptr");
1804         }
1805         
1806         aop->coff = offset;
1807         
1808         /* if not in accumulater */
1809         MOVA(s);        
1810         
1811         pic16_emitcode ("movx","@dptr,a");
1812         
1813     if (aop->type == AOP_DPTR2)
1814     {
1815         genSetDPTR(0);
1816     }
1817         break;
1818         
1819     case AOP_R0:
1820     case AOP_R1:
1821         while (offset > aop->coff) {
1822             aop->coff++;
1823             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1824         }
1825         while (offset < aop->coff) {
1826             aop->coff-- ;
1827             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1828         }
1829         aop->coff = offset;
1830         
1831         if (aop->paged) {
1832             MOVA(s);           
1833             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1834             
1835         } else
1836             if (*s == '@') {
1837                 MOVA(s);
1838                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1839             } else
1840                 if (strcmp(s,"r0") == 0 ||
1841                     strcmp(s,"r1") == 0 ||
1842                     strcmp(s,"r2") == 0 ||
1843                     strcmp(s,"r3") == 0 ||
1844                     strcmp(s,"r4") == 0 ||
1845                     strcmp(s,"r5") == 0 ||
1846                     strcmp(s,"r6") == 0 || 
1847                     strcmp(s,"r7") == 0 ) {
1848                     char buffer[10];
1849                     sprintf(buffer,"a%s",s);
1850                     pic16_emitcode("mov","@%s,%s",
1851                              aop->aopu.aop_ptr->name,buffer);
1852                 } else
1853                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1854         
1855         break;
1856         
1857     case AOP_STK:
1858         if (strcmp(s,"a") == 0)
1859             pic16_emitcode("push","acc");
1860         else
1861             pic16_emitcode("push","%s",s);
1862         
1863         break;
1864         
1865     case AOP_CRY:
1866         /* if bit variable */
1867         if (!aop->aopu.aop_dir) {
1868             pic16_emitcode("clr","a");
1869             pic16_emitcode("rlc","a");
1870         } else {
1871             if (s == zero) 
1872                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1873             else
1874                 if (s == one)
1875                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1876                 else
1877                     if (!strcmp(s,"c"))
1878                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1879                     else {
1880                         lbl = newiTempLabel(NULL);
1881                         
1882                         if (strcmp(s,"a")) {
1883                             MOVA(s);
1884                         }
1885                         pic16_emitcode("clr","c");
1886                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1887                         pic16_emitcode("cpl","c");
1888                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1889                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1890                     }
1891         }
1892         break;
1893         
1894     case AOP_STR:
1895         aop->coff = offset;
1896         if (strcmp(aop->aopu.aop_str[offset],s))
1897             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1898         break;
1899         
1900     case AOP_ACC:
1901         aop->coff = offset;
1902         if (!offset && (strcmp(s,"acc") == 0))
1903             break;
1904         
1905         if (strcmp(aop->aopu.aop_str[offset],s))
1906             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1907         break;
1908
1909     default :
1910         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1911                "pic16_aopPut got unsupported aop->type");
1912         exit(0);    
1913     }    
1914
1915 }
1916
1917 /*-----------------------------------------------------------------*/
1918 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1919 /*-----------------------------------------------------------------*/
1920 static void mov2w (asmop *aop, int offset)
1921 {
1922
1923 //  if(!aop)
1924 //    return;
1925
1926         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1927
1928         if(is_LitAOp(aop))
1929                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1930         else
1931                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1932
1933 }
1934
1935
1936 /* push pcop into stack */
1937 void pic16_pushpCodeOp(pCodeOp *pcop)
1938 {
1939 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1940         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1941 }
1942
1943 /* pop pcop from stack */
1944 void pic16_poppCodeOp(pCodeOp *pcop)
1945 {
1946         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1947 }
1948
1949
1950 /*-----------------------------------------------------------------*/
1951 /* pushw - pushes wreg to stack                                    */
1952 /*-----------------------------------------------------------------*/
1953 void pushw(void)
1954 {
1955         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1956         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1957 }
1958
1959                 
1960 /*-----------------------------------------------------------------*/
1961 /* pushaop - pushes aop to stack                                   */
1962 /*-----------------------------------------------------------------*/
1963 void pushaop(asmop *aop, int offset)
1964 {
1965         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1966         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1967 }
1968
1969 /*-----------------------------------------------------------------*/
1970 /* popaop - pops aop from stack                                    */
1971 /*-----------------------------------------------------------------*/
1972 void popaop(asmop *aop, int offset)
1973 {
1974         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1975         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1976 }
1977
1978 void popaopidx(asmop *aop, int offset, int index)
1979 {
1980   int ofs=1;
1981
1982         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1983
1984         if(STACK_MODEL_LARGE)ofs++;
1985
1986         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1987         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1988 }
1989
1990 /*-----------------------------------------------------------------*/
1991 /* reAdjustPreg - points a register back to where it should        */
1992 /*-----------------------------------------------------------------*/
1993 static void reAdjustPreg (asmop *aop)
1994 {
1995     int size ;
1996
1997     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1998     aop->coff = 0;
1999     if ((size = aop->size) <= 1)
2000         return ;
2001     size-- ;
2002     switch (aop->type) {
2003         case AOP_R0 :
2004         case AOP_R1 :
2005             while (size--)
2006                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2007             break;          
2008         case AOP_DPTR :
2009         case AOP_DPTR2:
2010             if (aop->type == AOP_DPTR2)
2011             {
2012                 genSetDPTR(1);
2013             } 
2014             while (size--)
2015             {
2016                 pic16_emitcode("lcall","__decdptr");
2017             }
2018                 
2019             if (aop->type == AOP_DPTR2)
2020             {
2021                 genSetDPTR(0);
2022             }                
2023             break;  
2024
2025     }   
2026
2027 }
2028
2029
2030 #if 0
2031 /*-----------------------------------------------------------------*/
2032 /* opIsGptr: returns non-zero if the passed operand is             */   
2033 /* a generic pointer type.                                         */
2034 /*-----------------------------------------------------------------*/ 
2035 static int opIsGptr(operand *op)
2036 {
2037     sym_link *type = operandType(op);
2038     
2039     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2040     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2041     {
2042         return 1;
2043     }
2044     return 0;        
2045 }
2046 #endif
2047
2048 /*-----------------------------------------------------------------*/
2049 /* pic16_getDataSize - get the operand data size                         */
2050 /*-----------------------------------------------------------------*/
2051 int pic16_getDataSize(operand *op)
2052 {
2053     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2054
2055
2056     return AOP_SIZE(op);
2057
2058     // tsd- in the pic port, the genptr size is 1, so this code here
2059     // fails. ( in the 8051 port, the size was 4).
2060 #if 0
2061     int size;
2062     size = AOP_SIZE(op);
2063     if (size == GPTRSIZE)
2064     {
2065         sym_link *type = operandType(op);
2066         if (IS_GENPTR(type))
2067         {
2068             /* generic pointer; arithmetic operations
2069              * should ignore the high byte (pointer type).
2070              */
2071             size--;
2072     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2073         }
2074     }
2075     return size;
2076 #endif
2077 }
2078
2079 /*-----------------------------------------------------------------*/
2080 /* pic16_outAcc - output Acc                                             */
2081 /*-----------------------------------------------------------------*/
2082 void pic16_outAcc(operand *result)
2083 {
2084   int size,offset;
2085   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2086   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2087
2088
2089   size = pic16_getDataSize(result);
2090   if(size){
2091     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2092     size--;
2093     offset = 1;
2094     /* unsigned or positive */
2095     while(size--)
2096       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2097   }
2098
2099 }
2100
2101 /*-----------------------------------------------------------------*/
2102 /* pic16_outBitC - output a bit C                                  */
2103 /*                 Move to result the value of Carry flag -- VR    */
2104 /*-----------------------------------------------------------------*/
2105 void pic16_outBitC(operand *result)
2106 {
2107   int i;
2108
2109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2110     /* if the result is bit */
2111     if (AOP_TYPE(result) == AOP_CRY) {
2112         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2113         pic16_aopPut(AOP(result),"c",0);
2114     } else {
2115
2116         i = AOP_SIZE(result);
2117         while(i--) {
2118                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2119         }
2120         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2121         
2122 /*
2123         pic16_emitcode("clr","a  ; %d", __LINE__);
2124         pic16_emitcode("rlc","a");
2125         pic16_outAcc(result);
2126 */
2127     }
2128 }
2129
2130 /*-----------------------------------------------------------------*/
2131 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2132 /*-----------------------------------------------------------------*/
2133 void pic16_toBoolean(operand *oper)
2134 {
2135     int size = AOP_SIZE(oper) - 1;
2136     int offset = 1;
2137
2138     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2139
2140     if ( AOP_TYPE(oper) != AOP_ACC) {
2141       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2142     }
2143     while (size--) {
2144       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2145     }
2146 }
2147
2148
2149 #if !defined(GEN_Not)
2150 /*-----------------------------------------------------------------*/
2151 /* genNot - generate code for ! operation                          */
2152 /*-----------------------------------------------------------------*/
2153 static void pic16_genNot (iCode *ic)
2154 {
2155   symbol *tlbl;
2156   int size;
2157
2158   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2159   /* assign asmOps to operand & result */
2160   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2161   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2162
2163   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2164   /* if in bit space then a special case */
2165   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2166     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2167       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2168       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2169     } else {
2170       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2171       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2172       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2173     }
2174     goto release;
2175   }
2176
2177   size = AOP_SIZE(IC_LEFT(ic));
2178   if(size == 1) {
2179     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2180     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2181     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2182     goto release;
2183   }
2184   pic16_toBoolean(IC_LEFT(ic));
2185
2186   tlbl = newiTempLabel(NULL);
2187   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2188   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2189   pic16_outBitC(IC_RESULT(ic));
2190
2191  release:    
2192   /* release the aops */
2193   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2194   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2195 }
2196 #endif
2197
2198
2199 #if !defined(GEN_Cpl)
2200 /*-----------------------------------------------------------------*/
2201 /* genCpl - generate code for complement                           */
2202 /*-----------------------------------------------------------------*/
2203 static void pic16_genCpl (iCode *ic)
2204 {
2205     int offset = 0;
2206     int size ;
2207
2208
2209     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2210     /* assign asmOps to operand & result */
2211     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2212     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2213
2214     /* if both are in bit space then 
2215     a special case */
2216     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2217         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2218
2219         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2220         pic16_emitcode("cpl","c"); 
2221         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2222         goto release; 
2223     } 
2224
2225     size = AOP_SIZE(IC_RESULT(ic));
2226     while (size--) {
2227 /*
2228         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2229         MOVA(l);       
2230         pic16_emitcode("cpl","a");
2231         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2232 */
2233         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2234               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2235         } else {
2236                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2237                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2238         }
2239         offset++;
2240
2241     }
2242
2243
2244 release:
2245     /* release the aops */
2246     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2247     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2248 }
2249 #endif
2250
2251 /*-----------------------------------------------------------------*/
2252 /* genUminusFloat - unary minus for floating points                */
2253 /*-----------------------------------------------------------------*/
2254 static void genUminusFloat(operand *op,operand *result)
2255 {
2256     int size ,offset =0 ;
2257     char *l;
2258
2259     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2260     /* for this we just need to flip the 
2261     first it then copy the rest in place */
2262     size = AOP_SIZE(op) - 1;
2263     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2264
2265     MOVA(l);    
2266
2267     pic16_emitcode("cpl","acc.7");
2268     pic16_aopPut(AOP(result),"a",3);    
2269
2270     while(size--) {
2271         pic16_aopPut(AOP(result),
2272                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2273                offset);
2274         offset++;
2275     }          
2276 }
2277
2278 /*-----------------------------------------------------------------*/
2279 /* genUminus - unary minus code generation                         */
2280 /*-----------------------------------------------------------------*/
2281 static void genUminus (iCode *ic)
2282 {
2283   int size, i;
2284   sym_link *optype, *rtype;
2285
2286         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2287         
2288         /* assign asmops */
2289         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2290         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2291
2292         /* if both in bit space then special case */
2293         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2294                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2295
2296                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2297                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2298                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2299                 
2300                 goto release; 
2301         } 
2302
2303         optype = operandType(IC_LEFT(ic));
2304         rtype = operandType(IC_RESULT(ic));
2305
2306         /* if float then do float stuff */
2307         if (IS_FLOAT(optype)) {
2308                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2309                 goto release;
2310         }
2311
2312         /* otherwise subtract from zero by taking the 2's complement */
2313         size = AOP_SIZE(IC_LEFT(ic));
2314
2315         for(i=0; i<size; i++) {
2316                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2317                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2318                 else {
2319                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2320                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2321                 }
2322         }
2323
2324         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2325         for(i=1; i<size; i++) {
2326                 emitSKPNZ;
2327                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2328         }
2329
2330 release:
2331         /* release the aops */
2332         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2333         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2334 }
2335
2336 /*-----------------------------------------------------------------*/
2337 /* saveRegisters - will look for a call and save the registers     */
2338 /*-----------------------------------------------------------------*/
2339 static void saveRegisters(iCode *lic) 
2340 {
2341     int i;
2342     iCode *ic;
2343     bitVect *rsave;
2344     sym_link *dtype;
2345
2346     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2347     /* look for call */
2348     for (ic = lic ; ic ; ic = ic->next) 
2349         if (ic->op == CALL || ic->op == PCALL)
2350             break;
2351
2352     if (!ic) {
2353         fprintf(stderr,"found parameter push with no function call\n");
2354         return ;
2355     }
2356
2357     /* if the registers have been saved already then
2358     do nothing */
2359     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2360         return ;
2361
2362     /* find the registers in use at this time 
2363     and push them away to safety */
2364     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2365                           ic->rUsed);
2366
2367     ic->regsSaved = 1;
2368     if (options.useXstack) {
2369         if (bitVectBitValue(rsave,R0_IDX))
2370             pic16_emitcode("mov","b,r0");
2371         pic16_emitcode("mov","r0,%s",spname);
2372         for (i = 0 ; i < pic16_nRegs ; i++) {
2373             if (bitVectBitValue(rsave,i)) {
2374                 if (i == R0_IDX)
2375                     pic16_emitcode("mov","a,b");
2376                 else
2377                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2378                 pic16_emitcode("movx","@r0,a");
2379                 pic16_emitcode("inc","r0");
2380             }
2381         }
2382         pic16_emitcode("mov","%s,r0",spname);
2383         if (bitVectBitValue(rsave,R0_IDX))
2384             pic16_emitcode("mov","r0,b");           
2385     }// else
2386     //for (i = 0 ; i < pic16_nRegs ; i++) {
2387     //    if (bitVectBitValue(rsave,i))
2388     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2389     //}
2390
2391     dtype = operandType(IC_LEFT(ic));
2392     if (currFunc && dtype && 
2393         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2394         IFFUNC_ISISR(currFunc->type) &&
2395         !ic->bankSaved) 
2396
2397         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2398
2399 }
2400 /*-----------------------------------------------------------------*/
2401 /* unsaveRegisters - pop the pushed registers                      */
2402 /*-----------------------------------------------------------------*/
2403 static void unsaveRegisters (iCode *ic)
2404 {
2405     int i;
2406     bitVect *rsave;
2407
2408     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2409     /* find the registers in use at this time 
2410     and push them away to safety */
2411     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2412                           ic->rUsed);
2413     
2414     if (options.useXstack) {
2415         pic16_emitcode("mov","r0,%s",spname);   
2416         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2417             if (bitVectBitValue(rsave,i)) {
2418                 pic16_emitcode("dec","r0");
2419                 pic16_emitcode("movx","a,@r0");
2420                 if (i == R0_IDX)
2421                     pic16_emitcode("mov","b,a");
2422                 else
2423                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2424             }       
2425
2426         }
2427         pic16_emitcode("mov","%s,r0",spname);
2428         if (bitVectBitValue(rsave,R0_IDX))
2429             pic16_emitcode("mov","r0,b");
2430     } //else
2431     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2432     //    if (bitVectBitValue(rsave,i))
2433     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2434     //}
2435
2436 }  
2437
2438 #if 0  // patch 14
2439 /*-----------------------------------------------------------------*/
2440 /* pushSide -                                                      */
2441 /*-----------------------------------------------------------------*/
2442 static void pushSide(operand * oper, int size)
2443 {
2444         int offset = 0;
2445     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2446         while (size--) {
2447                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2448                 if (AOP_TYPE(oper) != AOP_REG &&
2449                     AOP_TYPE(oper) != AOP_DIR &&
2450                     strcmp(l,"a") ) {
2451                         pic16_emitcode("mov","a,%s",l);
2452                         pic16_emitcode("push","acc");
2453                 } else
2454                         pic16_emitcode("push","%s",l);
2455         }
2456 }
2457 #endif // patch 14
2458
2459 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2460 {
2461 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2462
2463         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2464                 pic16_emitpcode(POC_MOVFW, src);
2465                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2466         } else {
2467                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2468                         src, pic16_popGet(AOP(op), offset)));
2469         }
2470 }
2471
2472
2473 /*-----------------------------------------------------------------*/
2474 /* assignResultValue - assign results to oper, rescall==1 is       */
2475 /*                     called from genCall() or genPCall()         */
2476 /*-----------------------------------------------------------------*/
2477 static void assignResultValue(operand * oper, int rescall)
2478 {
2479   int size = AOP_SIZE(oper);
2480
2481         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2482         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2483
2484         if(rescall) {
2485                 /* assign result from a call/pcall function() */
2486                 
2487                 /* function results are stored in a special order,
2488                  * see top of file with Function return policy, or manual */
2489
2490                 if(size <= 4) {
2491                         /* 8-bits, result in WREG */
2492                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2493                         
2494                         if(size>1) {
2495                                 /* 16-bits, result in PRODL:WREG */
2496                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2497                         }
2498                         
2499                         if(size>2) {
2500                                 /* 24-bits, result in PRODH:PRODL:WREG */
2501                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2502                         }
2503                         
2504                         if(size>3) {
2505                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2506                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2507                         }
2508                 } else {
2509                         /* >32-bits, result on stack, and FSR0 points to beginning.
2510                          * Fix stack when done */
2511                          
2512                         while (size--) {
2513 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2514 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2515                 
2516                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2517                                 GpsuedoStkPtr++;
2518                         }
2519                         
2520                         /* fix stack */
2521                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2522                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2523                         if(STACK_MODEL_LARGE) {
2524                                 emitSKPNC;
2525                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2526                         }
2527                 }                       
2528         } else {        
2529                 if(!GpsuedoStkPtr) {
2530 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2531                         /* The last byte in the assignment is in W */
2532                         size--;
2533                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2534                         GpsuedoStkPtr++;
2535                 }
2536
2537                 while (size--) {
2538 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2539 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2540                 
2541                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2542                         GpsuedoStkPtr++;
2543
2544 #if 0
2545 #if STACK_SUPPORT
2546                 if(!USE_STACK)
2547                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2548 #else
2549                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2550 #endif
2551 #endif
2552
2553                 }
2554         }
2555                 
2556 }
2557
2558
2559 /*-----------------------------------------------------------------*/
2560 /* genIpush - genrate code for pushing this gets a little complex  */
2561 /*-----------------------------------------------------------------*/
2562 static void genIpush (iCode *ic)
2563 {
2564
2565   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2566 #if 0
2567     int size, offset = 0 ;
2568     char *l;
2569
2570
2571     /* if this is not a parm push : ie. it is spill push 
2572     and spill push is always done on the local stack */
2573     if (!ic->parmPush) {
2574
2575         /* and the item is spilt then do nothing */
2576         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2577             return ;
2578
2579         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2580         size = AOP_SIZE(IC_LEFT(ic));
2581         /* push it on the stack */
2582         while(size--) {
2583             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2584             if (*l == '#') {
2585                 MOVA(l);
2586                 l = "acc";
2587             }
2588             pic16_emitcode("push","%s",l);
2589         }
2590         return ;        
2591     }
2592
2593     /* this is a paramter push: in this case we call
2594     the routine to find the call and save those
2595     registers that need to be saved */   
2596     saveRegisters(ic);
2597
2598     /* then do the push */
2599     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2600
2601
2602         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2603     size = AOP_SIZE(IC_LEFT(ic));
2604
2605     while (size--) {
2606         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2607         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2608             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2609             strcmp(l,"a") ) {
2610             pic16_emitcode("mov","a,%s",l);
2611             pic16_emitcode("push","acc");
2612         } else
2613             pic16_emitcode("push","%s",l);
2614     }       
2615
2616     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2617 #endif
2618 }
2619
2620 /*-----------------------------------------------------------------*/
2621 /* genIpop - recover the registers: can happen only for spilling   */
2622 /*-----------------------------------------------------------------*/
2623 static void genIpop (iCode *ic)
2624 {
2625   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2626 #if 0
2627     int size,offset ;
2628
2629
2630     /* if the temp was not pushed then */
2631     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2632         return ;
2633
2634     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2635     size = AOP_SIZE(IC_LEFT(ic));
2636     offset = (size-1);
2637     while (size--) 
2638         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2639                                    FALSE,TRUE));
2640
2641     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2642 #endif
2643 }
2644
2645 /*-----------------------------------------------------------------*/
2646 /* unsaverbank - restores the resgister bank from stack            */
2647 /*-----------------------------------------------------------------*/
2648 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2649 {
2650   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2651 #if 0
2652     int i;
2653     asmop *aop ;
2654     regs *r = NULL;
2655
2656     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2657     if (popPsw) {
2658         if (options.useXstack) {
2659             aop = newAsmop(0);
2660             r = getFreePtr(ic,&aop,FALSE);
2661             
2662             
2663             pic16_emitcode("mov","%s,_spx",r->name);
2664             pic16_emitcode("movx","a,@%s",r->name);
2665             pic16_emitcode("mov","psw,a");
2666             pic16_emitcode("dec","%s",r->name);
2667             
2668         }else
2669             pic16_emitcode ("pop","psw");
2670     }
2671
2672     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2673         if (options.useXstack) {       
2674             pic16_emitcode("movx","a,@%s",r->name);
2675             //pic16_emitcode("mov","(%s+%d),a",
2676             //       regspic16[i].base,8*bank+regspic16[i].offset);
2677             pic16_emitcode("dec","%s",r->name);
2678
2679         } else 
2680           pic16_emitcode("pop",""); //"(%s+%d)",
2681         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2682     }
2683
2684     if (options.useXstack) {
2685
2686         pic16_emitcode("mov","_spx,%s",r->name);
2687         pic16_freeAsmop(NULL,aop,ic,TRUE);
2688
2689     }
2690 #endif 
2691 }
2692
2693 /*-----------------------------------------------------------------*/
2694 /* saverbank - saves an entire register bank on the stack          */
2695 /*-----------------------------------------------------------------*/
2696 static void saverbank (int bank, iCode *ic, bool pushPsw)
2697 {
2698   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2699 #if 0
2700     int i;
2701     asmop *aop ;
2702     regs *r = NULL;
2703
2704     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2705     if (options.useXstack) {
2706
2707         aop = newAsmop(0);
2708         r = getFreePtr(ic,&aop,FALSE);  
2709         pic16_emitcode("mov","%s,_spx",r->name);
2710
2711     }
2712
2713     for (i = 0 ; i < pic16_nRegs ;i++) {
2714         if (options.useXstack) {
2715             pic16_emitcode("inc","%s",r->name);
2716             //pic16_emitcode("mov","a,(%s+%d)",
2717             //         regspic16[i].base,8*bank+regspic16[i].offset);
2718             pic16_emitcode("movx","@%s,a",r->name);           
2719         } else 
2720           pic16_emitcode("push","");// "(%s+%d)",
2721                      //regspic16[i].base,8*bank+regspic16[i].offset);
2722     }
2723     
2724     if (pushPsw) {
2725         if (options.useXstack) {
2726             pic16_emitcode("mov","a,psw");
2727             pic16_emitcode("movx","@%s,a",r->name);     
2728             pic16_emitcode("inc","%s",r->name);
2729             pic16_emitcode("mov","_spx,%s",r->name);       
2730             pic16_freeAsmop (NULL,aop,ic,TRUE);
2731             
2732         } else
2733             pic16_emitcode("push","psw");
2734         
2735         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2736     }
2737     ic->bankSaved = 1;
2738 #endif
2739 }
2740
2741
2742
2743 /*-----------------------------------------------------------------*/
2744 /* genCall - generates a call statement                            */
2745 /*-----------------------------------------------------------------*/
2746 static void genCall (iCode *ic)
2747 {
2748   sym_link *dtype;   
2749   int stackParms=0;
2750   
2751         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2752
2753         /* if caller saves & we have not saved then */
2754         if (!ic->regsSaved)
2755                 saveRegisters(ic);
2756
2757         /* if we are calling a function that is not using
2758          * the same register bank then we need to save the
2759          * destination registers on the stack */
2760         dtype = operandType(IC_LEFT(ic));
2761         if (currFunc && dtype && 
2762                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2763                 IFFUNC_ISISR(currFunc->type) &&
2764                 !ic->bankSaved) 
2765
2766                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2767
2768         /* if send set is not empty the assign */
2769         if (_G.sendSet) {
2770           iCode *sic;
2771
2772                 /* For the Pic port, there is no data stack.
2773                  * So parameters passed to functions are stored
2774                  * in registers. (The pCode optimizer will get
2775                  * rid of most of these :). */
2776
2777           int psuedoStkPtr=-1; 
2778           int firstTimeThruLoop = 1;
2779
2780                 _G.sendSet = reverseSet(_G.sendSet);
2781
2782                 /* First figure how many parameters are getting passed */
2783                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2784                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2785                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2786                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2787                 }
2788
2789                 stackParms = psuedoStkPtr;
2790
2791                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2792                   int size, offset = 0;
2793
2794                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2795                         size = AOP_SIZE(IC_LEFT(sic));
2796
2797                         while (size--) {
2798                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2799                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2800                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2801
2802                                 if(!firstTimeThruLoop) {
2803                                         /* If this is not the first time we've been through the loop
2804                                          * then we need to save the parameter in a temporary
2805                                          * register. The last byte of the last parameter is
2806                                          * passed in W. */
2807
2808                                         pushw();
2809                                         --psuedoStkPtr;         // sanity check
2810                                 }
2811                         
2812                                 firstTimeThruLoop=0;
2813
2814                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2815                                 offset++;
2816                         }
2817                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2818                 }
2819                 _G.sendSet = NULL;
2820         }
2821
2822         /* make the call */
2823         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2824                         OP_SYMBOL(IC_LEFT(ic))->rname :
2825                         OP_SYMBOL(IC_LEFT(ic))->name));
2826
2827         GpsuedoStkPtr=0;
2828         /* if we need assign a result value */
2829         if ((IS_ITEMP(IC_RESULT(ic)) && 
2830                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2831                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2832                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2833
2834                 _G.accInUse++;
2835                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2836                 _G.accInUse--;
2837
2838                 assignResultValue(IC_RESULT(ic), 1);
2839
2840                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2841                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2842                 
2843                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2844         }
2845
2846         if(stackParms>0) {
2847                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2848                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2849                 if(STACK_MODEL_LARGE) {
2850                         emitSKPNC;
2851                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2852                 }
2853         }
2854
2855         /* adjust the stack for parameters if required */
2856 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2857
2858         if (ic->parmBytes) {
2859           int i;
2860
2861                 if (ic->parmBytes > 3) {
2862                         pic16_emitcode("mov","a,%s",spname);
2863                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2864                         pic16_emitcode("mov","%s,a",spname);
2865                 } else 
2866                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2867                                 pic16_emitcode("dec","%s",spname);
2868         }
2869
2870 #if 0
2871         /* if register bank was saved then pop them */
2872         if (ic->bankSaved)
2873                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2874
2875         /* if we hade saved some registers then unsave them */
2876         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2877                 unsaveRegisters (ic);
2878 #endif
2879 }
2880
2881
2882
2883 /*-----------------------------------------------------------------*/   // patch 14
2884 /* genPcall - generates a call by pointer statement                */
2885 /*-----------------------------------------------------------------*/
2886
2887 // new version, created from genCall
2888
2889 static void genPcall (iCode *ic)
2890 {
2891   sym_link *dtype;   
2892   int stackParms=0;
2893   symbol *retlbl = newiTempLabel(NULL);
2894   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2895   
2896         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2897
2898         /* if caller saves & we have not saved then */
2899         if (!ic->regsSaved)
2900                 saveRegisters(ic);
2901
2902         /* if we are calling a function that is not using
2903          * the same register bank then we need to save the
2904          * destination registers on the stack */
2905         dtype = operandType(IC_LEFT(ic));
2906         if (currFunc && dtype && 
2907                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2908                 IFFUNC_ISISR(currFunc->type) &&
2909                 !ic->bankSaved) 
2910
2911                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2912
2913         /* if send set is not empty the assign */
2914         if (_G.sendSet) {
2915           iCode *sic;
2916
2917                 /* For the Pic port, there is no data stack.
2918                  * So parameters passed to functions are stored
2919                  * in registers. (The pCode optimizer will get
2920                  * rid of most of these :). */
2921
2922           int psuedoStkPtr=-1; 
2923           int firstTimeThruLoop = 1;
2924
2925                 _G.sendSet = reverseSet(_G.sendSet);
2926
2927                 /* First figure how many parameters are getting passed */
2928                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2929                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2930                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2931                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2932                 }
2933
2934                 stackParms = psuedoStkPtr;
2935
2936                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2937                   int size, offset = 0;
2938
2939                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2940                         size = AOP_SIZE(IC_LEFT(sic));
2941
2942                         while (size--) {
2943                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2944                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2945                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2946
2947                                 if(!firstTimeThruLoop) {
2948                                         /* If this is not the first time we've been through the loop
2949                                          * then we need to save the parameter in a temporary
2950                                          * register. The last byte of the last parameter is
2951                                          * passed in W. */
2952
2953                                         pushw();
2954                                         --psuedoStkPtr;         // sanity check
2955                                 }
2956                         
2957                                 firstTimeThruLoop=0;
2958
2959                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2960                                 offset++;
2961                         }
2962                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2963                 }
2964                 _G.sendSet = NULL;
2965         }
2966
2967         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2968
2969         // push return address
2970         // push $ on return stack, then replace with retlbl
2971
2972         pic16_emitpcodeNULLop(POC_PUSH);
2973
2974         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2975         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2976         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2977         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2978         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2979         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2980
2981         /* make the call by writing the pointer into pc */
2982         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2983         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2984
2985         // note: MOVFF to PCL not allowed
2986         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2987         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2988
2989
2990 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2991 //      pic16_emitpcodeNULLop(POC_NOP);
2992 //      pic16_emitpcodeNULLop(POC_NOP);
2993
2994         /* return address is here: (X) */
2995         pic16_emitpLabelFORCE(retlbl->key);
2996
2997 //      pic16_emitpcodeNULLop(POC_NOP);
2998
2999         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3000
3001         GpsuedoStkPtr=0;
3002         /* if we need assign a result value */
3003         if ((IS_ITEMP(IC_RESULT(ic)) && 
3004                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3005                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3006                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3007
3008                 _G.accInUse++;
3009                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3010                 _G.accInUse--;
3011
3012                 assignResultValue(IC_RESULT(ic), 1);
3013
3014                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3015                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3016                 
3017                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3018         }
3019
3020         if(stackParms>0) {
3021                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3022                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3023                 if(STACK_MODEL_LARGE) {
3024                         emitSKPNC;
3025                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3026                 }
3027         }
3028
3029         /* adjust the stack for parameters if required */
3030 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3031
3032         if (ic->parmBytes) {
3033           int i;
3034
3035                 if (ic->parmBytes > 3) {
3036                         pic16_emitcode("mov","a,%s",spname);
3037                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3038                         pic16_emitcode("mov","%s,a",spname);
3039                 } else 
3040                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3041                                 pic16_emitcode("dec","%s",spname);
3042         }
3043
3044         /* if register bank was saved then pop them */
3045         if (ic->bankSaved)
3046                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3047
3048         /* if we hade saved some registers then unsave them */
3049         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3050                 unsaveRegisters (ic);
3051 }
3052
3053
3054 #if 0                                                                           // patch 14
3055 // old version, kept for reference
3056
3057 /*-----------------------------------------------------------------*/
3058 /* genPcall - generates a call by pointer statement                */
3059 /*-----------------------------------------------------------------*/
3060 static void genPcall (iCode *ic)
3061 {
3062     sym_link *dtype;
3063     symbol *rlbl = newiTempLabel(NULL);
3064
3065
3066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3067     /* if caller saves & we have not saved then */
3068     if (!ic->regsSaved)
3069         saveRegisters(ic);
3070
3071     /* if we are calling a function that is not using
3072     the same register bank then we need to save the
3073     destination registers on the stack */
3074     dtype = operandType(IC_LEFT(ic));
3075     if (currFunc && dtype && 
3076         IFFUNC_ISISR(currFunc->type) &&
3077         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3078         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3079
3080
3081     /* push the return address on to the stack */
3082     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3083     pic16_emitcode("push","acc");    
3084     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3085     pic16_emitcode("push","acc");
3086     
3087     if (options.model == MODEL_FLAT24)
3088     {
3089         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3090         pic16_emitcode("push","acc");    
3091     }
3092
3093     /* now push the calling address */
3094     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3095
3096     pushSide(IC_LEFT(ic), FPTRSIZE);
3097
3098     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3099
3100     /* if send set is not empty the assign */
3101     if (_G.sendSet) {
3102         iCode *sic ;
3103
3104         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3105              sic = setNextItem(_G.sendSet)) {
3106             int size, offset = 0;
3107             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3108             size = AOP_SIZE(IC_LEFT(sic));
3109             while (size--) {
3110                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3111                                 FALSE,FALSE);
3112                 if (strcmp(l,fReturn[offset]))
3113                     pic16_emitcode("mov","%s,%s",
3114                              fReturn[offset],
3115                              l);
3116                 offset++;
3117             }
3118             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3119         }
3120         _G.sendSet = NULL;
3121     }
3122
3123     pic16_emitcode("ret","");
3124     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3125
3126
3127     /* if we need assign a result value */
3128     if ((IS_ITEMP(IC_RESULT(ic)) &&
3129          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3130           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3131         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3132
3133         _G.accInUse++;
3134         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3135         _G.accInUse--;
3136         
3137         assignResultValue(IC_RESULT(ic), 1);
3138
3139         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3140     }
3141
3142     /* adjust the stack for parameters if 
3143     required */
3144     if (ic->parmBytes) {
3145         int i;
3146         if (ic->parmBytes > 3) {
3147             pic16_emitcode("mov","a,%s",spname);
3148             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3149             pic16_emitcode("mov","%s,a",spname);
3150         } else 
3151             for ( i = 0 ; i <  ic->parmBytes ;i++)
3152                 pic16_emitcode("dec","%s",spname);
3153
3154     }
3155
3156     /* if register bank was saved then unsave them */
3157     if (currFunc && dtype && 
3158         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3159         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3160
3161     /* if we hade saved some registers then
3162     unsave them */
3163     if (ic->regsSaved)
3164         unsaveRegisters (ic);
3165
3166 }
3167 #endif                                                                          // patch 14
3168
3169
3170 /*-----------------------------------------------------------------*/
3171 /* resultRemat - result  is rematerializable                       */
3172 /*-----------------------------------------------------------------*/
3173 static int resultRemat (iCode *ic)
3174 {
3175   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3176   if (SKIP_IC(ic) || ic->op == IFX)
3177     return 0;
3178
3179   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3180     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3181     if (sym->remat && !POINTER_SET(ic)) 
3182       return 1;
3183   }
3184
3185   return 0;
3186 }
3187
3188 #if defined(__BORLANDC__) || defined(_MSC_VER)
3189 #define STRCASECMP stricmp
3190 #else
3191 #define STRCASECMP strcasecmp
3192 #endif
3193
3194 #if 0
3195 /*-----------------------------------------------------------------*/
3196 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3197 /*-----------------------------------------------------------------*/
3198 static bool inExcludeList(char *s)
3199 {
3200   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3201     int i =0;
3202     
3203     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3204     if (options.excludeRegs[i] &&
3205     STRCASECMP(options.excludeRegs[i],"none") == 0)
3206         return FALSE ;
3207
3208     for ( i = 0 ; options.excludeRegs[i]; i++) {
3209         if (options.excludeRegs[i] &&
3210         STRCASECMP(s,options.excludeRegs[i]) == 0)
3211             return TRUE;
3212     }
3213     return FALSE ;
3214 }
3215 #endif
3216
3217 /*-----------------------------------------------------------------*/
3218 /* genFunction - generated code for function entry                 */
3219 /*-----------------------------------------------------------------*/
3220 static void genFunction (iCode *ic)
3221 {
3222   symbol *sym;
3223   sym_link *ftype;
3224   
3225         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3226
3227         labelOffset += (max_key+4);
3228         max_key=0;
3229         GpsuedoStkPtr=0;
3230         _G.nRegsSaved = 0;
3231
3232         ftype = operandType(IC_LEFT(ic));
3233         sym = OP_SYMBOL(IC_LEFT(ic));
3234
3235         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3236                 /* create an absolute section at the interrupt vector:
3237                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3238           symbol *asym;
3239           char asymname[128];
3240           pBlock *apb;
3241
3242                 {
3243                   int i, found=-1;
3244
3245                         sym = OP_SYMBOL( IC_LEFT(ic));
3246                         for(i=0;i<=2;i++) {
3247                                 if(interrupts[i]->name
3248                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3249                                         found = i;
3250                                         break;
3251                                 }
3252                         }
3253                         
3254                         if(found == -1) {
3255                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3256                                         __FILE__, __LINE__, sym->name);
3257                                 assert( 0 );
3258                         }
3259                         _G.interruptvector = found;
3260                 }
3261
3262                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3263                 asym = newSymbol(asymname, 0);
3264
3265                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3266                 pic16_addpBlock( apb );
3267
3268                 pic16_addpCode2pBlock(apb,
3269                         pic16_newpCodeCharP(";-----------------------------------------"));
3270
3271
3272                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3273
3274                 pic16_addpCode2pBlock(apb,
3275                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3276                 
3277                 /* mark the end of this tiny function */
3278                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3279
3280                 {
3281                   absSym *abSym;
3282
3283                         abSym = Safe_calloc(1, sizeof(absSym));
3284                         abSym->name = Safe_strdup( asymname );
3285
3286                         switch( _G.interruptvector ) {
3287                                 case 0: abSym->address = 0x000000; break;
3288                                 case 1: abSym->address = 0x000008; break;
3289                                 case 2: abSym->address = 0x000018; break;
3290                         }
3291
3292                         addSet(&absSymSet, abSym);
3293                 }
3294         }
3295
3296
3297         /* create the function header */
3298         pic16_emitcode(";","-----------------------------------------");
3299         pic16_emitcode(";"," function %s",sym->name);
3300         pic16_emitcode(";","-----------------------------------------");
3301
3302         pic16_emitcode("","%s:",sym->rname);
3303         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3304
3305
3306         {
3307           absSym *ab;
3308
3309                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3310                         if(!strcmp(ab->name, sym->name)) {
3311                                 pic16_pBlockConvert2Absolute(pb);
3312                                 break;
3313                         }
3314
3315         }
3316
3317
3318         if(IFFUNC_ISNAKED(ftype)) {
3319                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3320                 return;
3321         }
3322         
3323         /* if critical function then turn interrupts off */
3324         if (IFFUNC_ISCRITICAL(ftype))
3325                 pic16_emitcode("clr","ea");
3326
3327         /* if this is an interrupt service routine then
3328          * save acc, b, dpl, dph  */
3329         if (IFFUNC_ISISR(sym->type)) {
3330           int i;
3331                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3332                 if(!(_G.interruptvector == 1)) {
3333
3334                         /* do not save WREG,STATUS,BSR for high priority interrupts
3335                          * because they are stored in the hardware shadow registers already */
3336                          
3337                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3338                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3339                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3340                 }
3341
3342                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3343                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3344                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3345                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3346
3347 //                pic16_pBlockConvert2ISR(pb);
3348                 
3349                 /* if any registers used */
3350                 if (sym->regsUsed) {
3351                         /* save the registers used */
3352                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3353                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3354                                 if (bitVectBitValue(sym->regsUsed,i)) {
3355 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3356 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3357 //                                                      pic16_regWithIdx(i)->name);
3358
3359                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3360                                         _G.nRegsSaved++;
3361                                 }
3362                         }
3363                 }
3364         } else {
3365                 /* emit code to setup stack frame if user enabled,
3366                  * and function is not main() */
3367          
3368 //              fprintf(stderr, "function name: %s\n", sym->name);
3369                 if(strcmp(sym->name, "main")) {
3370                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3371                         /* setup the stack frame */
3372                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3373                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3374                                 if(STACK_MODEL_LARGE)
3375                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3376                         }
3377                 }
3378
3379                 /* if callee-save to be used for this function
3380                 * then save the registers being used in this function */
3381 //              if (IFFUNC_CALLEESAVES(sym->type))
3382                 {
3383                   int i;
3384
3385 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3386
3387 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3388
3389                         /* if any registers used */
3390                         if (sym->regsUsed) {
3391                                 /* save the registers used */
3392                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3393                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3394                                         if (bitVectBitValue(sym->regsUsed,i)) {
3395
3396 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3397 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3398 //                                                              pic16_regWithIdx(i)->name);
3399
3400                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3401
3402 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3403 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3404 //                                                      &pic16_pc_postdec1, 0));
3405
3406                                                 _G.nRegsSaved++;
3407                                         }
3408                                 }
3409                         }
3410                 }
3411         }
3412
3413
3414         
3415 #if 0
3416         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3417
3418                 if (options.useXstack) {
3419                         pic16_emitcode("mov","r0,%s",spname);
3420                         pic16_emitcode("mov","a,_bp");
3421                         pic16_emitcode("movx","@r0,a");
3422                         pic16_emitcode("inc","%s",spname);
3423                 } else {
3424                         /* set up the stack */
3425                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3426                 }
3427                 pic16_emitcode ("mov","_bp,%s",spname);
3428         }
3429 #endif
3430         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3431
3432         /* adjust the stack for the function */
3433         if (sym->stack) {
3434           int i = sym->stack;
3435
3436                 if (i > 127 ) 
3437                         werror(W_STACK_OVERFLOW,sym->name);
3438
3439                 if (i > 3 && sym->recvSize < 4) {              
3440                         pic16_emitcode ("mov","a,sp");
3441                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3442                         pic16_emitcode ("mov","sp,a");
3443                 } else
3444                         while(i--)
3445                                 pic16_emitcode("inc","sp");
3446         }
3447
3448         if (sym->xstack) {
3449                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3450
3451                 pic16_emitcode ("mov","a,_spx");
3452                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3453                 pic16_emitcode ("mov","_spx,a");
3454         }
3455     
3456 }
3457
3458 /*-----------------------------------------------------------------*/
3459 /* genEndFunction - generates epilogue for functions               */
3460 /*-----------------------------------------------------------------*/
3461 static void genEndFunction (iCode *ic)
3462 {
3463     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3464
3465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3466
3467     if(IFFUNC_ISNAKED(sym->type)) {
3468         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3469         return;
3470     }
3471
3472 #if 0
3473     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3474     {
3475         pic16_emitcode ("mov","%s,_bp",spname);
3476     }
3477 #endif
3478
3479     /* if use external stack but some variables were
3480     added to the local stack then decrement the
3481     local stack */
3482     if (options.useXstack && sym->stack) {      
3483         pic16_emitcode("mov","a,sp");
3484         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3485         pic16_emitcode("mov","sp,a");
3486     }
3487
3488
3489 #if 0
3490     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3491         if (options.useXstack) {
3492             pic16_emitcode("mov","r0,%s",spname);
3493             pic16_emitcode("movx","a,@r0");
3494             pic16_emitcode("mov","_bp,a");
3495             pic16_emitcode("dec","%s",spname);
3496         }
3497         else
3498         {
3499             pic16_emitcode ("pop","_bp");
3500         }
3501     }
3502 #endif
3503
3504         if (IFFUNC_ISISR(sym->type)) {
3505                 /* now we need to restore the registers */
3506                 /* if any registers used */
3507                 if (sym->regsUsed) {
3508                   int i;
3509
3510                         /* restore registers used */
3511                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3512                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3513                                 if (bitVectBitValue(sym->regsUsed,i)) {
3514
3515 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3516 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3517 //                                                      pic16_regWithIdx(i)->name);
3518
3519                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3520
3521 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3522 //                                                      &pic16_pc_preinc1,
3523 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3524
3525                                 }
3526                         }
3527                 }
3528         
3529                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3530                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3531                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3532                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3533
3534                 if(!(_G.interruptvector == 1)) {
3535                         /* do not restore interrupt vector for WREG,STATUS,BSR
3536                          * for high priority interrupt, see genFunction */
3537                          
3538                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3539                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3540                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3541                 }
3542         
3543                 _G.interruptvector = 0;         /* sanity check */
3544
3545 //              pic16_pBlockConvert2ISR(pb);
3546
3547
3548                 /* if debug then send end of function */
3549 /*      if (options.debug && currFunc)  */
3550                 if (currFunc) {
3551                         debugFile->writeEndFunction (currFunc, ic, 1);
3552                 }
3553         
3554                 pic16_emitpcodeNULLop(POC_RETFIE);
3555         } else {
3556                 if (IFFUNC_ISCRITICAL(sym->type))
3557                         pic16_emitcode("setb","ea");
3558         
3559
3560 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3561
3562                 /* if any registers used */
3563                 if (sym->regsUsed) {
3564                   int i;
3565                         /* save the registers used */
3566                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3567                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3568                                 if (bitVectBitValue(sym->regsUsed,i)) {
3569         
3570 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3571 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3572 //                                                      pic16_regWithIdx(i)->name);
3573         
3574                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3575                                         
3576 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3577 //                                              &pic16_pc_preinc1,
3578 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3579
3580                                         _G.nRegsSaved--;
3581                                 }
3582                         }
3583                 }
3584         
3585                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3586                 /* if debug then send end of function */
3587                 if (currFunc) {
3588                         debugFile->writeEndFunction (currFunc, ic, 1);
3589                 }
3590
3591                 /* insert code to restore stack frame, if user enabled it
3592                  * and function is not main() */
3593          
3594
3595                 if(strcmp(sym->name, "main")) {
3596                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3597                                 /* restore stack frame */
3598                                 if(STACK_MODEL_LARGE)
3599                                         pic16_emitpcode(POC_MOVFF,
3600                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3601                                 pic16_emitpcode(POC_MOVFF,
3602                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3603                         }
3604                 }
3605
3606                 pic16_emitcode ("return","");
3607                 pic16_emitpcodeNULLop(POC_RETURN);
3608
3609                 /* Mark the end of a function */
3610                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3611         }
3612
3613 }
3614
3615
3616 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3617 {
3618
3619         if(is_LitOp(op)) {
3620                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3621
3622                 if(dest->type != PO_WREG)
3623                         pic16_emitpcode(POC_MOVWF, dest);
3624         } else {
3625                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3626                         pic16_popGet(AOP(op), offset), dest));
3627         }
3628 }
3629
3630 /*-----------------------------------------------------------------*/
3631 /* genRet - generate code for return statement                     */
3632 /*-----------------------------------------------------------------*/
3633 static void genRet (iCode *ic)
3634 {
3635   int size;
3636   operand *left;
3637
3638         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3639         /* if we have no return value then
3640          * just generate the "ret" */
3641         
3642         if (!IC_LEFT(ic)) 
3643                 goto jumpret;       
3644     
3645         /* we have something to return then
3646          * move the return value into place */
3647         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3648         size = AOP_SIZE(IC_LEFT(ic));
3649
3650         if(size <= 4) {
3651                 if(size>3) {
3652                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3653 //                      pic16_emitpcode(POC_MOVFF,
3654 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3655                 }
3656                 if(size>2) {
3657                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3658 //                      pic16_emitpcode(POC_MOVFF,
3659 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3660                 }
3661                 if(size>1) {
3662                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3663 //                      pic16_emitpcode(POC_MOVFF,
3664 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3665                 }
3666
3667 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3668
3669                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3670 //              pic16_emitpcode(POC_MOVFF,
3671 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3672
3673         } else {
3674                 /* >32-bits, setup stack and FSR0 */
3675                 while (size--) {
3676 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3677 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3678
3679                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3680
3681 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3682                         GpsuedoStkPtr++;
3683                 }
3684                         
3685                 /* setup FSR0 */
3686                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3687                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3688
3689                 if(STACK_MODEL_LARGE) {
3690                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3691                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3692                 } else {
3693                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3694                 }
3695         }
3696                                 
3697 #if 0
3698         /* old code, left here for reference -- VR */    
3699         while (size--) {
3700           char *l ;
3701
3702                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3703                         /* #NOCHANGE */
3704                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3705                         pic16_emitpcomment("push %s",l);
3706                         pushed++;
3707                 } else {
3708                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3709                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3710                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3711                         
3712                         if (strcmp(fReturn[offset],l)) {
3713                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3714                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3715                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3716                                 } else {
3717                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3718                                 }
3719                                 
3720                                 if(size) {
3721                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3722                                 }
3723                                 offset++;
3724                         }
3725                 }
3726         }    
3727
3728         if (pushed) {
3729                 while(pushed) {
3730                         pushed--;
3731                         if (strcmp(fReturn[pushed],"a"))
3732                                 pic16_emitcode("pop",fReturn[pushed]);
3733                         else
3734                                 pic16_emitcode("pop","acc");
3735                 }
3736         }
3737 #endif
3738
3739
3740         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3741     
3742 jumpret:
3743         /* generate a jump to the return label
3744          * if the next is not the return statement */
3745         if (!(ic->next && ic->next->op == LABEL
3746                 && IC_LABEL(ic->next) == returnLabel)) {
3747         
3748                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3749                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3750         }
3751 }
3752
3753 /*-----------------------------------------------------------------*/
3754 /* genLabel - generates a label                                    */
3755 /*-----------------------------------------------------------------*/
3756 static void genLabel (iCode *ic)
3757 {
3758
3759
3760     /* special case never generate */
3761     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3762     if (IC_LABEL(ic) == entryLabel)
3763         return ;
3764
3765     pic16_emitpLabel(IC_LABEL(ic)->key);
3766     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3767 }
3768
3769 /*-----------------------------------------------------------------*/
3770 /* genGoto - generates a goto                                      */
3771 /*-----------------------------------------------------------------*/
3772 //tsd
3773 static void genGoto (iCode *ic)
3774 {
3775   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3776   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3777 }
3778
3779
3780 /*-----------------------------------------------------------------*/
3781 /* genMultbits :- multiplication of bits                           */
3782 /*-----------------------------------------------------------------*/
3783 static void genMultbits (operand *left, 
3784                          operand *right, 
3785                          operand *result)
3786 {
3787   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3788
3789   if(!pic16_sameRegs(AOP(result),AOP(right)))
3790     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3791
3792   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3793   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3794   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3795
3796 }
3797
3798
3799 /*-----------------------------------------------------------------*/
3800 /* genMultOneByte : 8 bit multiplication & division                */
3801 /*-----------------------------------------------------------------*/
3802 static void genMultOneByte (operand *left,
3803                             operand *right,
3804                             operand *result)
3805 {
3806
3807   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3808   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3809   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3810
3811   /* (if two literals, the value is computed before) */
3812   /* if one literal, literal on the right */
3813   if (AOP_TYPE(left) == AOP_LIT){
3814     operand *t = right;
3815     right = left;
3816     left = t;
3817   }
3818
3819         /* size is already checked in genMult == 1 */
3820 //      size = AOP_SIZE(result);
3821
3822         if (AOP_TYPE(right) == AOP_LIT){
3823                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3824                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3825                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3826                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3827         } else {
3828                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3829                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3830                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3831                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3832         }
3833         
3834         pic16_genMult8X8_8 (left, right,result);
3835 }
3836
3837 /*-----------------------------------------------------------------*/
3838 /* genMultOneWord : 16 bit multiplication                          */
3839 /*-----------------------------------------------------------------*/
3840 static void genMultOneWord (operand *left,
3841                             operand *right,
3842                             operand *result)
3843 {
3844
3845         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3846         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3847         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3848
3849         /* (if two literals, the value is computed before)
3850          * if one literal, literal on the right */
3851         if (AOP_TYPE(left) == AOP_LIT){
3852           operand *t = right;
3853                 right = left;
3854                 left = t;
3855         }
3856
3857         /* size is checked already == 2 */
3858 //      size = AOP_SIZE(result);
3859
3860         if (AOP_TYPE(right) == AOP_LIT) {
3861                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3862                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3863                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3864                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3865         } else {
3866                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3867                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3868                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3869                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3870         }
3871         
3872         pic16_genMult16X16_16(left, right,result);
3873 }
3874
3875 /*-----------------------------------------------------------------*/
3876 /* genMultOneLong : 32 bit multiplication                          */
3877 /*-----------------------------------------------------------------*/
3878 static void genMultOneLong (operand *left,
3879                             operand *right,
3880                             operand *result)
3881 {
3882
3883         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3884         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3885         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3886
3887         /* (if two literals, the value is computed before)
3888          * if one literal, literal on the right */
3889         if (AOP_TYPE(left) == AOP_LIT){
3890           operand *t = right;
3891                 right = left;
3892                 left = t;
3893         }
3894
3895         /* size is checked already == 4 */
3896 //      size = AOP_SIZE(result);
3897
3898         if (AOP_TYPE(right) == AOP_LIT) {
3899                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3900                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3901                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3902                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3903         } else {
3904                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3905                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3906                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3907                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3908         }
3909         
3910         pic16_genMult32X32_32(left, right,result);
3911 }
3912
3913
3914
3915 /*-----------------------------------------------------------------*/
3916 /* genMult - generates code for multiplication                     */
3917 /*-----------------------------------------------------------------*/
3918 static void genMult (iCode *ic)
3919 {
3920   operand *left = IC_LEFT(ic);
3921   operand *right = IC_RIGHT(ic);
3922   operand *result= IC_RESULT(ic);   
3923
3924         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3925         /* assign the amsops */
3926         pic16_aopOp (left,ic,FALSE);
3927         pic16_aopOp (right,ic,FALSE);
3928         pic16_aopOp (result,ic,TRUE);
3929
3930         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3931
3932         /* special cases first *
3933         * both are bits */
3934         if (AOP_TYPE(left) == AOP_CRY
3935                 && AOP_TYPE(right)== AOP_CRY) {
3936                 genMultbits(left,right,result);
3937           goto release ;
3938         }
3939
3940         /* if both are of size == 1 */
3941         if(AOP_SIZE(left) == 1
3942                 && AOP_SIZE(right) == 1) {
3943                 genMultOneByte(left,right,result);
3944           goto release ;
3945         }
3946
3947         /* if both are of size == 2 */
3948         if(AOP_SIZE(left) == 2
3949                 && AOP_SIZE(right) == 2) {
3950                 genMultOneWord(left, right, result);
3951           goto release;
3952         }
3953         
3954         /* if both are of size == 4 */
3955         if(AOP_SIZE(left) == 4
3956                 && AOP_SIZE(right) == 4) {
3957                 genMultOneLong(left, right, result);
3958           goto release;
3959         }
3960         
3961         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3962
3963
3964         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3965         /* should have been converted to function call */
3966         assert(0) ;
3967
3968 release :
3969         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3970         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3971         pic16_freeAsmop(result,NULL,ic,TRUE); 
3972 }
3973
3974 /*-----------------------------------------------------------------*/
3975 /* genDivbits :- division of bits                                  */
3976 /*-----------------------------------------------------------------*/
3977 static void genDivbits (operand *left, 
3978                         operand *right, 
3979                         operand *result)
3980 {
3981
3982     char *l;
3983
3984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3985     /* the result must be bit */    
3986     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3987     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3988
3989     MOVA(l);    
3990
3991     pic16_emitcode("div","ab");
3992     pic16_emitcode("rrc","a");
3993     pic16_aopPut(AOP(result),"c",0);
3994 }
3995
3996 /*-----------------------------------------------------------------*/
3997 /* genDivOneByte : 8 bit division                                  */
3998 /*-----------------------------------------------------------------*/
3999 static void genDivOneByte (operand *left,
4000                            operand *right,
4001                            operand *result)
4002 {
4003     sym_link *opetype = operandType(result);
4004     char *l ;
4005     symbol *lbl ;
4006     int size,offset;
4007
4008         /* result = divident / divisor
4009          * - divident may be a register or a literal,
4010          * - divisor may be a register or a literal,
4011          * so there are 3 cases (literal / literal is optimized
4012          * by the front-end) to handle.
4013          * In addition we must handle signed and unsigned, which
4014          * result in 6 final different cases -- VR */
4015
4016     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4017     size = AOP_SIZE(result) - 1;
4018     offset = 1;
4019     /* signed or unsigned */
4020     if (SPEC_USIGN(opetype)) {
4021       pCodeOp *pct1,    /* count */
4022                 *pct2,  /* reste */
4023                 *pct3;  /* temp */
4024       symbol *label1, *label2, *label3;;
4025
4026
4027         /* unsigned is easy */
4028
4029         pct1 = pic16_popGetTempReg();
4030         pct2 = pic16_popGetTempReg();
4031         pct3 = pic16_popGetTempReg();
4032         
4033         label1 = newiTempLabel(NULL);
4034         label2 = newiTempLabel(NULL);
4035         label3 = newiTempLabel(NULL);
4036
4037         /* the following algorithm is extracted from divuint.c */
4038
4039         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4040         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4041         
4042         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4043
4044         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4045         
4046         pic16_emitpLabel(label1->key);
4047         
4048         emitCLRC;
4049         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4050
4051
4052         emitCLRC;
4053         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4054         
4055
4056         emitSKPNC;
4057         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4058         
4059         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4060         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4061         
4062         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4063         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4064         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4065         
4066         pic16_emitpLabel( label3->key );
4067         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4068         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4069         
4070         
4071
4072         pic16_emitpLabel(label2->key);
4073         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4074         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4075         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4076         
4077         /* result is in wreg */
4078         if(AOP_TYPE(result) != AOP_ACC)
4079                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4080
4081         pic16_popReleaseTempReg( pct3 );
4082         pic16_popReleaseTempReg( pct2 );
4083         pic16_popReleaseTempReg( pct1 );
4084
4085         return ;
4086     }
4087
4088     /* signed is a little bit more difficult */
4089
4090     /* save the signs of the operands */
4091     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4092     MOVA(l);    
4093     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4094     pic16_emitcode("push","acc"); /* save it on the stack */
4095
4096     /* now sign adjust for both left & right */
4097     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4098     MOVA(l);       
4099     lbl = newiTempLabel(NULL);
4100     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4101     pic16_emitcode("cpl","a");   
4102     pic16_emitcode("inc","a");
4103     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4104     pic16_emitcode("mov","b,a");
4105
4106     /* sign adjust left side */
4107     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4108     MOVA(l);
4109
4110     lbl = newiTempLabel(NULL);
4111     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4112     pic16_emitcode("cpl","a");
4113     pic16_emitcode("inc","a");
4114     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4115
4116     /* now the division */
4117     pic16_emitcode("div","ab");
4118     /* we are interested in the lower order
4119     only */
4120     pic16_emitcode("mov","b,a");
4121     lbl = newiTempLabel(NULL);
4122     pic16_emitcode("pop","acc");   
4123     /* if there was an over flow we don't 
4124     adjust the sign of the result */
4125     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4126     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4127     CLRC;
4128     pic16_emitcode("clr","a");
4129     pic16_emitcode("subb","a,b");
4130     pic16_emitcode("mov","b,a");
4131     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4132
4133     /* now we are done */
4134     pic16_aopPut(AOP(result),"b",0);
4135     if(size > 0){
4136         pic16_emitcode("mov","c,b.7");
4137         pic16_emitcode("subb","a,acc");   
4138     }
4139     while (size--)
4140         pic16_aopPut(AOP(result),"a",offset++);
4141
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genDiv - generates code for division                            */
4146 /*-----------------------------------------------------------------*/
4147 static void genDiv (iCode *ic)
4148 {
4149     operand *left = IC_LEFT(ic);
4150     operand *right = IC_RIGHT(ic);
4151     operand *result= IC_RESULT(ic);   
4152
4153
4154         /* Division is a very lengthy algorithm, so it is better
4155          * to call support routines than inlining algorithm.
4156          * Division functions written here just in case someone
4157          * wants to inline and not use the support libraries -- VR */
4158
4159     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4160     /* assign the amsops */
4161     pic16_aopOp (left,ic,FALSE);
4162     pic16_aopOp (right,ic,FALSE);
4163     pic16_aopOp (result,ic,TRUE);
4164
4165     /* special cases first */
4166     /* both are bits */
4167     if (AOP_TYPE(left) == AOP_CRY &&
4168         AOP_TYPE(right)== AOP_CRY) {
4169         genDivbits(left,right,result);
4170         goto release ;
4171     }
4172
4173     /* if both are of size == 1 */
4174     if (AOP_SIZE(left) == 1 &&
4175         AOP_SIZE(right) == 1 ) {
4176         genDivOneByte(left,right,result);
4177         goto release ;
4178     }
4179
4180     /* should have been converted to function call */
4181     assert(0);
4182 release :
4183     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4185     pic16_freeAsmop(result,NULL,ic,TRUE); 
4186 }
4187
4188 /*-----------------------------------------------------------------*/
4189 /* genModbits :- modulus of bits                                   */
4190 /*-----------------------------------------------------------------*/
4191 static void genModbits (operand *left, 
4192                         operand *right, 
4193                         operand *result)
4194 {
4195
4196     char *l;
4197
4198     /* the result must be bit */    
4199     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4200     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4201
4202     MOVA(l);       
4203
4204     pic16_emitcode("div","ab");
4205     pic16_emitcode("mov","a,b");
4206     pic16_emitcode("rrc","a");
4207     pic16_aopPut(AOP(result),"c",0);
4208 }
4209
4210 /*-----------------------------------------------------------------*/
4211 /* genModOneByte : 8 bit modulus                                   */
4212 /*-----------------------------------------------------------------*/
4213 static void genModOneByte (operand *left,
4214                            operand *right,
4215                            operand *result)
4216 {
4217     sym_link *opetype = operandType(result);
4218     char *l ;
4219     symbol *lbl ;
4220
4221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4222     /* signed or unsigned */
4223     if (SPEC_USIGN(opetype)) {
4224         /* unsigned is easy */
4225         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4226         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4227         MOVA(l);    
4228         pic16_emitcode("div","ab");
4229         pic16_aopPut(AOP(result),"b",0);
4230         return ;
4231     }
4232
4233     /* signed is a little bit more difficult */
4234
4235     /* save the signs of the operands */
4236     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4237     MOVA(l);
4238
4239     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4240     pic16_emitcode("push","acc"); /* save it on the stack */
4241
4242     /* now sign adjust for both left & right */
4243     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4244     MOVA(l);
4245
4246     lbl = newiTempLabel(NULL);
4247     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4248     pic16_emitcode("cpl","a");   
4249     pic16_emitcode("inc","a");
4250     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4251     pic16_emitcode("mov","b,a"); 
4252
4253     /* sign adjust left side */
4254     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4255     MOVA(l);
4256
4257     lbl = newiTempLabel(NULL);
4258     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4259     pic16_emitcode("cpl","a");   
4260     pic16_emitcode("inc","a");
4261     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4262
4263     /* now the multiplication */
4264     pic16_emitcode("div","ab");
4265     /* we are interested in the lower order
4266     only */
4267     lbl = newiTempLabel(NULL);
4268     pic16_emitcode("pop","acc");   
4269     /* if there was an over flow we don't 
4270     adjust the sign of the result */
4271     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4272     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4273     CLRC ;
4274     pic16_emitcode("clr","a");
4275     pic16_emitcode("subb","a,b");
4276     pic16_emitcode("mov","b,a");
4277     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4278
4279     /* now we are done */
4280     pic16_aopPut(AOP(result),"b",0);
4281
4282 }
4283
4284 /*-----------------------------------------------------------------*/
4285 /* genMod - generates code for division                            */
4286 /*-----------------------------------------------------------------*/
4287 static void genMod (iCode *ic)
4288 {
4289     operand *left = IC_LEFT(ic);
4290     operand *right = IC_RIGHT(ic);
4291     operand *result= IC_RESULT(ic);  
4292
4293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4294     /* assign the amsops */
4295     pic16_aopOp (left,ic,FALSE);
4296     pic16_aopOp (right,ic,FALSE);
4297     pic16_aopOp (result,ic,TRUE);
4298
4299     /* special cases first */
4300     /* both are bits */
4301     if (AOP_TYPE(left) == AOP_CRY &&
4302         AOP_TYPE(right)== AOP_CRY) {
4303         genModbits(left,right,result);
4304         goto release ;
4305     }
4306
4307     /* if both are of size == 1 */
4308     if (AOP_SIZE(left) == 1 &&
4309         AOP_SIZE(right) == 1 ) {
4310         genModOneByte(left,right,result);
4311         goto release ;
4312     }
4313
4314     /* should have been converted to function call */
4315     assert(0);
4316
4317 release :
4318     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4320     pic16_freeAsmop(result,NULL,ic,TRUE); 
4321 }
4322
4323 /*-----------------------------------------------------------------*/
4324 /* genIfxJump :- will create a jump depending on the ifx           */
4325 /*-----------------------------------------------------------------*/
4326 /*
4327   note: May need to add parameter to indicate when a variable is in bit space.
4328 */
4329 static void genIfxJump (iCode *ic, char *jval)
4330 {
4331
4332     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4333     /* if true label then we jump if condition
4334     supplied is true */
4335     if ( IC_TRUE(ic) ) {
4336
4337         if(strcmp(jval,"a") == 0)
4338           emitSKPZ;
4339         else if (strcmp(jval,"c") == 0)
4340           emitSKPC;
4341         else {
4342           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4343           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4344         }
4345
4346         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4347         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4348
4349     }
4350     else {
4351         /* false label is present */
4352         if(strcmp(jval,"a") == 0)
4353           emitSKPNZ;
4354         else if (strcmp(jval,"c") == 0)
4355           emitSKPNC;
4356         else {
4357           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4358           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4359         }
4360
4361         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4362         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4363
4364     }
4365
4366
4367     /* mark the icode as generated */
4368     ic->generated = 1;
4369 }
4370
4371 #if 0
4372 // not needed ATM
4373
4374 /*-----------------------------------------------------------------*/
4375 /* genSkip                                                         */
4376 /*-----------------------------------------------------------------*/
4377 static void genSkip(iCode *ifx,int status_bit)
4378 {
4379   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4380   if(!ifx)
4381     return;
4382
4383   if ( IC_TRUE(ifx) ) {
4384     switch(status_bit) {
4385     case 'z':
4386       emitSKPNZ;
4387       break;
4388
4389     case 'c':
4390       emitSKPNC;
4391       break;
4392
4393     case 'd':
4394       emitSKPDC;
4395       break;
4396
4397     }
4398
4399     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4400     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4401
4402   } else {
4403
4404     switch(status_bit) {
4405
4406     case 'z':
4407       emitSKPZ;
4408       break;
4409
4410     case 'c':
4411       emitSKPC;
4412       break;
4413
4414     case 'd':
4415       emitSKPDC;
4416       break;
4417     }
4418     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4419     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4420
4421   }
4422
4423 }
4424 #endif
4425
4426 /*-----------------------------------------------------------------*/
4427 /* genSkipc                                                        */
4428 /*-----------------------------------------------------------------*/
4429 static void genSkipc(resolvedIfx *rifx)
4430 {
4431   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4432   
4433   if(!rifx)
4434     return;
4435
4436   if(rifx->condition)
4437     emitSKPC;
4438   else
4439     emitSKPNC;
4440
4441   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4442   rifx->generated = 1;
4443 }
4444
4445 /*-----------------------------------------------------------------*/
4446 /* genSkipz2                                                       */
4447 /*-----------------------------------------------------------------*/
4448 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4449 {
4450   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4451   
4452   if(!rifx)
4453     return;
4454
4455   if( (rifx->condition ^ invert_condition) & 1)
4456     emitSKPZ;
4457   else
4458     emitSKPNZ;
4459
4460   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4461   rifx->generated = 1;
4462 }
4463
4464 #if 0
4465 /*-----------------------------------------------------------------*/
4466 /* genSkipz                                                        */
4467 /*-----------------------------------------------------------------*/
4468 static void genSkipz(iCode *ifx, int condition)
4469 {
4470   if(!ifx)
4471     return;
4472
4473   if(condition)
4474     emitSKPNZ;
4475   else
4476     emitSKPZ;
4477
4478   if ( IC_TRUE(ifx) )
4479     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4480   else
4481     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4482
4483   if ( IC_TRUE(ifx) )
4484     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4485   else
4486     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4487
4488 }
4489 #endif
4490
4491 /*-----------------------------------------------------------------*/
4492 /* genSkipCond                                                     */
4493 /*-----------------------------------------------------------------*/
4494 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4495 {
4496   if(!rifx)
4497     return;
4498
4499   if(rifx->condition)
4500     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4501   else
4502     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4503
4504
4505   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4506   rifx->generated = 1;
4507 }
4508
4509 #if 0
4510 /*-----------------------------------------------------------------*/
4511 /* genChkZeroes :- greater or less than comparison                 */
4512 /*     For each byte in a literal that is zero, inclusive or the   */
4513 /*     the corresponding byte in the operand with W                */
4514 /*     returns true if any of the bytes are zero                   */
4515 /*-----------------------------------------------------------------*/
4516 static int genChkZeroes(operand *op, int lit,  int size)
4517 {
4518
4519   int i;
4520   int flag =1;
4521
4522   while(size--) {
4523     i = (lit >> (size*8)) & 0xff;
4524
4525     if(i==0) {
4526       if(flag) 
4527         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4528       else
4529         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4530       flag = 0;
4531     }
4532   }
4533
4534   return (flag==0);
4535 }
4536 #endif
4537
4538 /*-----------------------------------------------------------------*/
4539 /* genCmp :- greater or less than comparison                       */
4540 /*-----------------------------------------------------------------*/
4541 static void genCmp (operand *left,operand *right,
4542                     operand *result, iCode *ifx, int sign)
4543 {
4544   int size; //, offset = 0 ;
4545   unsigned long lit = 0L,i = 0;
4546   resolvedIfx rFalseIfx;
4547   //  resolvedIfx rTrueIfx;
4548   symbol *truelbl;
4549   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4550 /*
4551   if(ifx) {
4552     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4553     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4554   }
4555 */
4556
4557   resolveIfx(&rFalseIfx,ifx);
4558   truelbl  = newiTempLabel(NULL);
4559   size = max(AOP_SIZE(left),AOP_SIZE(right));
4560
4561   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4562
4563 #define _swapp
4564
4565   /* if literal is on the right then swap with left */
4566   if ((AOP_TYPE(right) == AOP_LIT)) {
4567     operand *tmp = right ;
4568     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4569     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4570 #ifdef _swapp
4571
4572     lit = (lit - 1) & mask;
4573     right = left;
4574     left = tmp;
4575     rFalseIfx.condition ^= 1;
4576 #endif
4577
4578   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4579     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4580   }
4581
4582
4583   //if(IC_TRUE(ifx) == NULL)
4584   /* if left & right are bit variables */
4585   if (AOP_TYPE(left) == AOP_CRY &&
4586       AOP_TYPE(right) == AOP_CRY ) {
4587     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4588     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4589   } else {
4590     /* subtract right from left if at the
4591        end the carry flag is set then we know that
4592        left is greater than right */
4593
4594     symbol *lbl  = newiTempLabel(NULL);
4595
4596 #if 0
4597         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4598                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4599 #endif
4600
4601 #ifndef _swapp
4602     if(AOP_TYPE(right) == AOP_LIT) {
4603
4604       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4605
4606       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4607
4608       /* special cases */
4609
4610       if(lit == 0) {
4611
4612         if(sign != 0) 
4613           genSkipCond(&rFalseIfx,left,size-1,7);
4614         else 
4615           /* no need to compare to 0...*/
4616           /* NOTE: this is a de-generate compare that most certainly 
4617            *       creates some dead code. */
4618           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4619
4620         if(ifx) ifx->generated = 1;
4621         return;
4622
4623       }
4624       size--;
4625
4626       if(size == 0) {
4627         //i = (lit >> (size*8)) & 0xff;
4628         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4629         
4630         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4631
4632         i = ((0-lit) & 0xff);
4633         if(sign) {
4634           if( i == 0x81) { 
4635             /* lit is 0x7f, all signed chars are less than
4636              * this except for 0x7f itself */
4637             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4638             genSkipz2(&rFalseIfx,0);
4639           } else {
4640             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4641             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4642             genSkipc(&rFalseIfx);
4643           }
4644
4645         } else {
4646           if(lit == 1) {
4647             genSkipz2(&rFalseIfx,1);
4648           } else {
4649             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4650             genSkipc(&rFalseIfx);
4651           }
4652         }
4653
4654         if(ifx) ifx->generated = 1;
4655         return;
4656       }
4657
4658       /* chars are out of the way. now do ints and longs */
4659
4660
4661       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4662         
4663       /* special cases */
4664
4665       if(sign) {
4666
4667         if(lit == 0) {
4668           genSkipCond(&rFalseIfx,left,size,7);
4669           if(ifx) ifx->generated = 1;
4670           return;
4671         }
4672
4673         if(lit <0x100) {
4674           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4675
4676           //rFalseIfx.condition ^= 1;
4677           //genSkipCond(&rFalseIfx,left,size,7);
4678           //rFalseIfx.condition ^= 1;
4679
4680           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4681           if(rFalseIfx.condition)
4682             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4683           else
4684             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4685
4686           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4687           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4688           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4689
4690           while(size > 1)
4691             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4692
4693           if(rFalseIfx.condition) {
4694             emitSKPZ;
4695             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4696
4697           } else {
4698             emitSKPNZ;
4699           }
4700
4701           genSkipc(&rFalseIfx);
4702           pic16_emitpLabel(truelbl->key);
4703           if(ifx) ifx->generated = 1;
4704           return;
4705
4706         }
4707
4708         if(size == 1) {
4709
4710           if( (lit & 0xff) == 0) {
4711             /* lower byte is zero */
4712             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4713             i = ((lit >> 8) & 0xff) ^0x80;
4714             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4715             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4716             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4717             genSkipc(&rFalseIfx);
4718
4719
4720             if(ifx) ifx->generated = 1;
4721             return;
4722
4723           }
4724         } else {
4725           /* Special cases for signed longs */
4726           if( (lit & 0xffffff) == 0) {
4727             /* lower byte is zero */
4728             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4729             i = ((lit >> 8*3) & 0xff) ^0x80;
4730             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4731             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4732             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4733             genSkipc(&rFalseIfx);
4734
4735
4736             if(ifx) ifx->generated = 1;
4737             return;
4738
4739           }
4740
4741         }
4742
4743
4744         if(lit & (0x80 << (size*8))) {
4745           /* lit is negative */
4746           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4747
4748           //genSkipCond(&rFalseIfx,left,size,7);
4749
4750           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4751
4752           if(rFalseIfx.condition)
4753             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4754           else
4755             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4756
4757
4758         } else {
4759           /* lit is positive */
4760           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4761           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4762           if(rFalseIfx.condition)
4763             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4764           else
4765             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4766
4767         }
4768
4769         /*
4770           This works, but is only good for ints.
4771           It also requires a "known zero" register.
4772           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4773           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4774           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4775           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4776           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4777           genSkipc(&rFalseIfx);
4778
4779           pic16_emitpLabel(truelbl->key);
4780           if(ifx) ifx->generated = 1;
4781           return;
4782         **/
4783           
4784         /* There are no more special cases, so perform a general compare */
4785   
4786         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4787         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4788
4789         while(size--) {
4790
4791           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4792           emitSKPNZ;
4793           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4794         }
4795         //rFalseIfx.condition ^= 1;
4796         genSkipc(&rFalseIfx);
4797
4798         pic16_emitpLabel(truelbl->key);
4799
4800         if(ifx) ifx->generated = 1;
4801         return;
4802
4803
4804       }
4805
4806
4807       /* sign is out of the way. So now do an unsigned compare */
4808       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4809
4810
4811       /* General case - compare to an unsigned literal on the right.*/
4812
4813       i = (lit >> (size*8)) & 0xff;
4814       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4815       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4816       while(size--) {
4817         i = (lit >> (size*8)) & 0xff;
4818
4819         if(i) {
4820           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4821           emitSKPNZ;
4822           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4823         } else {
4824           /* this byte of the lit is zero, 
4825            *if it's not the last then OR in the variable */
4826           if(size)
4827             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4828         }
4829       }
4830
4831
4832       pic16_emitpLabel(lbl->key);
4833 //      pic16_emitpLabel(truelbl->key);
4834       //if(emitFinalCheck)
4835       genSkipc(&rFalseIfx);
4836       if(sign)
4837         pic16_emitpLabel(truelbl->key);
4838
4839       if(ifx) ifx->generated = 1;
4840       return;
4841
4842
4843     }
4844 #endif  // _swapp
4845
4846     if(AOP_TYPE(left) == AOP_LIT) {
4847       //symbol *lbl = newiTempLabel(NULL);
4848
4849       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4850
4851
4852       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4853
4854       /* Special cases */
4855       if((lit == 0) && (sign == 0)){
4856
4857         size--;
4858         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4859         while(size) 
4860           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4861
4862         genSkipz2(&rFalseIfx,0);
4863         if(ifx) ifx->generated = 1;
4864         return;
4865       }
4866
4867       if(size==1) {
4868         /* Special cases */
4869         lit &= 0xff;
4870         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4871           /* degenerate compare can never be true */
4872           if(rFalseIfx.condition == 0)
4873             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4874
4875           if(ifx) ifx->generated = 1;
4876           return;
4877         }
4878
4879         if(sign) {
4880           /* signed comparisons to a literal byte */
4881
4882           int lp1 = (lit+1) & 0xff;
4883
4884           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4885           switch (lp1) {
4886           case 0:
4887             rFalseIfx.condition ^= 1;
4888             genSkipCond(&rFalseIfx,right,0,7);
4889             break;
4890           case 0x7f:
4891             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4892             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4893             genSkipz2(&rFalseIfx,1);
4894             break;
4895           default:
4896             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4897             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4898             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4899             rFalseIfx.condition ^= 1;
4900             genSkipc(&rFalseIfx);
4901             break;
4902           }
4903         } else {
4904           /* unsigned comparisons to a literal byte */
4905
4906           switch(lit & 0xff ) {
4907           case 0:
4908             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4909             genSkipz2(&rFalseIfx,0);
4910             break;
4911           case 0x7f:
4912             rFalseIfx.condition ^= 1;
4913             genSkipCond(&rFalseIfx,right,0,7);
4914             break;
4915
4916           default:
4917             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4918             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4919             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4920             rFalseIfx.condition ^= 1;
4921             if (AOP_TYPE(result) == AOP_CRY)
4922               genSkipc(&rFalseIfx);
4923             else {
4924               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4925               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4926             }         
4927             break;
4928           }
4929         }
4930
4931         if(ifx) ifx->generated = 1;
4932         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4933                 goto check_carry;
4934         return;
4935
4936       } else {
4937
4938         /* Size is greater than 1 */
4939
4940         if(sign) {
4941           int lp1 = lit+1;
4942
4943           size--;
4944
4945           if(lp1 == 0) {
4946             /* this means lit = 0xffffffff, or -1 */
4947
4948
4949             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4950             rFalseIfx.condition ^= 1;
4951             genSkipCond(&rFalseIfx,right,size,7);
4952             if(ifx) ifx->generated = 1;
4953             return;
4954           }
4955
4956           if(lit == 0) {
4957             int s = size;
4958
4959             if(rFalseIfx.condition) {
4960               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4961               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4962             }
4963
4964             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4965             while(size--)
4966               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4967
4968
4969             emitSKPZ;
4970             if(rFalseIfx.condition) {
4971               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4972               pic16_emitpLabel(truelbl->key);
4973             }else {
4974               rFalseIfx.condition ^= 1;
4975               genSkipCond(&rFalseIfx,right,s,7);
4976             }
4977
4978             if(ifx) ifx->generated = 1;
4979             return;
4980           }
4981
4982           if((size == 1) &&  (0 == (lp1&0xff))) {
4983             /* lower byte of signed word is zero */
4984             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4985             i = ((lp1 >> 8) & 0xff) ^0x80;
4986             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4987             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4988             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4989             rFalseIfx.condition ^= 1;
4990             genSkipc(&rFalseIfx);
4991
4992
4993             if(ifx) ifx->generated = 1;
4994             return;
4995           }
4996
4997           if(lit & (0x80 << (size*8))) {
4998             /* Lit is less than zero */
4999             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5000             //rFalseIfx.condition ^= 1;
5001             //genSkipCond(&rFalseIfx,left,size,7);
5002             //rFalseIfx.condition ^= 1;
5003             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5004             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5005
5006             if(rFalseIfx.condition)
5007               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5008             else
5009               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5010
5011
5012           } else {
5013             /* Lit is greater than or equal to zero */
5014             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5015             //rFalseIfx.condition ^= 1;
5016             //genSkipCond(&rFalseIfx,right,size,7);
5017             //rFalseIfx.condition ^= 1;
5018
5019             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5020             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5021
5022             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5023             if(rFalseIfx.condition)
5024               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5025             else
5026               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5027
5028           }
5029
5030
5031           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5032           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5033
5034           while(size--) {
5035
5036             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5037             emitSKPNZ;
5038             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5039           }
5040           rFalseIfx.condition ^= 1;
5041           //rFalseIfx.condition = 1;
5042           genSkipc(&rFalseIfx);
5043
5044           pic16_emitpLabel(truelbl->key);
5045
5046           if(ifx) ifx->generated = 1;
5047           return;
5048           // end of if (sign)
5049         } else {
5050
5051           /* compare word or long to an unsigned literal on the right.*/
5052
5053
5054           size--;
5055           if(lit < 0xff) {
5056             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5057             switch (lit) {
5058             case 0:
5059               break; /* handled above */
5060 /*
5061             case 0xff:
5062               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5063               while(size--)
5064                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5065               genSkipz2(&rFalseIfx,0);
5066               break;
5067 */
5068             default:
5069               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5070               while(--size)
5071                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5072
5073               emitSKPZ;
5074               if(rFalseIfx.condition)
5075                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5076               else
5077                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5078
5079
5080               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5081               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5082
5083               rFalseIfx.condition ^= 1;
5084               genSkipc(&rFalseIfx);
5085             }
5086
5087             pic16_emitpLabel(truelbl->key);
5088
5089             if(ifx) ifx->generated = 1;
5090             return;
5091           }
5092
5093
5094           lit++;
5095           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5096           i = (lit >> (size*8)) & 0xff;
5097
5098           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5099           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5100
5101           while(size--) {
5102             i = (lit >> (size*8)) & 0xff;
5103
5104             if(i) {
5105               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5106               emitSKPNZ;
5107               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5108             } else {
5109               /* this byte of the lit is zero, 
5110                * if it's not the last then OR in the variable */
5111               if(size)
5112                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5113             }
5114           }
5115
5116
5117           pic16_emitpLabel(lbl->key);
5118
5119           rFalseIfx.condition ^= 1;
5120
5121           genSkipc(&rFalseIfx);
5122         }
5123
5124         if(sign)
5125           pic16_emitpLabel(truelbl->key);
5126         if(ifx) ifx->generated = 1;
5127         return;
5128       }
5129     }
5130     /* Compare two variables */
5131
5132     DEBUGpic16_emitcode(";sign","%d",sign);
5133
5134     size--;
5135     if(sign) {
5136       /* Sigh. thus sucks... */
5137       if(size) {
5138         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5139         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5140         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5141         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5142         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5143         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5144       } else {
5145         /* Signed char comparison */
5146         /* Special thanks to Nikolai Golovchenko for this snippet */
5147         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5148         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5149         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5150         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5151         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5152         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5153
5154         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5155         genSkipc(&rFalseIfx);
5156           
5157         if(ifx) ifx->generated = 1;
5158         return;
5159       }
5160
5161     } else {
5162
5163       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5164       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5165     }
5166
5167
5168     /* The rest of the bytes of a multi-byte compare */
5169     while (size) {
5170
5171       emitSKPZ;
5172       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5173       size--;
5174
5175       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5176       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5177
5178
5179     }
5180
5181     pic16_emitpLabel(lbl->key);
5182
5183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5184     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5185         (AOP_TYPE(result) == AOP_REG)) {
5186       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5187       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5188     } else {
5189       genSkipc(&rFalseIfx);
5190     }         
5191     //genSkipc(&rFalseIfx);
5192     if(ifx) ifx->generated = 1;
5193
5194     return;
5195
5196   }
5197
5198 check_carry:
5199   if ((AOP_TYPE(result) != AOP_CRY) 
5200         && AOP_SIZE(result)) {
5201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5202 //    pic16_emitpLabel( rFalseIfx.lbl->key );
5203
5204     pic16_outBitC(result);
5205   } else {
5206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5207     /* if the result is used in the next
5208        ifx conditional branch then generate
5209        code a little differently */
5210     if (ifx )
5211       genIfxJump (ifx,"c");
5212     else
5213       pic16_outBitC(result);
5214     /* leave the result in acc */
5215   }
5216
5217 }
5218
5219 /*-----------------------------------------------------------------*/
5220 /* genCmpGt :- greater than comparison                             */
5221 /*-----------------------------------------------------------------*/
5222 static void genCmpGt (iCode *ic, iCode *ifx)
5223 {
5224     operand *left, *right, *result;
5225     sym_link *letype , *retype;
5226     int sign ;
5227
5228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5229     left = IC_LEFT(ic);
5230     right= IC_RIGHT(ic);
5231     result = IC_RESULT(ic);
5232
5233     letype = getSpec(operandType(left));
5234     retype =getSpec(operandType(right));
5235     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5236     /* assign the amsops */
5237     pic16_aopOp (left,ic,FALSE);
5238     pic16_aopOp (right,ic,FALSE);
5239     pic16_aopOp (result,ic,TRUE);
5240
5241     genCmp(right, left, result, ifx, sign);
5242
5243     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5244     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5245     pic16_freeAsmop(result,NULL,ic,TRUE); 
5246 }
5247
5248 /*-----------------------------------------------------------------*/
5249 /* genCmpLt - less than comparisons                                */
5250 /*-----------------------------------------------------------------*/
5251 static void genCmpLt (iCode *ic, iCode *ifx)
5252 {
5253     operand *left, *right, *result;
5254     sym_link *letype , *retype;
5255     int sign ;
5256
5257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5258     left = IC_LEFT(ic);
5259     right= IC_RIGHT(ic);
5260     result = IC_RESULT(ic);
5261
5262     letype = getSpec(operandType(left));
5263     retype =getSpec(operandType(right));
5264     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5265
5266     /* assign the amsops */
5267     pic16_aopOp (left,ic,FALSE);
5268     pic16_aopOp (right,ic,FALSE);
5269     pic16_aopOp (result,ic,TRUE);
5270
5271     genCmp(left, right, result, ifx, sign);
5272
5273     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5274     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275     pic16_freeAsmop(result,NULL,ic,TRUE); 
5276 }
5277
5278 #if 0
5279 // not needed ATM
5280 // FIXME reenable literal optimisation when the pic16 port is stable
5281
5282 /*-----------------------------------------------------------------*/
5283 /* genc16bit2lit - compare a 16 bit value to a literal             */
5284 /*-----------------------------------------------------------------*/
5285 static void genc16bit2lit(operand *op, int lit, int offset)
5286 {
5287   int i;
5288
5289   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5290   if( (lit&0xff) == 0) 
5291     i=1;
5292   else
5293     i=0;
5294
5295   switch( BYTEofLONG(lit,i)) { 
5296   case 0:
5297     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5298     break;
5299   case 1:
5300     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5301     break;
5302   case 0xff:
5303     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5304     break;
5305   default:
5306     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5307     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5308   }
5309
5310   i ^= 1;
5311
5312   switch( BYTEofLONG(lit,i)) { 
5313   case 0:
5314     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5315     break;
5316   case 1:
5317     emitSKPNZ;
5318     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5319     break;
5320   case 0xff:
5321     emitSKPNZ;
5322     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5323     break;
5324   default:
5325     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5326     emitSKPNZ;
5327     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5328
5329   }
5330
5331 }
5332 #endif
5333
5334 #if 0
5335 // not needed ATM
5336 /*-----------------------------------------------------------------*/
5337 /* gencjneshort - compare and jump if not equal                    */
5338 /*-----------------------------------------------------------------*/
5339 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5340 {
5341   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5342   int offset = 0;
5343   int res_offset = 0;  /* the result may be a different size then left or right */
5344   int res_size = AOP_SIZE(result);
5345   resolvedIfx rIfx;
5346   symbol *lbl, *lbl_done;
5347
5348   unsigned long lit = 0L;
5349   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5350
5351   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5352   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5353   if(result)
5354     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5355   resolveIfx(&rIfx,ifx);
5356   lbl =  newiTempLabel(NULL);
5357   lbl_done =  newiTempLabel(NULL);
5358
5359
5360   /* if the left side is a literal or 
5361      if the right is in a pointer register and left 
5362      is not */
5363   if ((AOP_TYPE(left) == AOP_LIT) || 
5364       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5365     operand *t = right;
5366     right = left;
5367     left = t;
5368   }
5369   if(AOP_TYPE(right) == AOP_LIT)
5370     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5371
5372   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5373     preserve_result = 1;
5374
5375   if(result && !preserve_result)
5376     {
5377       int i;
5378       for(i = 0; i < AOP_SIZE(result); i++)
5379         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5380     }
5381
5382
5383   /* if the right side is a literal then anything goes */
5384   if (AOP_TYPE(right) == AOP_LIT &&
5385       AOP_TYPE(left) != AOP_DIR ) {
5386     switch(size) {
5387     case 2:
5388       genc16bit2lit(left, lit, 0);
5389       emitSKPZ;
5390       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5391       break;
5392     default:
5393       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5394       while (size--) {
5395         if(lit & 0xff) {
5396           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5397           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5398         } else {
5399           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5400         }
5401
5402         emitSKPZ;
5403         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5404         offset++;
5405         if(res_offset < res_size-1)
5406           res_offset++;
5407         lit >>= 8;
5408       }
5409       break;
5410     }
5411   }
5412
5413   /* if the right side is in a register or in direct space or
5414      if the left is a pointer register & right is not */    
5415   else if (AOP_TYPE(right) == AOP_REG ||
5416            AOP_TYPE(right) == AOP_DIR || 
5417            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5418            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5419     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5420     int lbl_key = lbl->key;
5421
5422     if(result) {
5423       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5424       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5425     }else {
5426       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5427       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5428               __FUNCTION__,__LINE__);
5429       return;
5430     }
5431    
5432 /*     switch(size) { */
5433 /*     case 2: */
5434 /*       genc16bit2lit(left, lit, 0); */
5435 /*       emitSKPNZ; */
5436 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5437 /*       break; */
5438 /*     default: */
5439     while (size--) {
5440       int emit_skip=1;
5441       if((AOP_TYPE(left) == AOP_DIR) && 
5442          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5443
5444         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5445         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5446
5447       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5448             
5449         switch (lit & 0xff) {
5450         case 0:
5451           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5452           break;
5453         case 1:
5454           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5455           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5456           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5457           emit_skip=0;
5458           break;
5459         case 0xff:
5460           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5461           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5462           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5463           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5464           emit_skip=0;
5465           break;
5466         default:
5467           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5468           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5469         }
5470         lit >>= 8;
5471
5472       } else {
5473         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5474       }
5475       if(emit_skip) {
5476         if(AOP_TYPE(result) == AOP_CRY) {
5477           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5478           if(rIfx.condition)
5479             emitSKPNZ;
5480           else
5481             emitSKPZ;
5482           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5483         } else {
5484           /* fix me. probably need to check result size too */
5485           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5486           if(rIfx.condition)
5487             emitSKPZ;
5488           else
5489             emitSKPNZ;
5490           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5491           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5492         }
5493         if(ifx)
5494           ifx->generated=1;
5495       }
5496       emit_skip++;
5497       offset++;
5498       if(res_offset < res_size-1)
5499         res_offset++;
5500     }
5501 /*       break; */
5502 /*     } */
5503   } else if(AOP_TYPE(right) == AOP_REG &&
5504             AOP_TYPE(left) != AOP_DIR){
5505
5506     while(size--) {
5507       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5508       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5509       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5510       if(rIfx.condition)
5511         emitSKPNZ;
5512       else
5513         emitSKPZ;
5514       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5515       offset++;
5516       if(res_offset < res_size-1)
5517         res_offset++;
5518     }
5519       
5520   }else{
5521     /* right is a pointer reg need both a & b */
5522     while(size--) {
5523       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5524       if(strcmp(l,"b"))
5525         pic16_emitcode("mov","b,%s",l);
5526       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5527       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5528       offset++;
5529     }
5530   }
5531
5532   if(result && preserve_result)
5533     {
5534       int i;
5535       for(i = 0; i < AOP_SIZE(result); i++)
5536         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5537     }
5538
5539   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5540
5541   if(result && preserve_result)
5542     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5543
5544   if(!rIfx.condition)
5545     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5546
5547   pic16_emitpLabel(lbl->key);
5548
5549   if(result && preserve_result)
5550     {
5551       int i;
5552       for(i = 0; i < AOP_SIZE(result); i++)
5553         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5554
5555       pic16_emitpLabel(lbl_done->key);
5556    }
5557
5558   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5559
5560   if(ifx)
5561     ifx->generated = 1;
5562 }
5563 #endif
5564
5565 #if 0
5566 /*-----------------------------------------------------------------*/
5567 /* gencjne - compare and jump if not equal                         */
5568 /*-----------------------------------------------------------------*/
5569 static void gencjne(operand *left, operand *right, iCode *ifx)
5570 {
5571     symbol *tlbl  = newiTempLabel(NULL);
5572
5573     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5574     gencjneshort(left, right, lbl);
5575
5576     pic16_emitcode("mov","a,%s",one);
5577     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5578     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5579     pic16_emitcode("clr","a");
5580     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5581
5582     pic16_emitpLabel(lbl->key);
5583     pic16_emitpLabel(tlbl->key);
5584
5585 }
5586 #endif
5587
5588
5589 /*-----------------------------------------------------------------*/
5590 /* is_LitOp - check if operand has to be treated as literal        */
5591 /*-----------------------------------------------------------------*/
5592 static bool is_LitOp(operand *op)
5593 {
5594   return (AOP_TYPE(op) == AOP_LIT)
5595       || ( (AOP_TYPE(op) == AOP_PCODE)
5596           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5597               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5598 }
5599
5600 /*-----------------------------------------------------------------*/
5601 /* is_LitAOp - check if operand has to be treated as literal        */
5602 /*-----------------------------------------------------------------*/
5603 static bool is_LitAOp(asmop *aop)
5604 {
5605   return (aop->type == AOP_LIT)
5606       || ( (aop->type == AOP_PCODE)
5607           && ( (aop->aopu.pcop->type == PO_LITERAL)
5608               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5609 }
5610
5611
5612
5613 /*-----------------------------------------------------------------*/
5614 /* genCmpEq - generates code for equal to                          */
5615 /*-----------------------------------------------------------------*/
5616 static void genCmpEq (iCode *ic, iCode *ifx)
5617 {
5618   operand *left, *right, *result;
5619   symbol *falselbl = newiTempLabel(NULL);
5620   symbol *donelbl = newiTempLabel(NULL);
5621
5622   int preserve_result = 0;
5623   int generate_result = 0;
5624   int i=0;
5625
5626   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5627   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5628   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5629  
5630   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5631   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5632
5633   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5634     {
5635       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5636       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5637       goto release;
5638     }
5639
5640   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5641     {
5642       operand *tmp = right ;
5643       right = left;
5644       left = tmp;
5645     }
5646
5647   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5648     preserve_result = 1;
5649
5650   if(result && AOP_SIZE(result))
5651     generate_result = 1;
5652
5653   if(generate_result && !preserve_result)
5654     {
5655       for(i = 0; i < AOP_SIZE(result); i++)
5656         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5657     }
5658
5659   for(i=0; i < AOP_SIZE(left); i++)
5660     {
5661       if(AOP_TYPE(left) != AOP_ACC)
5662         {
5663           if(is_LitOp(left))
5664             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5665           else
5666             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5667         }
5668       if(is_LitOp(right))
5669         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5670       else
5671         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5672
5673       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5674     }
5675
5676   // result == true
5677
5678   if(generate_result && preserve_result)
5679     {
5680       for(i = 0; i < AOP_SIZE(result); i++)
5681         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5682     }
5683
5684   if(generate_result)
5685     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5686
5687   if(generate_result && preserve_result)
5688     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5689
5690   if(ifx && IC_TRUE(ifx))
5691     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5692
5693   if(ifx && IC_FALSE(ifx))
5694     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5695
5696   pic16_emitpLabel(falselbl->key);
5697
5698   // result == false
5699
5700   if(ifx && IC_FALSE(ifx))
5701     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5702
5703   if(generate_result && preserve_result)
5704     {
5705       for(i = 0; i < AOP_SIZE(result); i++)
5706         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5707     }
5708
5709   pic16_emitpLabel(donelbl->key);
5710
5711   if(ifx)
5712     ifx->generated = 1;
5713
5714 release:
5715   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5716   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5717   pic16_freeAsmop(result,NULL,ic,TRUE);
5718
5719 }
5720
5721
5722 #if 0
5723 // old version kept for reference
5724
5725 /*-----------------------------------------------------------------*/
5726 /* genCmpEq - generates code for equal to                          */
5727 /*-----------------------------------------------------------------*/
5728 static void genCmpEq (iCode *ic, iCode *ifx)
5729 {
5730     operand *left, *right, *result;
5731     unsigned long lit = 0L;
5732     int size,offset=0;
5733     symbol *falselbl  = newiTempLabel(NULL);
5734
5735
5736     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5737
5738     if(ifx)
5739       DEBUGpic16_emitcode ("; ifx is non-null","");
5740     else
5741       DEBUGpic16_emitcode ("; ifx is null","");
5742
5743     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5744     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5745     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5746
5747     size = max(AOP_SIZE(left),AOP_SIZE(right));
5748
5749     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5750
5751     /* if literal, literal on the right or 
5752     if the right is in a pointer register and left 
5753     is not */
5754     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5755         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5756       operand *tmp = right ;
5757       right = left;
5758       left = tmp;
5759     }
5760
5761
5762     if(ifx && !AOP_SIZE(result)){
5763         symbol *tlbl;
5764         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5765         /* if they are both bit variables */
5766         if (AOP_TYPE(left) == AOP_CRY &&
5767             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5768                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5769             if(AOP_TYPE(right) == AOP_LIT){
5770                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5771                 if(lit == 0L){
5772                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5773                     pic16_emitcode("cpl","c");
5774                 } else if(lit == 1L) {
5775                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5776                 } else {
5777                     pic16_emitcode("clr","c");
5778                 }
5779                 /* AOP_TYPE(right) == AOP_CRY */
5780             } else {
5781                 symbol *lbl = newiTempLabel(NULL);
5782                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5783                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5784                 pic16_emitcode("cpl","c");
5785                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5786             }
5787             /* if true label then we jump if condition
5788             supplied is true */
5789             tlbl = newiTempLabel(NULL);
5790             if ( IC_TRUE(ifx) ) {
5791                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5792                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5793             } else {
5794                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5795                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5796             }
5797             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5798
5799                 {
5800                 /* left and right are both bit variables, result is carry */
5801                         resolvedIfx rIfx;
5802               
5803                         resolveIfx(&rIfx,ifx);
5804
5805                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5806                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5807                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5808                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5809                         genSkipz2(&rIfx,0);
5810                 }
5811         } else {
5812
5813                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5814
5815                         /* They're not both bit variables. Is the right a literal? */
5816                         if(AOP_TYPE(right) == AOP_LIT) {
5817                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5818             
5819                         switch(size) {
5820
5821                                 case 1:
5822                                         switch(lit & 0xff) {
5823                                                 case 1:
5824                                                                 if ( IC_TRUE(ifx) ) {
5825                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5826                                                                         emitSKPNZ;
5827                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5828                                                                 } else {
5829                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5830                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5831                                                                 }
5832                                                                 break;
5833                                                 case 0xff:
5834                                                                 if ( IC_TRUE(ifx) ) {
5835                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5836                                                                         emitSKPNZ;
5837                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5838                                                                 } else {
5839                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5840                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5841                                                                 }
5842                                                                 break;
5843                                                 default:
5844                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5845                                                                 if(lit)
5846                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5847                                                                 genSkip(ifx,'z');
5848                                         } // switch lit
5849
5850
5851                                         /* end of size == 1 */
5852                                         break;
5853               
5854                                 case 2:
5855                                         genc16bit2lit(left,lit,offset);
5856                                         genSkip(ifx,'z');
5857                                         break;
5858                                         /* end of size == 2 */
5859
5860                                 default:
5861                                         /* size is 4 */
5862                                         if(lit==0) {
5863                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5864                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5865                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5866                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5867                                                 genSkip(ifx,'z');
5868                                         } else {
5869                                                 /* search for patterns that can be optimized */
5870
5871                                                 genc16bit2lit(left,lit,0);
5872                                                 lit >>= 16;
5873                                                 if(lit) {
5874                                                                 if(IC_TRUE(ifx))
5875                                                                 emitSKPZ; // if hi word unequal
5876                                                                 else
5877                                                                 emitSKPNZ; // if hi word equal
5878                                                                 // fail early
5879                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5880                                                         genc16bit2lit(left,lit,2);
5881                                                         genSkip(ifx,'z');
5882                                                 } else {
5883                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5884                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5885                                                         genSkip(ifx,'z');
5886                                                 }
5887                                         }
5888                                                 pic16_emitpLabel(falselbl->key);
5889                                                 break;
5890
5891                         } // switch size
5892           
5893                         ifx->generated = 1;
5894                         goto release ;
5895             
5896
5897           } else if(AOP_TYPE(right) == AOP_CRY ) {
5898             /* we know the left is not a bit, but that the right is */
5899             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5900             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5901                       pic16_popGet(AOP(right),offset));
5902             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5903
5904             /* if the two are equal, then W will be 0 and the Z bit is set
5905              * we could test Z now, or go ahead and check the high order bytes if
5906              * the variable we're comparing is larger than a byte. */
5907
5908             while(--size)
5909               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5910
5911             if ( IC_TRUE(ifx) ) {
5912               emitSKPNZ;
5913               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5914               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5915             } else {
5916               emitSKPZ;
5917               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5918               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5919             }
5920
5921           } else {
5922             /* They're both variables that are larger than bits */
5923             int s = size;
5924
5925             tlbl = newiTempLabel(NULL);
5926
5927             while(size--) {
5928               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5929               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5930
5931               if ( IC_TRUE(ifx) ) {
5932                 if(size) {
5933                   emitSKPZ;
5934                 
5935                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5936
5937                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5938                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5939                 } else {
5940                   emitSKPNZ;
5941
5942                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5943
5944
5945                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5946                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5947                 }
5948               } else {
5949                 emitSKPZ;
5950
5951                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5952
5953                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5954                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5955               }
5956               offset++;
5957             }
5958             if(s>1 && IC_TRUE(ifx)) {
5959               pic16_emitpLabel(tlbl->key);
5960               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5961             }
5962           }
5963         }
5964         /* mark the icode as generated */
5965         ifx->generated = 1;
5966         goto release ;
5967     }
5968
5969     /* if they are both bit variables */
5970     if (AOP_TYPE(left) == AOP_CRY &&
5971         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5972         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5973         if(AOP_TYPE(right) == AOP_LIT){
5974             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5975             if(lit == 0L){
5976                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5977                 pic16_emitcode("cpl","c");
5978             } else if(lit == 1L) {
5979                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5980             } else {
5981                 pic16_emitcode("clr","c");
5982             }
5983             /* AOP_TYPE(right) == AOP_CRY */
5984         } else {
5985             symbol *lbl = newiTempLabel(NULL);
5986             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5987             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5988             pic16_emitcode("cpl","c");
5989             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5990         }
5991         /* c = 1 if egal */
5992         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5993             pic16_outBitC(result);
5994             goto release ;
5995         }
5996         if (ifx) {
5997             genIfxJump (ifx,"c");
5998             goto release ;
5999         }
6000         /* if the result is used in an arithmetic operation
6001         then put the result in place */
6002         pic16_outBitC(result);
6003     } else {
6004       
6005       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6006       gencjne(left,right,result,ifx);
6007 /*
6008       if(ifx) 
6009         gencjne(left,right,newiTempLabel(NULL));
6010       else {
6011         if(IC_TRUE(ifx)->key)
6012           gencjne(left,right,IC_TRUE(ifx)->key);
6013         else
6014           gencjne(left,right,IC_FALSE(ifx)->key);
6015         ifx->generated = 1;
6016         goto release ;
6017       }
6018       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6019         pic16_aopPut(AOP(result),"a",0);
6020         goto release ;
6021       }
6022
6023       if (ifx) {
6024         genIfxJump (ifx,"a");
6025         goto release ;
6026       }
6027 */
6028       /* if the result is used in an arithmetic operation
6029          then put the result in place */
6030 /*
6031       if (AOP_TYPE(result) != AOP_CRY) 
6032         pic16_outAcc(result);
6033 */
6034       /* leave the result in acc */
6035     }
6036
6037 release:
6038     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6039     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6040     pic16_freeAsmop(result,NULL,ic,TRUE);
6041 }
6042 #endif
6043
6044 /*-----------------------------------------------------------------*/
6045 /* ifxForOp - returns the icode containing the ifx for operand     */
6046 /*-----------------------------------------------------------------*/
6047 static iCode *ifxForOp ( operand *op, iCode *ic )
6048 {
6049     /* if true symbol then needs to be assigned */
6050     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6051     if (IS_TRUE_SYMOP(op))
6052         return NULL ;
6053
6054     /* if this has register type condition and
6055     the next instruction is ifx with the same operand
6056     and live to of the operand is upto the ifx only then */
6057     if (ic->next
6058         && ic->next->op == IFX
6059         && IC_COND(ic->next)->key == op->key
6060         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6061         ) {
6062                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6063           return ic->next;
6064     }
6065
6066     if (ic->next &&
6067         ic->next->op == IFX &&
6068         IC_COND(ic->next)->key == op->key) {
6069       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6070       return ic->next;
6071     }
6072
6073     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6074     if (ic->next &&
6075         ic->next->op == IFX)
6076       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6077
6078     if (ic->next &&
6079         ic->next->op == IFX &&
6080         IC_COND(ic->next)->key == op->key) {
6081       DEBUGpic16_emitcode ("; "," key is okay");
6082       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6083                            OP_SYMBOL(op)->liveTo,
6084                            ic->next->seq);
6085     }
6086
6087 #if 0
6088     /* the code below is completely untested
6089      * it just allows ulong2fs.c compile -- VR */
6090          
6091     ic = ic->next;
6092     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6093                                         __FILE__, __FUNCTION__, __LINE__);
6094         
6095     /* if this has register type condition and
6096     the next instruction is ifx with the same operand
6097     and live to of the operand is upto the ifx only then */
6098     if (ic->next &&
6099         ic->next->op == IFX &&
6100         IC_COND(ic->next)->key == op->key &&
6101         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6102         return ic->next;
6103
6104     if (ic->next &&
6105         ic->next->op == IFX &&
6106         IC_COND(ic->next)->key == op->key) {
6107       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6108       return ic->next;
6109     }
6110
6111     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6112                                         __FILE__, __FUNCTION__, __LINE__);
6113
6114 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6115 #endif
6116
6117     return NULL;
6118 }
6119 /*-----------------------------------------------------------------*/
6120 /* genAndOp - for && operation                                     */
6121 /*-----------------------------------------------------------------*/
6122 static void genAndOp (iCode *ic)
6123 {
6124     operand *left,*right, *result;
6125 /*     symbol *tlbl; */
6126
6127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6128     /* note here that && operations that are in an
6129     if statement are taken away by backPatchLabels
6130     only those used in arthmetic operations remain */
6131     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6132     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6133     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6134
6135     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6136
6137     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6138     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6139     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6140
6141     /* if both are bit variables */
6142 /*     if (AOP_TYPE(left) == AOP_CRY && */
6143 /*         AOP_TYPE(right) == AOP_CRY ) { */
6144 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6145 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6146 /*         pic16_outBitC(result); */
6147 /*     } else { */
6148 /*         tlbl = newiTempLabel(NULL); */
6149 /*         pic16_toBoolean(left);     */
6150 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6151 /*         pic16_toBoolean(right); */
6152 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6153 /*         pic16_outBitAcc(result); */
6154 /*     } */
6155
6156     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6157     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6158     pic16_freeAsmop(result,NULL,ic,TRUE);
6159 }
6160
6161
6162 /*-----------------------------------------------------------------*/
6163 /* genOrOp - for || operation                                      */
6164 /*-----------------------------------------------------------------*/
6165 /*
6166   tsd pic port -
6167   modified this code, but it doesn't appear to ever get called
6168 */
6169
6170 static void genOrOp (iCode *ic)
6171 {
6172     operand *left,*right, *result;
6173     symbol *tlbl;
6174
6175     /* note here that || operations that are in an
6176     if statement are taken away by backPatchLabels
6177     only those used in arthmetic operations remain */
6178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6179     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6180     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6181     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6182
6183     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6184
6185     /* if both are bit variables */
6186     if (AOP_TYPE(left) == AOP_CRY &&
6187         AOP_TYPE(right) == AOP_CRY ) {
6188       pic16_emitcode("clrc","");
6189       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6190                AOP(left)->aopu.aop_dir,
6191                AOP(left)->aopu.aop_dir);
6192       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6193                AOP(right)->aopu.aop_dir,
6194                AOP(right)->aopu.aop_dir);
6195       pic16_emitcode("setc","");
6196
6197     } else {
6198         tlbl = newiTempLabel(NULL);
6199         pic16_toBoolean(left);
6200         emitSKPZ;
6201         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6202         pic16_toBoolean(right);
6203         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6204
6205         pic16_outBitAcc(result);
6206     }
6207
6208     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6209     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210     pic16_freeAsmop(result,NULL,ic,TRUE);            
6211 }
6212
6213 /*-----------------------------------------------------------------*/
6214 /* isLiteralBit - test if lit == 2^n                               */
6215 /*-----------------------------------------------------------------*/
6216 static int isLiteralBit(unsigned long lit)
6217 {
6218     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6219     0x100L,0x200L,0x400L,0x800L,
6220     0x1000L,0x2000L,0x4000L,0x8000L,
6221     0x10000L,0x20000L,0x40000L,0x80000L,
6222     0x100000L,0x200000L,0x400000L,0x800000L,
6223     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6224     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6225     int idx;
6226     
6227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6228     for(idx = 0; idx < 32; idx++)
6229         if(lit == pw[idx])
6230             return idx+1;
6231     return 0;
6232 }
6233
6234 /*-----------------------------------------------------------------*/
6235 /* continueIfTrue -                                                */
6236 /*-----------------------------------------------------------------*/
6237 static void continueIfTrue (iCode *ic)
6238 {
6239     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6240     if(IC_TRUE(ic))
6241         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6242     ic->generated = 1;
6243 }
6244
6245 /*-----------------------------------------------------------------*/
6246 /* jmpIfTrue -                                                     */
6247 /*-----------------------------------------------------------------*/
6248 static void jumpIfTrue (iCode *ic)
6249 {
6250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6251     if(!IC_TRUE(ic))
6252         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6253     ic->generated = 1;
6254 }
6255
6256 /*-----------------------------------------------------------------*/
6257 /* jmpTrueOrFalse -                                                */
6258 /*-----------------------------------------------------------------*/
6259 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6260 {
6261     // ugly but optimized by peephole
6262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6263     if(IC_TRUE(ic)){
6264         symbol *nlbl = newiTempLabel(NULL);
6265         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6266         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6267         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6268         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6269     }
6270     else{
6271         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6272         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6273     }
6274     ic->generated = 1;
6275 }
6276
6277 /*-----------------------------------------------------------------*/
6278 /* genAnd  - code for and                                          */
6279 /*-----------------------------------------------------------------*/
6280 static void genAnd (iCode *ic, iCode *ifx)
6281 {
6282   operand *left, *right, *result;
6283   int size, offset=0;  
6284   unsigned long lit = 0L;
6285   int bytelit = 0;
6286   resolvedIfx rIfx;
6287
6288
6289   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6290   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6291   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6292   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6293
6294   resolveIfx(&rIfx,ifx);
6295
6296   /* if left is a literal & right is not then exchange them */
6297   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6298       AOP_NEEDSACC(left)) {
6299     operand *tmp = right ;
6300     right = left;
6301     left = tmp;
6302   }
6303
6304   /* if result = right then exchange them */
6305   if(pic16_sameRegs(AOP(result),AOP(right))){
6306     operand *tmp = right ;
6307     right = left;
6308     left = tmp;
6309   }
6310
6311   /* if right is bit then exchange them */
6312   if (AOP_TYPE(right) == AOP_CRY &&
6313       AOP_TYPE(left) != AOP_CRY){
6314     operand *tmp = right ;
6315     right = left;
6316     left = tmp;
6317   }
6318   if(AOP_TYPE(right) == AOP_LIT)
6319     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6320
6321   size = AOP_SIZE(result);
6322
6323   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6324
6325   // if(bit & yy)
6326   // result = bit & yy;
6327   if (AOP_TYPE(left) == AOP_CRY){
6328     // c = bit & literal;
6329     if(AOP_TYPE(right) == AOP_LIT){
6330       if(lit & 1) {
6331         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6332           // no change
6333           goto release;
6334         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6335       } else {
6336         // bit(result) = 0;
6337         if(size && (AOP_TYPE(result) == AOP_CRY)){
6338           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6339           goto release;
6340         }
6341         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6342           jumpIfTrue(ifx);
6343           goto release;
6344         }
6345         pic16_emitcode("clr","c");
6346       }
6347     } else {
6348       if (AOP_TYPE(right) == AOP_CRY){
6349         // c = bit & bit;
6350         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6351         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6352       } else {
6353         // c = bit & val;
6354         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6355         // c = lsb
6356         pic16_emitcode("rrc","a");
6357         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6358       }
6359     }
6360     // bit = c
6361     // val = c
6362     if(size)
6363       pic16_outBitC(result);
6364     // if(bit & ...)
6365     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6366       genIfxJump(ifx, "c");           
6367     goto release ;
6368   }
6369
6370   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6371   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6372   if((AOP_TYPE(right) == AOP_LIT) &&
6373      (AOP_TYPE(result) == AOP_CRY) &&
6374      (AOP_TYPE(left) != AOP_CRY)){
6375     int posbit = isLiteralBit(lit);
6376     /* left &  2^n */
6377     if(posbit){
6378       posbit--;
6379       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6380       // bit = left & 2^n
6381       if(size)
6382         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6383       // if(left &  2^n)
6384       else{
6385         if(ifx){
6386 /*
6387           if(IC_TRUE(ifx)) {
6388             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6389             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6390           } else {
6391             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6392             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6393           }
6394 */
6395         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6396         size = AOP_SIZE(left);
6397
6398         {
6399           int bp = posbit, ofs=0;
6400           
6401             while(bp > 7) {
6402               bp -= 8;
6403               ofs++;
6404             }
6405         
6406           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6407                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6408
6409         }
6410 /*
6411           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6412                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6413 */
6414           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6415           
6416           ifx->generated = 1;
6417         }
6418         goto release;
6419       }
6420     } else {
6421       symbol *tlbl = newiTempLabel(NULL);
6422       int sizel = AOP_SIZE(left);
6423       if(size)
6424         pic16_emitcode("setb","c");
6425       while(sizel--){
6426         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6427           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6428           // byte ==  2^n ?
6429           if((posbit = isLiteralBit(bytelit)) != 0)
6430             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6431           else{
6432             if(bytelit != 0x0FFL)
6433               pic16_emitcode("anl","a,%s",
6434                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6435             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6436           }
6437         }
6438         offset++;
6439       }
6440       // bit = left & literal
6441       if(size){
6442         pic16_emitcode("clr","c");
6443         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6444       }
6445       // if(left & literal)
6446       else{
6447         if(ifx)
6448           jmpTrueOrFalse(ifx, tlbl);
6449         goto release ;
6450       }
6451     }
6452     pic16_outBitC(result);
6453     goto release ;
6454   }
6455
6456   /* if left is same as result */
6457   if(pic16_sameRegs(AOP(result),AOP(left))){
6458     int know_W = -1;
6459     for(;size--; offset++,lit>>=8) {
6460       if(AOP_TYPE(right) == AOP_LIT){
6461         switch(lit & 0xff) {
6462         case 0x00:
6463           /*  and'ing with 0 has clears the result */
6464 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6465           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6466           break;
6467         case 0xff:
6468           /* and'ing with 0xff is a nop when the result and left are the same */
6469           break;
6470
6471         default:
6472           {
6473             int p = my_powof2( (~lit) & 0xff );
6474             if(p>=0) {
6475               /* only one bit is set in the literal, so use a bcf instruction */
6476 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6477               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6478
6479             } else {
6480               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6481               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6482               if(know_W != (lit&0xff))
6483                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6484               know_W = lit &0xff;
6485               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6486             }
6487           }    
6488         }
6489       } else {
6490         if (AOP_TYPE(left) == AOP_ACC) {
6491           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6492         } else {                    
6493           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6494           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6495
6496         }
6497       }
6498     }
6499
6500   } else {
6501     // left & result in different registers
6502     if(AOP_TYPE(result) == AOP_CRY){
6503       // result = bit
6504       // if(size), result in bit
6505       // if(!size && ifx), conditional oper: if(left & right)
6506       symbol *tlbl = newiTempLabel(NULL);
6507       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6508       if(size)
6509         pic16_emitcode("setb","c");
6510       while(sizer--){
6511         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6512         pic16_emitcode("anl","a,%s",
6513                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6514         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6515         offset++;
6516       }
6517       if(size){
6518         CLRC;
6519         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6520         pic16_outBitC(result);
6521       } else if(ifx)
6522         jmpTrueOrFalse(ifx, tlbl);
6523     } else {
6524       for(;(size--);offset++) {
6525         // normal case
6526         // result = left & right
6527         if(AOP_TYPE(right) == AOP_LIT){
6528           int t = (lit >> (offset*8)) & 0x0FFL;
6529           switch(t) { 
6530           case 0x00:
6531             pic16_emitcode("clrf","%s",
6532                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6533             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6534             break;
6535           case 0xff:
6536             pic16_emitcode("movf","%s,w",
6537                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6538             pic16_emitcode("movwf","%s",
6539                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6540             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6541             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6542             break;
6543           default:
6544             pic16_emitcode("movlw","0x%x",t);
6545             pic16_emitcode("andwf","%s,w",
6546                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6547             pic16_emitcode("movwf","%s",
6548                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6549               
6550             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6551             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6552             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6553           }
6554           continue;
6555         }
6556
6557         if (AOP_TYPE(left) == AOP_ACC) {
6558           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6559           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6560         } else {
6561           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6562           pic16_emitcode("andwf","%s,w",
6563                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6564           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6565           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6566         }
6567         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6568         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6569       }
6570     }
6571   }
6572
6573   release :
6574     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6575   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6576   pic16_freeAsmop(result,NULL,ic,TRUE);     
6577 }
6578
6579 /*-----------------------------------------------------------------*/
6580 /* genOr  - code for or                                            */
6581 /*-----------------------------------------------------------------*/
6582 static void genOr (iCode *ic, iCode *ifx)
6583 {
6584     operand *left, *right, *result;
6585     int size, offset=0;
6586     unsigned long lit = 0L;
6587
6588     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6589
6590     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6591     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6592     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6593
6594     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6595
6596     /* if left is a literal & right is not then exchange them */
6597     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6598         AOP_NEEDSACC(left)) {
6599         operand *tmp = right ;
6600         right = left;
6601         left = tmp;
6602     }
6603
6604     /* if result = right then exchange them */
6605     if(pic16_sameRegs(AOP(result),AOP(right))){
6606         operand *tmp = right ;
6607         right = left;
6608         left = tmp;
6609     }
6610
6611     /* if right is bit then exchange them */
6612     if (AOP_TYPE(right) == AOP_CRY &&
6613         AOP_TYPE(left) != AOP_CRY){
6614         operand *tmp = right ;
6615         right = left;
6616         left = tmp;
6617     }
6618
6619     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6620
6621     if(AOP_TYPE(right) == AOP_LIT)
6622         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6623
6624     size = AOP_SIZE(result);
6625
6626     // if(bit | yy)
6627     // xx = bit | yy;
6628     if (AOP_TYPE(left) == AOP_CRY){
6629         if(AOP_TYPE(right) == AOP_LIT){
6630             // c = bit & literal;
6631             if(lit){
6632                 // lit != 0 => result = 1
6633                 if(AOP_TYPE(result) == AOP_CRY){
6634                   if(size)
6635                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6636                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6637                   //     AOP(result)->aopu.aop_dir,
6638                   //     AOP(result)->aopu.aop_dir);
6639                     else if(ifx)
6640                         continueIfTrue(ifx);
6641                     goto release;
6642                 }
6643             } else {
6644                 // lit == 0 => result = left
6645                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6646                     goto release;
6647                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6648             }
6649         } else {
6650             if (AOP_TYPE(right) == AOP_CRY){
6651               if(pic16_sameRegs(AOP(result),AOP(left))){
6652                 // c = bit | bit;
6653                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6654                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6655                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6656
6657                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6658                          AOP(result)->aopu.aop_dir,
6659                          AOP(result)->aopu.aop_dir);
6660                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6661                          AOP(right)->aopu.aop_dir,
6662                          AOP(right)->aopu.aop_dir);
6663                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6664                          AOP(result)->aopu.aop_dir,
6665                          AOP(result)->aopu.aop_dir);
6666               } else {
6667                 if( AOP_TYPE(result) == AOP_ACC) {
6668                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6669                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6670                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6671                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6672
6673                 } else {
6674
6675                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6676                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6677                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6678                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6679
6680                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6681                                  AOP(result)->aopu.aop_dir,
6682                                  AOP(result)->aopu.aop_dir);
6683                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6684                                  AOP(right)->aopu.aop_dir,
6685                                  AOP(right)->aopu.aop_dir);
6686                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6687                                  AOP(left)->aopu.aop_dir,
6688                                  AOP(left)->aopu.aop_dir);
6689                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6690                                  AOP(result)->aopu.aop_dir,
6691                                  AOP(result)->aopu.aop_dir);
6692                 }
6693               }
6694             } else {
6695                 // c = bit | val;
6696                 symbol *tlbl = newiTempLabel(NULL);
6697                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6698
6699
6700                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6701                 if( AOP_TYPE(right) == AOP_ACC) {
6702                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6703                   emitSKPNZ;
6704                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6705                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6706                 }
6707
6708
6709
6710                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6711                     pic16_emitcode(";XXX setb","c");
6712                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6713                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6714                 pic16_toBoolean(right);
6715                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6716                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6717                     jmpTrueOrFalse(ifx, tlbl);
6718                     goto release;
6719                 } else {
6720                     CLRC;
6721                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6722                 }
6723             }
6724         }
6725         // bit = c
6726         // val = c
6727         if(size)
6728             pic16_outBitC(result);
6729         // if(bit | ...)
6730         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6731             genIfxJump(ifx, "c");           
6732         goto release ;
6733     }
6734
6735     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6736     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6737     if((AOP_TYPE(right) == AOP_LIT) &&
6738        (AOP_TYPE(result) == AOP_CRY) &&
6739        (AOP_TYPE(left) != AOP_CRY)){
6740         if(lit){
6741           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6742             // result = 1
6743             if(size)
6744                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6745             else 
6746                 continueIfTrue(ifx);
6747             goto release;
6748         } else {
6749           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6750             // lit = 0, result = boolean(left)
6751             if(size)
6752                 pic16_emitcode(";XXX setb","c");
6753             pic16_toBoolean(right);
6754             if(size){
6755                 symbol *tlbl = newiTempLabel(NULL);
6756                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6757                 CLRC;
6758                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6759             } else {
6760                 genIfxJump (ifx,"a");
6761                 goto release;
6762             }
6763         }
6764         pic16_outBitC(result);
6765         goto release ;
6766     }
6767
6768     /* if left is same as result */
6769     if(pic16_sameRegs(AOP(result),AOP(left))){
6770       int know_W = -1;
6771       for(;size--; offset++,lit>>=8) {
6772         if(AOP_TYPE(right) == AOP_LIT){
6773           if((lit & 0xff) == 0)
6774             /*  or'ing with 0 has no effect */
6775             continue;
6776           else {
6777             int p = my_powof2(lit & 0xff);
6778             if(p>=0) {
6779               /* only one bit is set in the literal, so use a bsf instruction */
6780               pic16_emitpcode(POC_BSF,
6781                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6782             } else {
6783               if(know_W != (lit & 0xff))
6784                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6785               know_W = lit & 0xff;
6786               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6787             }
6788                     
6789           }
6790         } else {
6791           if (AOP_TYPE(left) == AOP_ACC) {
6792             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6793             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6794           } else {                  
6795             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6796             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6797
6798             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6799             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6800
6801           }
6802         }
6803       }
6804     } else {
6805         // left & result in different registers
6806         if(AOP_TYPE(result) == AOP_CRY){
6807             // result = bit
6808             // if(size), result in bit
6809             // if(!size && ifx), conditional oper: if(left | right)
6810             symbol *tlbl = newiTempLabel(NULL);
6811             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6812             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6813
6814
6815             if(size)
6816                 pic16_emitcode(";XXX setb","c");
6817             while(sizer--){
6818                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6819                 pic16_emitcode(";XXX orl","a,%s",
6820                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6821                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6822                 offset++;
6823             }
6824             if(size){
6825                 CLRC;
6826                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6827                 pic16_outBitC(result);
6828             } else if(ifx)
6829                 jmpTrueOrFalse(ifx, tlbl);
6830         } else for(;(size--);offset++){
6831           // normal case
6832           // result = left & right
6833           if(AOP_TYPE(right) == AOP_LIT){
6834             int t = (lit >> (offset*8)) & 0x0FFL;
6835             switch(t) { 
6836             case 0x00:
6837               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6838               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6839
6840               pic16_emitcode("movf","%s,w",
6841                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6842               pic16_emitcode("movwf","%s",
6843                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6844               break;
6845             default:
6846               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6847               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6848               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6849
6850               pic16_emitcode("movlw","0x%x",t);
6851               pic16_emitcode("iorwf","%s,w",
6852                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6853               pic16_emitcode("movwf","%s",
6854                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6855               
6856             }
6857             continue;
6858           }
6859
6860           // faster than result <- left, anl result,right
6861           // and better if result is SFR
6862           if (AOP_TYPE(left) == AOP_ACC) {
6863             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6864             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6865           } else {
6866             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6867             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6868
6869             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6870             pic16_emitcode("iorwf","%s,w",
6871                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6872           }
6873           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6874           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6875         }
6876     }
6877
6878 release :
6879     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6880     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6881     pic16_freeAsmop(result,NULL,ic,TRUE);     
6882 }
6883
6884 /*-----------------------------------------------------------------*/
6885 /* genXor - code for xclusive or                                   */
6886 /*-----------------------------------------------------------------*/
6887 static void genXor (iCode *ic, iCode *ifx)
6888 {
6889   operand *left, *right, *result;
6890   int size, offset=0;
6891   unsigned long lit = 0L;
6892
6893   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6894
6895   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6896   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6897   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6898
6899   /* if left is a literal & right is not ||
6900      if left needs acc & right does not */
6901   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6902       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6903     operand *tmp = right ;
6904     right = left;
6905     left = tmp;
6906   }
6907
6908   /* if result = right then exchange them */
6909   if(pic16_sameRegs(AOP(result),AOP(right))){
6910     operand *tmp = right ;
6911     right = left;
6912     left = tmp;
6913   }
6914
6915   /* if right is bit then exchange them */
6916   if (AOP_TYPE(right) == AOP_CRY &&
6917       AOP_TYPE(left) != AOP_CRY){
6918     operand *tmp = right ;
6919     right = left;
6920     left = tmp;
6921   }
6922   if(AOP_TYPE(right) == AOP_LIT)
6923     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6924
6925   size = AOP_SIZE(result);
6926
6927   // if(bit ^ yy)
6928   // xx = bit ^ yy;
6929   if (AOP_TYPE(left) == AOP_CRY){
6930     if(AOP_TYPE(right) == AOP_LIT){
6931       // c = bit & literal;
6932       if(lit>>1){
6933         // lit>>1  != 0 => result = 1
6934         if(AOP_TYPE(result) == AOP_CRY){
6935           if(size)
6936             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6937             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6938           else if(ifx)
6939             continueIfTrue(ifx);
6940           goto release;
6941         }
6942         pic16_emitcode("setb","c");
6943       } else{
6944         // lit == (0 or 1)
6945         if(lit == 0){
6946           // lit == 0, result = left
6947           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6948             goto release;
6949           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6950         } else{
6951           // lit == 1, result = not(left)
6952           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6953             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6954             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6955             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6956             goto release;
6957           } else {
6958             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6959             pic16_emitcode("cpl","c");
6960           }
6961         }
6962       }
6963
6964     } else {
6965       // right != literal
6966       symbol *tlbl = newiTempLabel(NULL);
6967       if (AOP_TYPE(right) == AOP_CRY){
6968         // c = bit ^ bit;
6969         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6970       }
6971       else{
6972         int sizer = AOP_SIZE(right);
6973         // c = bit ^ val
6974         // if val>>1 != 0, result = 1
6975         pic16_emitcode("setb","c");
6976         while(sizer){
6977           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6978           if(sizer == 1)
6979             // test the msb of the lsb
6980             pic16_emitcode("anl","a,#0xfe");
6981           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6982           sizer--;
6983         }
6984         // val = (0,1)
6985         pic16_emitcode("rrc","a");
6986       }
6987       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6988       pic16_emitcode("cpl","c");
6989       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6990     }
6991     // bit = c
6992     // val = c
6993     if(size)
6994       pic16_outBitC(result);
6995     // if(bit | ...)
6996     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6997       genIfxJump(ifx, "c");           
6998     goto release ;
6999   }
7000
7001   if(pic16_sameRegs(AOP(result),AOP(left))){
7002     /* if left is same as result */
7003     for(;size--; offset++) {
7004       if(AOP_TYPE(right) == AOP_LIT){
7005         int t  = (lit >> (offset*8)) & 0x0FFL;
7006         if(t == 0x00L)
7007           continue;
7008         else
7009           if (IS_AOP_PREG(left)) {
7010             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7011             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7012             pic16_aopPut(AOP(result),"a",offset);
7013           } else {
7014             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7015             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7016             pic16_emitcode("xrl","%s,%s",
7017                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7018                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7019           }
7020       } else {
7021         if (AOP_TYPE(left) == AOP_ACC)
7022           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7023         else {
7024           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7025           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7026 /*
7027           if (IS_AOP_PREG(left)) {
7028             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7029             pic16_aopPut(AOP(result),"a",offset);
7030           } else
7031             pic16_emitcode("xrl","%s,a",
7032                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7033 */
7034         }
7035       }
7036     }
7037   } else {
7038     // left & result in different registers
7039     if(AOP_TYPE(result) == AOP_CRY){
7040       // result = bit
7041       // if(size), result in bit
7042       // if(!size && ifx), conditional oper: if(left ^ right)
7043       symbol *tlbl = newiTempLabel(NULL);
7044       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7045       if(size)
7046         pic16_emitcode("setb","c");
7047       while(sizer--){
7048         if((AOP_TYPE(right) == AOP_LIT) &&
7049            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7050           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7051         } else {
7052           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7053           pic16_emitcode("xrl","a,%s",
7054                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7055         }
7056         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7057         offset++;
7058       }
7059       if(size){
7060         CLRC;
7061         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7062         pic16_outBitC(result);
7063       } else if(ifx)
7064         jmpTrueOrFalse(ifx, tlbl);
7065     } else for(;(size--);offset++){
7066       // normal case
7067       // result = left & right
7068       if(AOP_TYPE(right) == AOP_LIT){
7069         int t = (lit >> (offset*8)) & 0x0FFL;
7070         switch(t) { 
7071         case 0x00:
7072           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7073           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7074           pic16_emitcode("movf","%s,w",
7075                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7076           pic16_emitcode("movwf","%s",
7077                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7078           break;
7079         case 0xff:
7080           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7081           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7082           pic16_emitcode("comf","%s,w",
7083                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7084           pic16_emitcode("movwf","%s",
7085                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7086           break;
7087         default:
7088           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7089           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7090           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7091           pic16_emitcode("movlw","0x%x",t);
7092           pic16_emitcode("xorwf","%s,w",
7093                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7094           pic16_emitcode("movwf","%s",
7095                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7096
7097         }
7098         continue;
7099       }
7100
7101       // faster than result <- left, anl result,right
7102       // and better if result is SFR
7103       if (AOP_TYPE(left) == AOP_ACC) {
7104         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7105         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7106       } else {
7107         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7108         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7109         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7110         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7111       }
7112       if ( AOP_TYPE(result) != AOP_ACC){
7113         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7114         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7115       }
7116     }
7117   }
7118
7119   release :
7120     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7121   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7122   pic16_freeAsmop(result,NULL,ic,TRUE);     
7123 }
7124
7125 /*-----------------------------------------------------------------*/
7126 /* genInline - write the inline code out                           */
7127 /*-----------------------------------------------------------------*/
7128 static void genInline (iCode *ic)
7129 {
7130   char *buffer, *bp, *bp1;
7131     
7132         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7133
7134         _G.inLine += (!options.asmpeep);
7135
7136         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7137         strcpy(buffer,IC_INLINE(ic));
7138
7139 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7140
7141         /* emit each line as a code */
7142         while (*bp) {
7143                 if (*bp == '\n') {
7144                         *bp++ = '\0';
7145
7146                         if(*bp1)
7147                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7148                         bp1 = bp;
7149                 } else {
7150                         if (*bp == ':') {
7151                                 bp++;
7152                                 *bp = '\0';
7153                                 bp++;
7154
7155                                 /* print label, use this special format with NULL directive
7156                                  * to denote that the argument should not be indented with tab */
7157                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7158                                 bp1 = bp;
7159                         } else
7160                                 bp++;
7161                 }
7162         }
7163
7164         if ((bp1 != bp) && *bp1)
7165                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7166
7167
7168     Safe_free(buffer);
7169
7170     _G.inLine -= (!options.asmpeep);
7171 }
7172
7173 /*-----------------------------------------------------------------*/
7174 /* genRRC - rotate right with carry                                */
7175 /*-----------------------------------------------------------------*/
7176 static void genRRC (iCode *ic)
7177 {
7178   operand *left , *result ;
7179   int size, offset = 0, same;
7180
7181   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7182
7183   /* rotate right with carry */
7184   left = IC_LEFT(ic);
7185   result=IC_RESULT(ic);
7186   pic16_aopOp (left,ic,FALSE);
7187   pic16_aopOp (result,ic,FALSE);
7188
7189   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7190
7191   same = pic16_sameRegs(AOP(result),AOP(left));
7192
7193   size = AOP_SIZE(result);    
7194
7195   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7196
7197   /* get the lsb and put it into the carry */
7198   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7199
7200   offset = 0 ;
7201
7202   while(size--) {
7203
7204     if(same) {
7205       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7206     } else {
7207       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7208       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7209     }
7210
7211     offset++;
7212   }
7213
7214   pic16_freeAsmop(left,NULL,ic,TRUE);
7215   pic16_freeAsmop(result,NULL,ic,TRUE);
7216 }
7217
7218 /*-----------------------------------------------------------------*/
7219 /* genRLC - generate code for rotate left with carry               */
7220 /*-----------------------------------------------------------------*/
7221 static void genRLC (iCode *ic)
7222 {    
7223   operand *left , *result ;
7224   int size, offset = 0;
7225   int same;
7226
7227   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7228   /* rotate right with carry */
7229   left = IC_LEFT(ic);
7230   result=IC_RESULT(ic);
7231   pic16_aopOp (left,ic,FALSE);
7232   pic16_aopOp (result,ic,FALSE);
7233
7234   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7235
7236   same = pic16_sameRegs(AOP(result),AOP(left));
7237
7238   /* move it to the result */
7239   size = AOP_SIZE(result);    
7240
7241   /* get the msb and put it into the carry */
7242   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7243
7244   offset = 0 ;
7245
7246   while(size--) {
7247
7248     if(same) {
7249       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7250     } else {
7251       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7252       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7253     }
7254
7255     offset++;
7256   }
7257
7258
7259   pic16_freeAsmop(left,NULL,ic,TRUE);
7260   pic16_freeAsmop(result,NULL,ic,TRUE);
7261 }
7262
7263
7264 /* gpasm can get the highest order bit with HIGH/UPPER
7265  * so the following probably is not needed -- VR */
7266  
7267 /*-----------------------------------------------------------------*/
7268 /* genGetHbit - generates code get highest order bit               */
7269 /*-----------------------------------------------------------------*/
7270 static void genGetHbit (iCode *ic)
7271 {
7272     operand *left, *result;
7273     left = IC_LEFT(ic);
7274     result=IC_RESULT(ic);
7275     pic16_aopOp (left,ic,FALSE);
7276     pic16_aopOp (result,ic,FALSE);
7277
7278     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7279     /* get the highest order byte into a */
7280     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7281     if(AOP_TYPE(result) == AOP_CRY){
7282         pic16_emitcode("rlc","a");
7283         pic16_outBitC(result);
7284     }
7285     else{
7286         pic16_emitcode("rl","a");
7287         pic16_emitcode("anl","a,#0x01");
7288         pic16_outAcc(result);
7289     }
7290
7291
7292     pic16_freeAsmop(left,NULL,ic,TRUE);
7293     pic16_freeAsmop(result,NULL,ic,TRUE);
7294 }
7295
7296 #if 0
7297 /*-----------------------------------------------------------------*/
7298 /* AccRol - rotate left accumulator by known count                 */
7299 /*-----------------------------------------------------------------*/
7300 static void AccRol (int shCount)
7301 {
7302     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7303     shCount &= 0x0007;              // shCount : 0..7
7304     switch(shCount){
7305         case 0 :
7306             break;
7307         case 1 :
7308             pic16_emitcode("rl","a");
7309             break;
7310         case 2 :
7311             pic16_emitcode("rl","a");
7312             pic16_emitcode("rl","a");
7313             break;
7314         case 3 :
7315             pic16_emitcode("swap","a");
7316             pic16_emitcode("rr","a");
7317             break;
7318         case 4 :
7319             pic16_emitcode("swap","a");
7320             break;
7321         case 5 :
7322             pic16_emitcode("swap","a");
7323             pic16_emitcode("rl","a");
7324             break;
7325         case 6 :
7326             pic16_emitcode("rr","a");
7327             pic16_emitcode("rr","a");
7328             break;
7329         case 7 :
7330             pic16_emitcode("rr","a");
7331             break;
7332     }
7333 }
7334 #endif
7335
7336 /*-----------------------------------------------------------------*/
7337 /* AccLsh - left shift accumulator by known count                  */
7338 /*-----------------------------------------------------------------*/
7339 static void AccLsh (int shCount)
7340 {
7341         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7342         switch(shCount){
7343                 case 0 :
7344                         return;
7345                         break;
7346                 case 1 :
7347                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7348                         break;
7349                 case 2 :
7350                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7351                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7352                         break;
7353                 case 3 :
7354                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7355                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7356                         break;
7357                 case 4 :
7358                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7359                         break;
7360                 case 5 :
7361                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7362                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7363                         break;
7364                 case 6 :
7365                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7366                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7367                         break;
7368                 case 7 :
7369                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7370                         break;
7371         }
7372
7373         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7374 }
7375
7376 /*-----------------------------------------------------------------*/
7377 /* AccRsh - right shift accumulator by known count                 */
7378 /*-----------------------------------------------------------------*/
7379 static void AccRsh (int shCount, int andmask)
7380 {
7381         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7382         switch(shCount){
7383                 case 0 :
7384                         return; break;
7385                 case 1 :
7386                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7387 //                      andmask = 0;    /* no need */
7388                         break;
7389                 case 2 :
7390                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7391                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7392 //                      andmask = 0;    /* no need */
7393                         break;
7394                 case 3 :
7395                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7396                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7397                         break;
7398                 case 4 :
7399                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7400                         break;
7401                 case 5 :
7402                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7403                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7404                         break;
7405                 case 6 :
7406                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7407                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7408                         break;
7409                 case 7 :
7410                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7411                         break;
7412         }
7413         
7414         if(andmask)
7415                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7416         else
7417                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7418 }
7419
7420 #if 0
7421 /*-----------------------------------------------------------------*/
7422 /* AccSRsh - signed right shift accumulator by known count                 */
7423 /*-----------------------------------------------------------------*/
7424 static void AccSRsh (int shCount)
7425 {
7426     symbol *tlbl ;
7427     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7428     if(shCount != 0){
7429         if(shCount == 1){
7430             pic16_emitcode("mov","c,acc.7");
7431             pic16_emitcode("rrc","a");
7432         } else if(shCount == 2){
7433             pic16_emitcode("mov","c,acc.7");
7434             pic16_emitcode("rrc","a");
7435             pic16_emitcode("mov","c,acc.7");
7436             pic16_emitcode("rrc","a");
7437         } else {
7438             tlbl = newiTempLabel(NULL);
7439             /* rotate right accumulator */
7440             AccRol(8 - shCount);
7441             /* and kill the higher order bits */
7442             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7443             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7444             pic16_emitcode("orl","a,#0x%02x",
7445                      (unsigned char)~SRMask[shCount]);
7446             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7447         }
7448     }
7449 }
7450 #endif
7451 /*-----------------------------------------------------------------*/
7452 /* shiftR1Left2Result - shift right one byte from left to result   */
7453 /*-----------------------------------------------------------------*/
7454 static void shiftR1Left2ResultSigned (operand *left, int offl,
7455                                 operand *result, int offr,
7456                                 int shCount)
7457 {
7458   int same;
7459
7460   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7461
7462   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7463
7464   switch(shCount) {
7465   case 1:
7466     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7467     if(same) 
7468       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7469     else {
7470       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7471       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7472     }
7473
7474     break;
7475   case 2:
7476
7477     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7478     if(same) 
7479       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7480     else {
7481       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7482       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7483     }
7484     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7485     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7486
7487     break;
7488
7489   case 3:
7490     if(same)
7491       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7492     else {
7493       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7494       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7495     }
7496
7497     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7498     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7499     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7500
7501     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7502     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7503
7504     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7505     break;
7506
7507   case 4:
7508     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7509     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7510     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7511     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7512     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7513     break;
7514   case 5:
7515     if(same) {
7516       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7517     } else {
7518       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7519       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7520     }
7521     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7522     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7523     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7524     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7525     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7526     break;
7527
7528   case 6:
7529     if(same) {
7530       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7531       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7532       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7533       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7534       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7535       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7536     } else {
7537       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7538       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7539       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7540       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7541       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7542     }
7543     break;
7544
7545   case 7:
7546     if(same) {
7547       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7548       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7549       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7550       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7551     } else {
7552       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7553       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7554       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7555     }
7556
7557   default:
7558     break;
7559   }
7560 }
7561
7562 /*-----------------------------------------------------------------*/
7563 /* shiftR1Left2Result - shift right one byte from left to result   */
7564 /*-----------------------------------------------------------------*/
7565 static void shiftR1Left2Result (operand *left, int offl,
7566                                 operand *result, int offr,
7567                                 int shCount, int sign)
7568 {
7569   int same;
7570
7571   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7572
7573   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7574
7575   /* Copy the msb into the carry if signed. */
7576   if(sign) {
7577     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7578     return;
7579   }
7580
7581
7582
7583   switch(shCount) {
7584   case 1:
7585     emitCLRC;
7586     if(same) 
7587       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7588     else {
7589       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7590       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7591     }
7592     break;
7593   case 2:
7594     emitCLRC;
7595     if(same) {
7596       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7597     } else {
7598       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7599       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7600     }
7601     emitCLRC;
7602     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7603
7604     break;
7605   case 3:
7606     if(same)
7607       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7608     else {
7609       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7610       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7611     }
7612
7613     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7614     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7615     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7616     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7617     break;
7618       
7619   case 4:
7620     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7621     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7622     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7623     break;
7624
7625   case 5:
7626     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7627     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7628     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7629     emitCLRC;
7630     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7631
7632     break;
7633   case 6:
7634
7635     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7636     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7637     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7638     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7639     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7640     break;
7641
7642   case 7:
7643
7644     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7645     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7646     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7647
7648     break;
7649
7650   default:
7651     break;
7652   }
7653 }
7654
7655 /*-----------------------------------------------------------------*/
7656 /* shiftL1Left2Result - shift left one byte from left to result    */
7657 /*-----------------------------------------------------------------*/
7658 static void shiftL1Left2Result (operand *left, int offl,
7659                                 operand *result, int offr, int shCount)
7660 {
7661   int same;
7662
7663   //    char *l;
7664   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7665
7666   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7667   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7668     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7669     //    MOVA(l);
7670     /* shift left accumulator */
7671     //AccLsh(shCount); // don't comment out just yet...
7672   //    pic16_aopPut(AOP(result),"a",offr);
7673
7674   switch(shCount) {
7675   case 1:
7676     /* Shift left 1 bit position */
7677     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7678     if(same) {
7679       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7680     } else {
7681       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7682       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7683     }
7684     break;
7685   case 2:
7686     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7687     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7688     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7689     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7690     break;
7691   case 3:
7692     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7693     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7694     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7695     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7696     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7697     break;
7698   case 4:
7699     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7700     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7701     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7702     break;
7703   case 5:
7704     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7705     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7706     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7707     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7708     break;
7709   case 6:
7710     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7711     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7712     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7713     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7714     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7715     break;
7716   case 7:
7717     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7718     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7719     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7720     break;
7721
7722   default:
7723     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7724   }
7725
7726 }
7727
7728 /*-----------------------------------------------------------------*/
7729 /* movLeft2Result - move byte from left to result                  */
7730 /*-----------------------------------------------------------------*/
7731 static void movLeft2Result (operand *left, int offl,
7732                             operand *result, int offr)
7733 {
7734   char *l;
7735   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7736   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7737     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7738
7739     if (*l == '@' && (IS_AOP_PREG(result))) {
7740       pic16_emitcode("mov","a,%s",l);
7741       pic16_aopPut(AOP(result),"a",offr);
7742     } else {
7743       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7744       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7745     }
7746   }
7747 }
7748
7749 /*-----------------------------------------------------------------*/
7750 /* shiftL2Left2Result - shift left two bytes from left to result   */
7751 /*-----------------------------------------------------------------*/
7752 static void shiftL2Left2Result (operand *left, int offl,
7753                                 operand *result, int offr, int shCount)
7754 {
7755   int same = pic16_sameRegs(AOP(result), AOP(left));
7756   int i;
7757
7758   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7759
7760   if (same && (offl != offr)) { // shift bytes
7761     if (offr > offl) {
7762        for(i=1;i>-1;i--) {
7763          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7764          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7765        }
7766     } else { // just treat as different later on
7767                 same = 0;
7768     }
7769   }
7770
7771   if(same) {
7772     switch(shCount) {
7773     case 0:
7774       break;
7775     case 1:
7776     case 2:
7777     case 3:
7778
7779       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7780       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7781       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7782
7783       while(--shCount) {
7784                 emitCLRC;
7785                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7786                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7787       }
7788
7789       break;
7790     case 4:
7791     case 5:
7792       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7793       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7794       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7795       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7796       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7797       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7798       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7799       if(shCount >=5) {
7800                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7801                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7802       }
7803       break;
7804     case 6:
7805       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7806       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7807       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7808       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7809       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7810       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7811       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7812       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7813       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7814       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7815       break;
7816     case 7:
7817       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7818       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7819       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7820       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7821       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7822     }
7823
7824   } else {
7825     switch(shCount) {
7826     case 0:
7827       break;
7828     case 1:
7829     case 2:
7830     case 3:
7831       /* note, use a mov/add for the shift since the mov has a
7832          chance of getting optimized out */
7833       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7834       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7835       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7836       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7837       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7838
7839       while(--shCount) {
7840                 emitCLRC;
7841                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7842                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7843       }
7844       break;
7845
7846     case 4:
7847     case 5:
7848       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7849       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7850       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7851       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7852       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7853       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7854       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7855       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7856
7857
7858       if(shCount == 5) {
7859                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7860                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7861       }
7862       break;
7863     case 6:
7864       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7865       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7866       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7867       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7868
7869       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7870       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7871       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7872       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7873       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7874       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7875       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7876       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7877       break;
7878     case 7:
7879       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7880       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7881       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7882       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7883       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7884     }
7885   }
7886
7887 }
7888 /*-----------------------------------------------------------------*/
7889 /* shiftR2Left2Result - shift right two bytes from left to result  */
7890 /*-----------------------------------------------------------------*/
7891 static void shiftR2Left2Result (operand *left, int offl,
7892                                 operand *result, int offr,
7893                                 int shCount, int sign)
7894 {
7895   int same = pic16_sameRegs(AOP(result), AOP(left));
7896   int i;
7897   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7898
7899   if (same && (offl != offr)) { // shift right bytes
7900     if (offr < offl) {
7901        for(i=0;i<2;i++) {
7902          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7903          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7904        }
7905     } else { // just treat as different later on
7906                 same = 0;
7907     }
7908   }
7909
7910   switch(shCount) {
7911   case 0:
7912     break;
7913   case 1:
7914   case 2:
7915   case 3:
7916     if(sign)
7917       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7918     else
7919       emitCLRC;
7920
7921     if(same) {
7922       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7923       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7924     } else {
7925       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7926       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7927       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7928       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7929     }
7930
7931     while(--shCount) {
7932       if(sign)
7933                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7934       else
7935                 emitCLRC;
7936       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7937       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7938     }
7939     break;
7940   case 4:
7941   case 5:
7942     if(same) {
7943
7944       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7945       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7946       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7947
7948       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7949       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7950       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7951       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7952     } else {
7953       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7954       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7955       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7956
7957       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7958       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7959       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7960       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7961       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7962     }
7963
7964     if(shCount >=5) {
7965       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7966       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7967     }
7968
7969     if(sign) {
7970       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7971       pic16_emitpcode(POC_BTFSC, 
7972                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7973       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7974     }
7975
7976     break;
7977
7978   case 6:
7979     if(same) {
7980
7981       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7982       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7983
7984       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7985       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7986       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7987       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7988       if(sign) {
7989         pic16_emitpcode(POC_BTFSC, 
7990                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7991         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7992       }
7993       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7994       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7995       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7996       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7997     } else {
7998       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7999       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8000       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8001       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8002       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8003       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8004       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8005       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8006       if(sign) {
8007         pic16_emitpcode(POC_BTFSC, 
8008                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8009         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8010       }
8011       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8012       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8013
8014         
8015     }
8016
8017     break;
8018   case 7:
8019     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8020     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8021     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8022     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8023     if(sign) {
8024       emitSKPNC;
8025       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8026     } else 
8027       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8028   }
8029 }
8030
8031
8032 /*-----------------------------------------------------------------*/
8033 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8034 /*-----------------------------------------------------------------*/
8035 static void shiftLLeftOrResult (operand *left, int offl,
8036                                 operand *result, int offr, int shCount)
8037 {
8038     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8039
8040     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8041     /* shift left accumulator */
8042     AccLsh(shCount);
8043     /* or with result */
8044     /* back to result */
8045     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8046 }
8047
8048 /*-----------------------------------------------------------------*/
8049 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8050 /*-----------------------------------------------------------------*/
8051 static void shiftRLeftOrResult (operand *left, int offl,
8052                                 operand *result, int offr, int shCount)
8053 {
8054     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8055     
8056     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8057     /* shift right accumulator */
8058     AccRsh(shCount, 1);
8059     /* or with result */
8060     /* back to result */
8061     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8062 }
8063
8064 /*-----------------------------------------------------------------*/
8065 /* genlshOne - left shift a one byte quantity by known count       */
8066 /*-----------------------------------------------------------------*/
8067 static void genlshOne (operand *result, operand *left, int shCount)
8068 {       
8069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8070     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8071 }
8072
8073 /*-----------------------------------------------------------------*/
8074 /* genlshTwo - left shift two bytes by known amount != 0           */
8075 /*-----------------------------------------------------------------*/
8076 static void genlshTwo (operand *result,operand *left, int shCount)
8077 {
8078     int size;
8079     
8080     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8081     size = pic16_getDataSize(result);
8082
8083     /* if shCount >= 8 */
8084     if (shCount >= 8) {
8085         shCount -= 8 ;
8086
8087         if (size > 1){
8088             if (shCount)
8089                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8090             else 
8091                 movLeft2Result(left, LSB, result, MSB16);
8092         }
8093         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8094     }
8095
8096     /*  1 <= shCount <= 7 */
8097     else {  
8098         if(size == 1)
8099             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8100         else 
8101             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8102     }
8103 }
8104
8105 /*-----------------------------------------------------------------*/
8106 /* shiftLLong - shift left one long from left to result            */
8107 /* offr = LSB or MSB16                                             */
8108 /*-----------------------------------------------------------------*/
8109 static void shiftLLong (operand *left, operand *result, int offr )
8110 {
8111     int size = AOP_SIZE(result);
8112     int same = pic16_sameRegs(AOP(left),AOP(result));
8113         int i;
8114
8115     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8116
8117         if (same && (offr == MSB16)) { //shift one byte
8118                 for(i=size-1;i>=MSB16;i--) {
8119                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8120                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8121                 }
8122         } else {
8123                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8124         }
8125         
8126     if (size >= LSB+offr ){
8127                 if (same) {
8128                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8129                 } else {
8130                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8131                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8132                 }
8133          }
8134
8135     if(size >= MSB16+offr){
8136                 if (same) {
8137                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8138                 } else {
8139                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8140                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8141                 }
8142     }
8143
8144     if(size >= MSB24+offr){
8145                 if (same) {
8146                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8147                 } else {
8148                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8149                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8150                 }
8151     }
8152
8153     if(size > MSB32+offr){
8154                 if (same) {
8155                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8156                 } else {
8157                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8158                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8159                 }
8160     }
8161     if(offr != LSB)
8162                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8163
8164 }
8165
8166 /*-----------------------------------------------------------------*/
8167 /* genlshFour - shift four byte by a known amount != 0             */
8168 /*-----------------------------------------------------------------*/
8169 static void genlshFour (operand *result, operand *left, int shCount)
8170 {
8171     int size;
8172
8173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8174     size = AOP_SIZE(result);
8175
8176     /* if shifting more that 3 bytes */
8177     if (shCount >= 24 ) {
8178         shCount -= 24;
8179         if (shCount)
8180             /* lowest order of left goes to the highest
8181             order of the destination */
8182             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8183         else
8184             movLeft2Result(left, LSB, result, MSB32);
8185
8186                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8187                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8188                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8189
8190         return;
8191     }
8192
8193     /* more than two bytes */
8194     else if ( shCount >= 16 ) {
8195         /* lower order two bytes goes to higher order two bytes */
8196         shCount -= 16;
8197         /* if some more remaining */
8198         if (shCount)
8199             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8200         else {
8201             movLeft2Result(left, MSB16, result, MSB32);
8202             movLeft2Result(left, LSB, result, MSB24);
8203         }
8204                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8205                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8206         return;
8207     }    
8208
8209     /* if more than 1 byte */
8210     else if ( shCount >= 8 ) {
8211         /* lower order three bytes goes to higher order  three bytes */
8212         shCount -= 8;
8213         if(size == 2){
8214             if(shCount)
8215                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8216             else
8217                 movLeft2Result(left, LSB, result, MSB16);
8218         }
8219         else{   /* size = 4 */
8220             if(shCount == 0){
8221                 movLeft2Result(left, MSB24, result, MSB32);
8222                 movLeft2Result(left, MSB16, result, MSB24);
8223                 movLeft2Result(left, LSB, result, MSB16);
8224                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8225             }
8226             else if(shCount == 1)
8227                 shiftLLong(left, result, MSB16);
8228             else{
8229                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8230                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8231                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8232                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8233             }
8234         }
8235     }
8236
8237     /* 1 <= shCount <= 7 */
8238     else if(shCount <= 3)
8239     { 
8240         shiftLLong(left, result, LSB);
8241         while(--shCount >= 1)
8242             shiftLLong(result, result, LSB);
8243     }
8244     /* 3 <= shCount <= 7, optimize */
8245     else{
8246         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8247         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8248         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8249     }
8250 }
8251
8252 /*-----------------------------------------------------------------*/
8253 /* genLeftShiftLiteral - left shifting by known count              */
8254 /*-----------------------------------------------------------------*/
8255 static void genLeftShiftLiteral (operand *left,
8256                                  operand *right,
8257                                  operand *result,
8258                                  iCode *ic)
8259 {    
8260     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8261     int size;
8262
8263     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8264     pic16_freeAsmop(right,NULL,ic,TRUE);
8265
8266     pic16_aopOp(left,ic,FALSE);
8267     pic16_aopOp(result,ic,FALSE);
8268
8269     size = getSize(operandType(result));
8270
8271 #if VIEW_SIZE
8272     pic16_emitcode("; shift left ","result %d, left %d",size,
8273              AOP_SIZE(left));
8274 #endif
8275
8276     /* I suppose that the left size >= result size */
8277     if(shCount == 0){
8278         while(size--){
8279             movLeft2Result(left, size, result, size);
8280         }
8281     }
8282
8283     else if(shCount >= (size * 8))
8284         while(size--)
8285             pic16_aopPut(AOP(result),zero,size);
8286     else{
8287         switch (size) {
8288             case 1:
8289                 genlshOne (result,left,shCount);
8290                 break;
8291
8292             case 2:
8293             case 3:
8294                 genlshTwo (result,left,shCount);
8295                 break;
8296
8297             case 4:
8298                 genlshFour (result,left,shCount);
8299                 break;
8300         }
8301     }
8302     pic16_freeAsmop(left,NULL,ic,TRUE);
8303     pic16_freeAsmop(result,NULL,ic,TRUE);
8304 }
8305
8306 /*-----------------------------------------------------------------*
8307  * genMultiAsm - repeat assembly instruction for size of register.
8308  * if endian == 1, then the high byte (i.e base address + size of 
8309  * register) is used first else the low byte is used first;
8310  *-----------------------------------------------------------------*/
8311 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8312 {
8313
8314   int offset = 0;
8315
8316   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8317
8318   if(!reg)
8319     return;
8320
8321   if(!endian) {
8322     endian = 1;
8323   } else {
8324     endian = -1;
8325     offset = size-1;
8326   }
8327
8328   while(size--) {
8329     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8330     offset += endian;
8331   }
8332
8333 }
8334 /*-----------------------------------------------------------------*/
8335 /* genLeftShift - generates code for left shifting                 */
8336 /*-----------------------------------------------------------------*/
8337 static void genLeftShift (iCode *ic)
8338 {
8339   operand *left,*right, *result;
8340   int size, offset;
8341   char *l;
8342   symbol *tlbl , *tlbl1;
8343   pCodeOp *pctemp;
8344
8345   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8346
8347   right = IC_RIGHT(ic);
8348   left  = IC_LEFT(ic);
8349   result = IC_RESULT(ic);
8350
8351   pic16_aopOp(right,ic,FALSE);
8352
8353   /* if the shift count is known then do it 
8354      as efficiently as possible */
8355   if (AOP_TYPE(right) == AOP_LIT) {
8356     genLeftShiftLiteral (left,right,result,ic);
8357     return ;
8358   }
8359
8360   /* shift count is unknown then we have to form 
8361      a loop get the loop count in B : Note: we take
8362      only the lower order byte since shifting
8363      more that 32 bits make no sense anyway, ( the
8364      largest size of an object can be only 32 bits ) */  
8365
8366     
8367   pic16_aopOp(left,ic,FALSE);
8368   pic16_aopOp(result,ic,FALSE);
8369
8370   /* now move the left to the result if they are not the
8371      same */
8372   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8373       AOP_SIZE(result) > 1) {
8374
8375     size = AOP_SIZE(result);
8376     offset=0;
8377     while (size--) {
8378       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8379       if (*l == '@' && (IS_AOP_PREG(result))) {
8380
8381         pic16_emitcode("mov","a,%s",l);
8382         pic16_aopPut(AOP(result),"a",offset);
8383       } else {
8384         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8385         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8386         //pic16_aopPut(AOP(result),l,offset);
8387       }
8388       offset++;
8389     }
8390   }
8391
8392   size = AOP_SIZE(result);
8393
8394   /* if it is only one byte then */
8395   if (size == 1) {
8396     if(optimized_for_speed) {
8397       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8398       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8399       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8400       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8401       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8402       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8403       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8404       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8405       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8406       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8407       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8408       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8409     } else {
8410
8411       tlbl = newiTempLabel(NULL);
8412       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8413                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8414                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8415       }
8416
8417       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8418       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8419       pic16_emitpLabel(tlbl->key);
8420       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8421       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8422       emitSKPC;
8423       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8424     }
8425     goto release ;
8426   }
8427     
8428   if (pic16_sameRegs(AOP(left),AOP(result))) {
8429
8430     tlbl = newiTempLabel(NULL);
8431     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8432     genMultiAsm(POC_RRCF, result, size,1);
8433     pic16_emitpLabel(tlbl->key);
8434     genMultiAsm(POC_RLCF, result, size,0);
8435     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8436     emitSKPC;
8437     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8438     goto release;
8439   }
8440
8441   //tlbl = newiTempLabel(NULL);
8442   //offset = 0 ;   
8443   //tlbl1 = newiTempLabel(NULL);
8444
8445   //reAdjustPreg(AOP(result));    
8446     
8447   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8448   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8449   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8450   //MOVA(l);
8451   //pic16_emitcode("add","a,acc");         
8452   //pic16_aopPut(AOP(result),"a",offset++);
8453   //while (--size) {
8454   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8455   //  MOVA(l);
8456   //  pic16_emitcode("rlc","a");         
8457   //  pic16_aopPut(AOP(result),"a",offset++);
8458   //}
8459   //reAdjustPreg(AOP(result));
8460
8461   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8462   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8463
8464
8465   tlbl = newiTempLabel(NULL);
8466   tlbl1= newiTempLabel(NULL);
8467
8468   size = AOP_SIZE(result);
8469   offset = 1;
8470
8471   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8472
8473   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8474
8475   /* offset should be 0, 1 or 3 */
8476   
8477   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8478   emitSKPNZ;
8479   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8480
8481   pic16_emitpcode(POC_MOVWF, pctemp);
8482
8483
8484   pic16_emitpLabel(tlbl->key);
8485
8486   emitCLRC;
8487   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8488   while(--size)
8489     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8490
8491   pic16_emitpcode(POC_DECFSZ,  pctemp);
8492   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8493   pic16_emitpLabel(tlbl1->key);
8494
8495   pic16_popReleaseTempReg(pctemp);
8496
8497
8498  release:
8499   pic16_freeAsmop (right,NULL,ic,TRUE);
8500   pic16_freeAsmop(left,NULL,ic,TRUE);
8501   pic16_freeAsmop(result,NULL,ic,TRUE);
8502 }
8503
8504 /*-----------------------------------------------------------------*/
8505 /* genrshOne - right shift a one byte quantity by known count      */
8506 /*-----------------------------------------------------------------*/
8507 static void genrshOne (operand *result, operand *left,
8508                        int shCount, int sign)
8509 {
8510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8511     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8512 }
8513
8514 /*-----------------------------------------------------------------*/
8515 /* genrshTwo - right shift two bytes by known amount != 0          */
8516 /*-----------------------------------------------------------------*/
8517 static void genrshTwo (operand *result,operand *left,
8518                        int shCount, int sign)
8519 {
8520   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8521   /* if shCount >= 8 */
8522   if (shCount >= 8) {
8523     shCount -= 8 ;
8524     if (shCount)
8525       shiftR1Left2Result(left, MSB16, result, LSB,
8526                          shCount, sign);
8527     else
8528       movLeft2Result(left, MSB16, result, LSB);
8529
8530     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8531
8532     if(sign) {
8533       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8534       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8535     }
8536   }
8537
8538   /*  1 <= shCount <= 7 */
8539   else
8540     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8541 }
8542
8543 /*-----------------------------------------------------------------*/
8544 /* shiftRLong - shift right one long from left to result           */
8545 /* offl = LSB or MSB16                                             */
8546 /*-----------------------------------------------------------------*/
8547 static void shiftRLong (operand *left, int offl,
8548                         operand *result, int sign)
8549 {
8550     int size = AOP_SIZE(result);
8551     int same = pic16_sameRegs(AOP(left),AOP(result));
8552     int i;
8553     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8554
8555         if (same && (offl == MSB16)) { //shift one byte right
8556                 for(i=MSB16;i<size;i++) {
8557                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8558                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8559                 }
8560         }
8561
8562     if(sign)
8563                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8564         else
8565                 emitCLRC;
8566
8567         if (same) {
8568                 if (offl == LSB)
8569                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8570         } else {
8571         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8572         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8573         }
8574
8575     if(offl == MSB16) {
8576         /* add sign of "a" */
8577         pic16_addSign(result, MSB32, sign);
8578         }
8579
8580         if (same) {
8581         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8582         } else {
8583         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8584         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8585         }
8586         
8587         if (same) {
8588         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8589         } else {
8590         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8591         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8592         }
8593
8594         if (same) {
8595         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8596         } else {
8597         if(offl == LSB){
8598                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8599                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8600         }
8601         }
8602 }
8603
8604 /*-----------------------------------------------------------------*/
8605 /* genrshFour - shift four byte by a known amount != 0             */
8606 /*-----------------------------------------------------------------*/
8607 static void genrshFour (operand *result, operand *left,
8608                         int shCount, int sign)
8609 {
8610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8611   /* if shifting more that 3 bytes */
8612   if(shCount >= 24 ) {
8613     shCount -= 24;
8614     if(shCount)
8615       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8616     else
8617       movLeft2Result(left, MSB32, result, LSB);
8618
8619     pic16_addSign(result, MSB16, sign);
8620   }
8621   else if(shCount >= 16){
8622     shCount -= 16;
8623     if(shCount)
8624       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8625     else{
8626       movLeft2Result(left, MSB24, result, LSB);
8627       movLeft2Result(left, MSB32, result, MSB16);
8628     }
8629     pic16_addSign(result, MSB24, sign);
8630   }
8631   else if(shCount >= 8){
8632     shCount -= 8;
8633     if(shCount == 1)
8634       shiftRLong(left, MSB16, result, sign);
8635     else if(shCount == 0){
8636       movLeft2Result(left, MSB16, result, LSB);
8637       movLeft2Result(left, MSB24, result, MSB16);
8638       movLeft2Result(left, MSB32, result, MSB24);
8639       pic16_addSign(result, MSB32, sign);
8640     }
8641     else{ //shcount >= 2
8642       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8643       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8644       /* the last shift is signed */
8645       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8646       pic16_addSign(result, MSB32, sign);
8647     }
8648   }
8649   else{   /* 1 <= shCount <= 7 */
8650     if(shCount <= 2){
8651       shiftRLong(left, LSB, result, sign);
8652       if(shCount == 2)
8653         shiftRLong(result, LSB, result, sign);
8654     }
8655     else{
8656       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8657       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8658       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8659     }
8660   }
8661 }
8662
8663 /*-----------------------------------------------------------------*/
8664 /* genRightShiftLiteral - right shifting by known count            */
8665 /*-----------------------------------------------------------------*/
8666 static void genRightShiftLiteral (operand *left,
8667                                   operand *right,
8668                                   operand *result,
8669                                   iCode *ic,
8670                                   int sign)
8671 {    
8672   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8673   int lsize,res_size;
8674
8675   pic16_freeAsmop(right,NULL,ic,TRUE);
8676
8677   pic16_aopOp(left,ic,FALSE);
8678   pic16_aopOp(result,ic,FALSE);
8679
8680   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8681
8682 #if VIEW_SIZE
8683   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8684                  AOP_SIZE(left));
8685 #endif
8686
8687   lsize = pic16_getDataSize(left);
8688   res_size = pic16_getDataSize(result);
8689   /* test the LEFT size !!! */
8690
8691   /* I suppose that the left size >= result size */
8692   if(shCount == 0){
8693     while(res_size--)
8694       movLeft2Result(left, lsize, result, res_size);
8695   }
8696
8697   else if(shCount >= (lsize * 8)){
8698
8699     if(res_size == 1) {
8700       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8701       if(sign) {
8702         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8703         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8704       }
8705     } else {
8706
8707       if(sign) {
8708         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8709         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8710         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711         while(res_size--)
8712           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8713
8714       } else {
8715
8716         while(res_size--)
8717           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8718       }
8719     }
8720   } else {
8721
8722     switch (res_size) {
8723     case 1:
8724       genrshOne (result,left,shCount,sign);
8725       break;
8726
8727     case 2:
8728       genrshTwo (result,left,shCount,sign);
8729       break;
8730
8731     case 4:
8732       genrshFour (result,left,shCount,sign);
8733       break;
8734     default :
8735       break;
8736     }
8737
8738   }
8739
8740   pic16_freeAsmop(left,NULL,ic,TRUE);
8741   pic16_freeAsmop(result,NULL,ic,TRUE);
8742 }
8743
8744 /*-----------------------------------------------------------------*/
8745 /* genSignedRightShift - right shift of signed number              */
8746 /*-----------------------------------------------------------------*/
8747 static void genSignedRightShift (iCode *ic)
8748 {
8749   operand *right, *left, *result;
8750   int size, offset;
8751   //  char *l;
8752   symbol *tlbl, *tlbl1 ;
8753   pCodeOp *pctemp;
8754
8755   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8756
8757   /* we do it the hard way put the shift count in b
8758      and loop thru preserving the sign */
8759   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8760
8761   right = IC_RIGHT(ic);
8762   left  = IC_LEFT(ic);
8763   result = IC_RESULT(ic);
8764
8765   pic16_aopOp(right,ic,FALSE);  
8766   pic16_aopOp(left,ic,FALSE);
8767   pic16_aopOp(result,ic,FALSE);
8768
8769
8770   if ( AOP_TYPE(right) == AOP_LIT) {
8771     genRightShiftLiteral (left,right,result,ic,1);
8772     return ;
8773   }
8774   /* shift count is unknown then we have to form 
8775      a loop get the loop count in B : Note: we take
8776      only the lower order byte since shifting
8777      more that 32 bits make no sense anyway, ( the
8778      largest size of an object can be only 32 bits ) */  
8779
8780   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8781   //pic16_emitcode("inc","b");
8782   //pic16_freeAsmop (right,NULL,ic,TRUE);
8783   //pic16_aopOp(left,ic,FALSE);
8784   //pic16_aopOp(result,ic,FALSE);
8785
8786   /* now move the left to the result if they are not the
8787      same */
8788   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8789       AOP_SIZE(result) > 1) {
8790
8791     size = AOP_SIZE(result);
8792     offset=0;
8793     while (size--) { 
8794       /*
8795         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8796         if (*l == '@' && IS_AOP_PREG(result)) {
8797
8798         pic16_emitcode("mov","a,%s",l);
8799         pic16_aopPut(AOP(result),"a",offset);
8800         } else
8801         pic16_aopPut(AOP(result),l,offset);
8802       */
8803       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8804       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8805
8806       offset++;
8807     }
8808   }
8809
8810   /* mov the highest order bit to OVR */    
8811   tlbl = newiTempLabel(NULL);
8812   tlbl1= newiTempLabel(NULL);
8813
8814   size = AOP_SIZE(result);
8815   offset = size - 1;
8816
8817   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8818
8819   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8820
8821   /* offset should be 0, 1 or 3 */
8822   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8823   emitSKPNZ;
8824   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8825
8826   pic16_emitpcode(POC_MOVWF, pctemp);
8827
8828
8829   pic16_emitpLabel(tlbl->key);
8830
8831   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8832   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8833
8834   while(--size) {
8835     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8836   }
8837
8838   pic16_emitpcode(POC_DECFSZ,  pctemp);
8839   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8840   pic16_emitpLabel(tlbl1->key);
8841
8842   pic16_popReleaseTempReg(pctemp);
8843 #if 0
8844   size = AOP_SIZE(result);
8845   offset = size - 1;
8846   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8847   pic16_emitcode("rlc","a");
8848   pic16_emitcode("mov","ov,c");
8849   /* if it is only one byte then */
8850   if (size == 1) {
8851     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8852     MOVA(l);
8853     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8854     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8855     pic16_emitcode("mov","c,ov");
8856     pic16_emitcode("rrc","a");
8857     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8858     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8859     pic16_aopPut(AOP(result),"a",0);
8860     goto release ;
8861   }
8862
8863   reAdjustPreg(AOP(result));
8864   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8865   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8866   pic16_emitcode("mov","c,ov");
8867   while (size--) {
8868     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8869     MOVA(l);
8870     pic16_emitcode("rrc","a");         
8871     pic16_aopPut(AOP(result),"a",offset--);
8872   }
8873   reAdjustPreg(AOP(result));
8874   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8875   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8876
8877  release:
8878 #endif
8879
8880   pic16_freeAsmop(left,NULL,ic,TRUE);
8881   pic16_freeAsmop(result,NULL,ic,TRUE);
8882   pic16_freeAsmop(right,NULL,ic,TRUE);
8883 }
8884
8885 /*-----------------------------------------------------------------*/
8886 /* genRightShift - generate code for right shifting                */
8887 /*-----------------------------------------------------------------*/
8888 static void genRightShift (iCode *ic)
8889 {
8890     operand *right, *left, *result;
8891     sym_link *letype ;
8892     int size, offset;
8893     char *l;
8894     symbol *tlbl, *tlbl1 ;
8895
8896     /* if signed then we do it the hard way preserve the
8897     sign bit moving it inwards */
8898     letype = getSpec(operandType(IC_LEFT(ic)));
8899     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8900
8901     if (!SPEC_USIGN(letype)) {
8902         genSignedRightShift (ic);
8903         return ;
8904     }
8905
8906     /* signed & unsigned types are treated the same : i.e. the
8907     signed is NOT propagated inwards : quoting from the
8908     ANSI - standard : "for E1 >> E2, is equivalent to division
8909     by 2**E2 if unsigned or if it has a non-negative value,
8910     otherwise the result is implementation defined ", MY definition
8911     is that the sign does not get propagated */
8912
8913     right = IC_RIGHT(ic);
8914     left  = IC_LEFT(ic);
8915     result = IC_RESULT(ic);
8916
8917     pic16_aopOp(right,ic,FALSE);
8918
8919     /* if the shift count is known then do it 
8920     as efficiently as possible */
8921     if (AOP_TYPE(right) == AOP_LIT) {
8922         genRightShiftLiteral (left,right,result,ic, 0);
8923         return ;
8924     }
8925
8926     /* shift count is unknown then we have to form 
8927     a loop get the loop count in B : Note: we take
8928     only the lower order byte since shifting
8929     more that 32 bits make no sense anyway, ( the
8930     largest size of an object can be only 32 bits ) */  
8931
8932     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8933     pic16_emitcode("inc","b");
8934     pic16_aopOp(left,ic,FALSE);
8935     pic16_aopOp(result,ic,FALSE);
8936
8937     /* now move the left to the result if they are not the
8938     same */
8939     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8940         AOP_SIZE(result) > 1) {
8941
8942         size = AOP_SIZE(result);
8943         offset=0;
8944         while (size--) {
8945             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8946             if (*l == '@' && IS_AOP_PREG(result)) {
8947
8948                 pic16_emitcode("mov","a,%s",l);
8949                 pic16_aopPut(AOP(result),"a",offset);
8950             } else
8951                 pic16_aopPut(AOP(result),l,offset);
8952             offset++;
8953         }
8954     }
8955
8956     tlbl = newiTempLabel(NULL);
8957     tlbl1= newiTempLabel(NULL);
8958     size = AOP_SIZE(result);
8959     offset = size - 1;
8960
8961     /* if it is only one byte then */
8962     if (size == 1) {
8963
8964       tlbl = newiTempLabel(NULL);
8965       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8966         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8967         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8968       }
8969
8970       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8971       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8972       pic16_emitpLabel(tlbl->key);
8973       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8974       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8975       emitSKPC;
8976       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8977
8978       goto release ;
8979     }
8980
8981     reAdjustPreg(AOP(result));
8982     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8983     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8984     CLRC;
8985     while (size--) {
8986         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8987         MOVA(l);
8988         pic16_emitcode("rrc","a");         
8989         pic16_aopPut(AOP(result),"a",offset--);
8990     }
8991     reAdjustPreg(AOP(result));
8992
8993     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8994     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8995
8996 release:
8997     pic16_freeAsmop(left,NULL,ic,TRUE);
8998     pic16_freeAsmop (right,NULL,ic,TRUE);
8999     pic16_freeAsmop(result,NULL,ic,TRUE);
9000 }
9001
9002 /*-----------------------------------------------------------------*/
9003 /* genUnpackBits - generates code for unpacking bits               */
9004 /*-----------------------------------------------------------------*/
9005 static void genUnpackBits (operand *result, char *rname, int ptype)
9006 {    
9007     int shCnt ;
9008     int rlen = 0 ;
9009     sym_link *etype;
9010     int offset = 0 ;
9011
9012         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9013         etype = getSpec(operandType(result));
9014
9015         /* read the first byte  */
9016         switch (ptype) {
9017                 case POINTER:
9018                 case IPOINTER:
9019                 case PPOINTER:
9020                 case FPOINTER:
9021                 case GPOINTER:
9022                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9023                         break;
9024                 case CPOINTER:
9025                         pic16_emitcode("clr","a");
9026                         pic16_emitcode("movc","a","@a+dptr");
9027                         break;
9028         }
9029         
9030
9031         /* if we have bitdisplacement then it fits   */
9032         /* into this byte completely or if length is */
9033         /* less than a byte                          */
9034         if ((shCnt = SPEC_BSTR(etype)) || 
9035                 (SPEC_BLEN(etype) <= 8))  {
9036
9037                 /* shift right acc */
9038                 AccRsh(shCnt, 0);
9039
9040                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9041                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9042
9043 /* VR -- normally I would use the following, but since we use the hack,
9044  * to avoid the masking from AccRsh, why not mask it right now? */
9045
9046 /*
9047                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9048 */
9049
9050                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9051           return ;
9052         }
9053
9054
9055
9056         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9057         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9058         exit(-1);
9059
9060     /* bit field did not fit in a byte  */
9061     rlen = SPEC_BLEN(etype) - 8;
9062     pic16_aopPut(AOP(result),"a",offset++);
9063
9064     while (1)  {
9065
9066         switch (ptype) {
9067         case POINTER:
9068         case IPOINTER:
9069             pic16_emitcode("inc","%s",rname);
9070             pic16_emitcode("mov","a,@%s",rname);
9071             break;
9072             
9073         case PPOINTER:
9074             pic16_emitcode("inc","%s",rname);
9075             pic16_emitcode("movx","a,@%s",rname);
9076             break;
9077
9078         case FPOINTER:
9079             pic16_emitcode("inc","dptr");
9080             pic16_emitcode("movx","a,@dptr");
9081             break;
9082             
9083         case CPOINTER:
9084             pic16_emitcode("clr","a");
9085             pic16_emitcode("inc","dptr");
9086             pic16_emitcode("movc","a","@a+dptr");
9087             break;
9088             
9089         case GPOINTER:
9090             pic16_emitcode("inc","dptr");
9091             pic16_emitcode("lcall","__gptrget");
9092             break;
9093         }
9094
9095         rlen -= 8;            
9096         /* if we are done */
9097         if ( rlen <= 0 )
9098             break ;
9099         
9100         pic16_aopPut(AOP(result),"a",offset++);
9101                               
9102     }
9103     
9104     if (rlen) {
9105         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9106         pic16_aopPut(AOP(result),"a",offset);          
9107     }
9108     
9109     return ;
9110 }
9111
9112
9113 static void genDataPointerGet(operand *left,
9114                               operand *result,
9115                               iCode *ic)
9116 {
9117   int size, offset = 0, leoffset=0 ;
9118
9119         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9120         pic16_aopOp(result, ic, FALSE);
9121
9122         size = AOP_SIZE(result);
9123 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9124
9125
9126 #if 0
9127         /* The following tests may save a redudant movff instruction when
9128          * accessing unions */
9129          
9130         /* if they are the same */
9131         if (operandsEqu (left, result)) {
9132                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9133                 goto release;
9134         }
9135 #endif
9136
9137 #if 0
9138         /* if they are the same registers */
9139         if (pic16_sameRegs(AOP(left),AOP(result))) {
9140                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9141                 goto release;
9142         }
9143 #endif
9144
9145 #if 1
9146         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9147                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9148                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9149                 goto release;
9150         }
9151 #endif
9152
9153
9154 #if 0
9155         if ( AOP_TYPE(left) == AOP_PCODE) {
9156                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9157                                 AOP(left)->aopu.pcop->name,
9158                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9159                                 PCOR(AOP(left)->aopu.pcop)->instance:
9160                                 PCOI(AOP(left)->aopu.pcop)->offset);
9161         }
9162 #endif
9163
9164         if(AOP(left)->aopu.pcop->type == PO_DIR)
9165                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9166
9167         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9168
9169         while (size--) {
9170                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9171                 
9172                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9173                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9174                         mov2w(AOP(left), offset); // patch 8
9175                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9176                 } else {
9177                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9178                                 pic16_popGet(AOP(left), offset), //patch 8
9179                                 pic16_popGet(AOP(result), offset)));
9180                 }
9181
9182                 offset++;
9183                 leoffset++;
9184         }
9185
9186 release:
9187     pic16_freeAsmop(result,NULL,ic,TRUE);
9188 }
9189
9190 void pic16_loadFSR0(operand *op)
9191 {
9192         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9193 }
9194
9195
9196 /*-----------------------------------------------------------------*/
9197 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9198 /*-----------------------------------------------------------------*/
9199 static void genNearPointerGet (operand *left, 
9200                                operand *result, 
9201                                iCode *ic)
9202 {
9203     asmop *aop = NULL;
9204     //regs *preg = NULL ;
9205     sym_link *rtype, *retype;
9206     sym_link *ltype = operandType(left);    
9207
9208         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9209         rtype = operandType(result);
9210         retype= getSpec(rtype);
9211     
9212         pic16_aopOp(left,ic,FALSE);
9213
9214 //      pic16_DumpOp("(left)",left);
9215 //      pic16_DumpOp("(result)",result);
9216
9217         /* if left is rematerialisable and
9218          * result is not bit variable type and
9219          * the left is pointer to data space i.e
9220          * lower 128 bytes of space */
9221         if (AOP_TYPE(left) == AOP_PCODE
9222                 && !IS_BITFIELD(retype)
9223                 && DCL_TYPE(ltype) == POINTER) {
9224
9225                 genDataPointerGet (left,result,ic);
9226                 pic16_freeAsmop(left, NULL, ic, TRUE);
9227           return ;
9228         }
9229     
9230         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9231
9232         /* if the value is already in a pointer register
9233          * then don't need anything more */
9234         if (!AOP_INPREG(AOP(left))) {
9235                 /* otherwise get a free pointer register */
9236                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9237                 
9238                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9239                 if( (AOP_TYPE(left) == AOP_PCODE) 
9240                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9241                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9242                 {
9243                         pic16_loadFSR0( left );  // patch 10
9244                 } else {
9245                         // set up FSR0 with address from left
9246                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9247                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9248                 }
9249         }
9250 //       else
9251 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9252     
9253         pic16_aopOp (result,ic,FALSE);
9254     
9255       /* if bitfield then unpack the bits */
9256     if (IS_BITFIELD(retype)) 
9257         genUnpackBits (result, NULL, POINTER);
9258     else {
9259         /* we have can just get the values */
9260       int size = AOP_SIZE(result);
9261       int offset = 0;   
9262         
9263       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9264
9265
9266         /* fsr0 is loaded already -- VR */
9267 //      pic16_loadFSR0( left );
9268
9269 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9270 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9271       while(size--) {
9272
9273         if(size) {
9274                 pic16_emitpcode(POC_MOVFF,
9275                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9276                                 pic16_popGet(AOP(result), offset++)));
9277         } else {
9278                 pic16_emitpcode(POC_MOVFF,
9279                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9280                                 pic16_popGet(AOP(result), offset++)));
9281         }
9282       }
9283 #if 0
9284 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9285 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9286         if(size)
9287           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9288 #endif
9289 /*
9290         while (size--) {
9291             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9292
9293                 pic16_emitcode("mov","a,@%s",rname);
9294                 pic16_aopPut(AOP(result),"a",offset);
9295             } else {
9296                 sprintf(buffer,"@%s",rname);
9297                 pic16_aopPut(AOP(result),buffer,offset);
9298             }
9299             offset++ ;
9300             if (size)
9301                 pic16_emitcode("inc","%s",rname);
9302         }
9303 */
9304     }
9305
9306     /* now some housekeeping stuff */
9307     if (aop) {
9308         /* we had to allocate for this iCode */
9309     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9310         pic16_freeAsmop(NULL,aop,ic,TRUE);
9311     } else { 
9312         /* we did not allocate which means left
9313            already in a pointer register, then
9314            if size > 0 && this could be used again
9315            we have to point it back to where it 
9316            belongs */
9317     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9318         if (AOP_SIZE(result) > 1 &&
9319             !OP_SYMBOL(left)->remat &&
9320             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9321               ic->depth )) {
9322 //          int size = AOP_SIZE(result) - 1;
9323 //          while (size--)
9324 //              pic16_emitcode("dec","%s",rname);
9325         }
9326     }
9327
9328     /* done */
9329     pic16_freeAsmop(left,NULL,ic,TRUE);
9330     pic16_freeAsmop(result,NULL,ic,TRUE);
9331      
9332 }
9333
9334 /*-----------------------------------------------------------------*/
9335 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9336 /*-----------------------------------------------------------------*/
9337 static void genPagedPointerGet (operand *left, 
9338                                operand *result, 
9339                                iCode *ic)
9340 {
9341     asmop *aop = NULL;
9342     regs *preg = NULL ;
9343     char *rname ;
9344     sym_link *rtype, *retype;    
9345
9346     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9347
9348     rtype = operandType(result);
9349     retype= getSpec(rtype);
9350     
9351     pic16_aopOp(left,ic,FALSE);
9352
9353   /* if the value is already in a pointer register
9354        then don't need anything more */
9355     if (!AOP_INPREG(AOP(left))) {
9356         /* otherwise get a free pointer register */
9357         aop = newAsmop(0);
9358         preg = getFreePtr(ic,&aop,FALSE);
9359         pic16_emitcode("mov","%s,%s",
9360                 preg->name,
9361                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9362         rname = preg->name ;
9363     } else
9364         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9365     
9366     pic16_freeAsmop(left,NULL,ic,TRUE);
9367     pic16_aopOp (result,ic,FALSE);
9368
9369     /* if bitfield then unpack the bits */
9370     if (IS_BITFIELD(retype)) 
9371         genUnpackBits (result,rname,PPOINTER);
9372     else {
9373         /* we have can just get the values */
9374         int size = AOP_SIZE(result);
9375         int offset = 0 ;        
9376         
9377         while (size--) {
9378             
9379             pic16_emitcode("movx","a,@%s",rname);
9380             pic16_aopPut(AOP(result),"a",offset);
9381             
9382             offset++ ;
9383             
9384             if (size)
9385                 pic16_emitcode("inc","%s",rname);
9386         }
9387     }
9388
9389     /* now some housekeeping stuff */
9390     if (aop) {
9391         /* we had to allocate for this iCode */
9392         pic16_freeAsmop(NULL,aop,ic,TRUE);
9393     } else { 
9394         /* we did not allocate which means left
9395            already in a pointer register, then
9396            if size > 0 && this could be used again
9397            we have to point it back to where it 
9398            belongs */
9399         if (AOP_SIZE(result) > 1 &&
9400             !OP_SYMBOL(left)->remat &&
9401             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9402               ic->depth )) {
9403             int size = AOP_SIZE(result) - 1;
9404             while (size--)
9405                 pic16_emitcode("dec","%s",rname);
9406         }
9407     }
9408
9409     /* done */
9410     pic16_freeAsmop(result,NULL,ic,TRUE);
9411     
9412         
9413 }
9414
9415 /*-----------------------------------------------------------------*/
9416 /* genFarPointerGet - gget value from far space                    */
9417 /*-----------------------------------------------------------------*/
9418 static void genFarPointerGet (operand *left,
9419                               operand *result, iCode *ic)
9420 {
9421     int size, offset ;
9422     sym_link *retype = getSpec(operandType(result));
9423
9424     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9425
9426     pic16_aopOp(left,ic,FALSE);
9427
9428     /* if the operand is already in dptr 
9429     then we do nothing else we move the value to dptr */
9430     if (AOP_TYPE(left) != AOP_STR) {
9431         /* if this is remateriazable */
9432         if (AOP_TYPE(left) == AOP_IMMD)
9433             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9434         else { /* we need to get it byte by byte */
9435             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9436             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9437             if (options.model == MODEL_FLAT24)
9438             {
9439                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9440             }
9441         }
9442     }
9443     /* so dptr know contains the address */
9444     pic16_freeAsmop(left,NULL,ic,TRUE);
9445     pic16_aopOp(result,ic,FALSE);
9446
9447     /* if bit then unpack */
9448     if (IS_BITFIELD(retype)) 
9449         genUnpackBits(result,"dptr",FPOINTER);
9450     else {
9451         size = AOP_SIZE(result);
9452         offset = 0 ;
9453
9454         while (size--) {
9455             pic16_emitcode("movx","a,@dptr");
9456             pic16_aopPut(AOP(result),"a",offset++);
9457             if (size)
9458                 pic16_emitcode("inc","dptr");
9459         }
9460     }
9461
9462     pic16_freeAsmop(result,NULL,ic,TRUE);
9463 }
9464 #if 0
9465 /*-----------------------------------------------------------------*/
9466 /* genCodePointerGet - get value from code space                  */
9467 /*-----------------------------------------------------------------*/
9468 static void genCodePointerGet (operand *left,
9469                                 operand *result, iCode *ic)
9470 {
9471     int size, offset ;
9472     sym_link *retype = getSpec(operandType(result));
9473
9474     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9475
9476     pic16_aopOp(left,ic,FALSE);
9477
9478     /* if the operand is already in dptr 
9479     then we do nothing else we move the value to dptr */
9480     if (AOP_TYPE(left) != AOP_STR) {
9481         /* if this is remateriazable */
9482         if (AOP_TYPE(left) == AOP_IMMD)
9483             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9484         else { /* we need to get it byte by byte */
9485             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9486             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9487             if (options.model == MODEL_FLAT24)
9488             {
9489                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9490             }
9491         }
9492     }
9493     /* so dptr know contains the address */
9494     pic16_freeAsmop(left,NULL,ic,TRUE);
9495     pic16_aopOp(result,ic,FALSE);
9496
9497     /* if bit then unpack */
9498     if (IS_BITFIELD(retype)) 
9499         genUnpackBits(result,"dptr",CPOINTER);
9500     else {
9501         size = AOP_SIZE(result);
9502         offset = 0 ;
9503
9504         while (size--) {
9505             pic16_emitcode("clr","a");
9506             pic16_emitcode("movc","a,@a+dptr");
9507             pic16_aopPut(AOP(result),"a",offset++);
9508             if (size)
9509                 pic16_emitcode("inc","dptr");
9510         }
9511     }
9512
9513     pic16_freeAsmop(result,NULL,ic,TRUE);
9514 }
9515 #endif
9516 /*-----------------------------------------------------------------*/
9517 /* genGenPointerGet - gget value from generic pointer space        */
9518 /*-----------------------------------------------------------------*/
9519 static void genGenPointerGet (operand *left,
9520                               operand *result, iCode *ic)
9521 {
9522   int size, offset, lit;
9523   sym_link *retype = getSpec(operandType(result));
9524
9525         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9526         pic16_aopOp(left,ic,FALSE);
9527         pic16_aopOp(result,ic,FALSE);
9528         size = AOP_SIZE(result);
9529
9530         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9531
9532         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9533
9534                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9535                 // load FSR0 from immediate
9536                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9537
9538 //              pic16_loadFSR0( left );
9539
9540                 offset = 0;
9541                 while(size--) {
9542                         if(size) {
9543                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9544                         } else {
9545                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9546                         }
9547                         offset++;
9548                 }
9549                 goto release;
9550
9551         }
9552         else { /* we need to get it byte by byte */
9553                 // set up FSR0 with address from left
9554                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9555                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9556
9557                 offset = 0 ;
9558
9559                 while(size--) {
9560                         if(size) {
9561                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9562                         } else {
9563                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9564                         }
9565                         offset++;
9566                 }
9567                 goto release;
9568         }
9569
9570   /* if bit then unpack */
9571         if (IS_BITFIELD(retype)) 
9572                 genUnpackBits(result,"BAD",GPOINTER);
9573
9574         release:
9575         pic16_freeAsmop(left,NULL,ic,TRUE);
9576         pic16_freeAsmop(result,NULL,ic,TRUE);
9577
9578 }
9579
9580 /*-----------------------------------------------------------------*/
9581 /* genConstPointerGet - get value from const generic pointer space */
9582 /*-----------------------------------------------------------------*/
9583 static void genConstPointerGet (operand *left,
9584                                 operand *result, iCode *ic)
9585 {
9586   //sym_link *retype = getSpec(operandType(result));
9587   // symbol *albl = newiTempLabel(NULL);        // patch 15
9588   // symbol *blbl = newiTempLabel(NULL);        //
9589   // PIC_OPCODE poc;                            // patch 15
9590   int size;
9591   int offset = 0;
9592
9593   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9594   pic16_aopOp(left,ic,FALSE);
9595   pic16_aopOp(result,ic,TRUE);
9596   size = AOP_SIZE(result);
9597
9598   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9599
9600   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9601 #if 0                                                                   // patch 15
9602   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9603   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9604   pic16_emitpLabel(albl->key);
9605
9606   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9607     
9608   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9609   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9610   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9611   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9612   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9613
9614   pic16_emitpLabel(blbl->key);
9615
9616   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9617 #endif                                                                  // patch 15
9618
9619
9620   // set up table pointer
9621   if( (AOP_TYPE(left) == AOP_PCODE) 
9622       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9623           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9624     {
9625       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9626       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9627       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9628       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9629       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9630       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9631     }
9632   else
9633     {
9634       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9635       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9636       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9637     }
9638
9639
9640   while(size--)
9641     {
9642       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9643       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9644       offset++;
9645     }
9646     
9647   pic16_freeAsmop(left,NULL,ic,TRUE);
9648   pic16_freeAsmop(result,NULL,ic,TRUE);
9649
9650 }
9651
9652
9653 /*-----------------------------------------------------------------*/
9654 /* genPointerGet - generate code for pointer get                   */
9655 /*-----------------------------------------------------------------*/
9656 static void genPointerGet (iCode *ic)
9657 {
9658     operand *left, *result ;
9659     sym_link *type, *etype;
9660     int p_type;
9661
9662     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9663
9664     left = IC_LEFT(ic);
9665     result = IC_RESULT(ic) ;
9666
9667     /* depending on the type of pointer we need to
9668     move it to the correct pointer register */
9669     type = operandType(left);
9670     etype = getSpec(type);
9671
9672 #if 0
9673     if (IS_PTR_CONST(type))
9674 #else
9675     if (IS_CODEPTR(type))
9676 #endif
9677       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9678
9679     /* if left is of type of pointer then it is simple */
9680     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9681         p_type = DCL_TYPE(type);
9682     else {
9683         /* we have to go by the storage class */
9684         p_type = PTR_TYPE(SPEC_OCLS(etype));
9685
9686         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9687
9688         if (SPEC_OCLS(etype)->codesp ) {
9689           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9690           //p_type = CPOINTER ; 
9691         }
9692         else
9693             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9694               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9695                /*p_type = FPOINTER ;*/ 
9696             else
9697                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9698                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9699 /*                  p_type = PPOINTER; */
9700                 else
9701                     if (SPEC_OCLS(etype) == idata )
9702                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9703 /*                      p_type = IPOINTER; */
9704                     else
9705                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9706 /*                      p_type = POINTER ; */
9707     }
9708
9709     /* now that we have the pointer type we assign
9710     the pointer values */
9711     switch (p_type) {
9712
9713     case POINTER:       
9714     case IPOINTER:
9715         genNearPointerGet (left,result,ic);
9716         break;
9717
9718     case PPOINTER:
9719         genPagedPointerGet(left,result,ic);
9720         break;
9721
9722     case FPOINTER:
9723         genFarPointerGet (left,result,ic);
9724         break;
9725
9726     case CPOINTER:
9727         genConstPointerGet (left,result,ic);
9728         //pic16_emitcodePointerGet (left,result,ic);
9729         break;
9730
9731     case GPOINTER:
9732 #if 0
9733       if (IS_PTR_CONST(type))
9734         genConstPointerGet (left,result,ic);
9735       else
9736 #endif
9737         genGenPointerGet (left,result,ic);
9738       break;
9739
9740     default:
9741       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9742               "genPointerGet: illegal pointer type");
9743     
9744     }
9745
9746 }
9747
9748 /*-----------------------------------------------------------------*/
9749 /* genPackBits - generates code for packed bit storage             */
9750 /*-----------------------------------------------------------------*/
9751 static void genPackBits (sym_link    *etype ,
9752                          operand *right ,
9753                          char *rname, int p_type)
9754 {
9755   int shCnt = 0 ;
9756   int offset = 0  ;
9757   int rLen = 0 ;
9758   int blen, bstr ;   
9759   char *l ;
9760
9761         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9762         blen = SPEC_BLEN(etype);
9763         bstr = SPEC_BSTR(etype);
9764
9765         if(AOP_TYPE(right) == AOP_LIT) {
9766                 if((blen == 1) && (bstr < 8)) {
9767                   unsigned long lit;
9768                         /* it is a single bit, so use the appropriate bit instructions */
9769
9770                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9771
9772                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9773 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9774                         if(lit) {
9775                                 pic16_emitpcode(POC_BSF,
9776                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9777                         } else {
9778                                 pic16_emitpcode(POC_BCF,
9779                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9780                         }
9781         
9782                   return;
9783                 }
9784
9785                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9786                 offset++;
9787         } else
9788                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9789
9790         /* if the bit lenth is less than or    */
9791         /* it exactly fits a byte then         */
9792         if((shCnt=SPEC_BSTR(etype))
9793                 || SPEC_BLEN(etype) <= 8 )  {
9794
9795                 /* shift left acc */
9796                 AccLsh(shCnt);
9797
9798                 /* using PRODL as a temporary register here */
9799                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9800
9801                 switch (p_type) {
9802                         case FPOINTER:
9803                         case POINTER:
9804                         case GPOINTER:
9805                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9806 //                              pic16_emitcode ("mov","b,a");
9807 //                              pic16_emitcode("mov","a,@%s",rname);
9808                                 break;
9809                 }
9810 #if 1
9811                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9812                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9813                                         (unsigned char)(0xff >> (8-bstr))) ));
9814                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9815                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9816 #endif
9817
9818           return;
9819         }
9820
9821
9822         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9823         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9824         exit(-1);
9825
9826
9827     /* if we r done */
9828     if ( SPEC_BLEN(etype) <= 8 )
9829         return ;
9830
9831     pic16_emitcode("inc","%s",rname);
9832     rLen = SPEC_BLEN(etype) ;     
9833
9834
9835
9836     /* now generate for lengths greater than one byte */
9837     while (1) {
9838
9839         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9840
9841         rLen -= 8 ;
9842         if (rLen <= 0 )
9843             break ;
9844
9845         switch (p_type) {
9846             case POINTER:
9847                 if (*l == '@') {
9848                     MOVA(l);
9849                     pic16_emitcode("mov","@%s,a",rname);
9850                 } else
9851                     pic16_emitcode("mov","@%s,%s",rname,l);
9852                 break;
9853
9854             case FPOINTER:
9855                 MOVA(l);
9856                 pic16_emitcode("movx","@dptr,a");
9857                 break;
9858
9859             case GPOINTER:
9860                 MOVA(l);
9861                 DEBUGpic16_emitcode(";lcall","__gptrput");
9862                 break;  
9863         }   
9864         pic16_emitcode ("inc","%s",rname);
9865     }
9866
9867     MOVA(l);
9868
9869     /* last last was not complete */
9870     if (rLen)   {
9871         /* save the byte & read byte */
9872         switch (p_type) {
9873             case POINTER:
9874                 pic16_emitcode ("mov","b,a");
9875                 pic16_emitcode("mov","a,@%s",rname);
9876                 break;
9877
9878             case FPOINTER:
9879                 pic16_emitcode ("mov","b,a");
9880                 pic16_emitcode("movx","a,@dptr");
9881                 break;
9882
9883             case GPOINTER:
9884                 pic16_emitcode ("push","b");
9885                 pic16_emitcode ("push","acc");
9886                 pic16_emitcode ("lcall","__gptrget");
9887                 pic16_emitcode ("pop","b");
9888                 break;
9889         }
9890
9891         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9892         pic16_emitcode ("orl","a,b");
9893     }
9894
9895     if (p_type == GPOINTER)
9896         pic16_emitcode("pop","b");
9897
9898     switch (p_type) {
9899
9900     case POINTER:
9901         pic16_emitcode("mov","@%s,a",rname);
9902         break;
9903         
9904     case FPOINTER:
9905         pic16_emitcode("movx","@dptr,a");
9906         break;
9907         
9908     case GPOINTER:
9909         DEBUGpic16_emitcode(";lcall","__gptrput");
9910         break;                  
9911     }
9912 }
9913 /*-----------------------------------------------------------------*/
9914 /* genDataPointerSet - remat pointer to data space                 */
9915 /*-----------------------------------------------------------------*/
9916 static void genDataPointerSet(operand *right,
9917                               operand *result,
9918                               iCode *ic)
9919 {
9920     int size, offset = 0, resoffset=0 ;
9921
9922     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9923     pic16_aopOp(right,ic,FALSE);
9924
9925     size = AOP_SIZE(right);
9926
9927 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9928
9929 #if 0
9930     if ( AOP_TYPE(result) == AOP_PCODE) {
9931       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9932               AOP(result)->aopu.pcop->name,
9933                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9934               PCOR(AOP(result)->aopu.pcop)->instance:
9935               PCOI(AOP(result)->aopu.pcop)->offset);
9936     }
9937 #endif
9938
9939         if(AOP(result)->aopu.pcop->type == PO_DIR)
9940                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9941
9942         while (size--) {
9943                 if (AOP_TYPE(right) == AOP_LIT) {
9944                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9945
9946                         lit = lit >> (8*offset);
9947                         if(lit&0xff) {
9948                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9949                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9950                         } else {
9951                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9952                         }
9953                 } else {
9954                         mov2w(AOP(right), offset);
9955                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9956                 }
9957                 offset++;
9958                 resoffset++;
9959         }
9960
9961     pic16_freeAsmop(right,NULL,ic,TRUE);
9962 }
9963
9964
9965
9966 /*-----------------------------------------------------------------*/
9967 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9968 /*-----------------------------------------------------------------*/
9969 static void genNearPointerSet (operand *right,
9970                                operand *result, 
9971                                iCode *ic)
9972 {
9973   asmop *aop = NULL;
9974   char *l;
9975   sym_link *retype;
9976   sym_link *ptype = operandType(result);
9977   sym_link *resetype;
9978     
9979         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9980         retype= getSpec(operandType(right));
9981         resetype = getSpec(operandType(result));
9982   
9983         pic16_aopOp(result,ic,FALSE);
9984     
9985         /* if the result is rematerializable &
9986          * in data space & not a bit variable */
9987         
9988         /* and result is not a bit variable */
9989         if (AOP_TYPE(result) == AOP_PCODE
9990 //              && AOP_TYPE(result) == AOP_IMMD
9991                 && DCL_TYPE(ptype) == POINTER
9992                 && !IS_BITFIELD(retype)
9993                 && !IS_BITFIELD(resetype)) {
9994
9995                 genDataPointerSet (right,result,ic);
9996                 pic16_freeAsmop(result,NULL,ic,TRUE);
9997           return;
9998         }
9999
10000         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10001         pic16_aopOp(right,ic,FALSE);
10002         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10003
10004         /* if the value is already in a pointer register
10005          * then don't need anything more */
10006         if (!AOP_INPREG(AOP(result))) {
10007                 /* otherwise get a free pointer register */
10008                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10009
10010                 if( (AOP_TYPE(result) == AOP_PCODE) 
10011                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10012                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10013                 {
10014                         pic16_loadFSR0( result );  // patch 10
10015                 } else {
10016                         // set up FSR0 with address of result
10017                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10018                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10019                 }
10020
10021         }
10022 //      else
10023 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10024
10025         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10026
10027         /* if bitfield then unpack the bits */
10028         if (IS_BITFIELD(resetype)) {
10029                 genPackBits (resetype, right, NULL, POINTER);
10030         } else {
10031                 /* we have can just get the values */
10032           int size = AOP_SIZE(right);
10033           int offset = 0 ;    
10034
10035                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10036                 while (size--) {
10037                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10038                         if (*l == '@' ) {
10039                                 //MOVA(l);
10040                                 //pic16_emitcode("mov","@%s,a",rname);
10041                                 pic16_emitcode("movf","indf0,w ;1");
10042                         } else {
10043
10044                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10045                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10046                                         if (size) {                                                                     // 
10047                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10048                                         } else {                                                                        // 
10049                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10050                                         }                                                                               // 
10051                                 } else { // no literal                                                                  // 
10052                                         if(size) {                                                                      // 
10053                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10054                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10055                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10056                                         } else {                                                                        // 
10057                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10058                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10059                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10060                                         }                                                                               //
10061                                 }                                                                                       // patch 10
10062                         }
10063                         offset++;
10064                 }
10065         }
10066
10067         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10068         /* now some housekeeping stuff */
10069         if (aop) {
10070                 /* we had to allocate for this iCode */
10071                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10072         } else { 
10073                 /* we did not allocate which means left
10074                  * already in a pointer register, then
10075                  * if size > 0 && this could be used again
10076                  * we have to point it back to where it 
10077                  * belongs */
10078                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10079                 if (AOP_SIZE(right) > 1
10080                         && !OP_SYMBOL(result)->remat
10081                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10082                                 || ic->depth )) {
10083
10084                   int size = AOP_SIZE(right) - 1;
10085
10086                         while (size--)
10087                                 pic16_emitcode("decf","fsr0,f");
10088                         //pic16_emitcode("dec","%s",rname);
10089                 }
10090         }
10091
10092         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10093         /* done */
10094 //release:
10095         pic16_freeAsmop(right,NULL,ic,TRUE);
10096         pic16_freeAsmop(result,NULL,ic,TRUE);
10097 }
10098
10099 /*-----------------------------------------------------------------*/
10100 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10101 /*-----------------------------------------------------------------*/
10102 static void genPagedPointerSet (operand *right,
10103                                operand *result, 
10104                                iCode *ic)
10105 {
10106     asmop *aop = NULL;
10107     regs *preg = NULL ;
10108     char *rname , *l;
10109     sym_link *retype;
10110        
10111     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10112
10113     retype= getSpec(operandType(right));
10114     
10115     pic16_aopOp(result,ic,FALSE);
10116     
10117     /* if the value is already in a pointer register
10118        then don't need anything more */
10119     if (!AOP_INPREG(AOP(result))) {
10120         /* otherwise get a free pointer register */
10121         aop = newAsmop(0);
10122         preg = getFreePtr(ic,&aop,FALSE);
10123         pic16_emitcode("mov","%s,%s",
10124                 preg->name,
10125                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10126         rname = preg->name ;
10127     } else
10128         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10129     
10130     pic16_freeAsmop(result,NULL,ic,TRUE);
10131     pic16_aopOp (right,ic,FALSE);
10132
10133     /* if bitfield then unpack the bits */
10134     if (IS_BITFIELD(retype)) 
10135         genPackBits (retype,right,rname,PPOINTER);
10136     else {
10137         /* we have can just get the values */
10138         int size = AOP_SIZE(right);
10139         int offset = 0 ;        
10140         
10141         while (size--) {
10142             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10143             
10144             MOVA(l);
10145             pic16_emitcode("movx","@%s,a",rname);
10146
10147             if (size)
10148                 pic16_emitcode("inc","%s",rname);
10149
10150             offset++;
10151         }
10152     }
10153     
10154     /* now some housekeeping stuff */
10155     if (aop) {
10156         /* we had to allocate for this iCode */
10157         pic16_freeAsmop(NULL,aop,ic,TRUE);
10158     } else { 
10159         /* we did not allocate which means left
10160            already in a pointer register, then
10161            if size > 0 && this could be used again
10162            we have to point it back to where it 
10163            belongs */
10164         if (AOP_SIZE(right) > 1 &&
10165             !OP_SYMBOL(result)->remat &&
10166             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10167               ic->depth )) {
10168             int size = AOP_SIZE(right) - 1;
10169             while (size--)
10170                 pic16_emitcode("dec","%s",rname);
10171         }
10172     }
10173
10174     /* done */
10175     pic16_freeAsmop(right,NULL,ic,TRUE);
10176     
10177         
10178 }
10179
10180 /*-----------------------------------------------------------------*/
10181 /* genFarPointerSet - set value from far space                     */
10182 /*-----------------------------------------------------------------*/
10183 static void genFarPointerSet (operand *right,
10184                               operand *result, iCode *ic)
10185 {
10186     int size, offset ;
10187     sym_link *retype = getSpec(operandType(right));
10188
10189     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10190     pic16_aopOp(result,ic,FALSE);
10191
10192     /* if the operand is already in dptr 
10193     then we do nothing else we move the value to dptr */
10194     if (AOP_TYPE(result) != AOP_STR) {
10195         /* if this is remateriazable */
10196         if (AOP_TYPE(result) == AOP_IMMD)
10197             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10198         else { /* we need to get it byte by byte */
10199             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10200             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10201             if (options.model == MODEL_FLAT24)
10202             {
10203                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10204             }
10205         }
10206     }
10207     /* so dptr know contains the address */
10208     pic16_freeAsmop(result,NULL,ic,TRUE);
10209     pic16_aopOp(right,ic,FALSE);
10210
10211     /* if bit then unpack */
10212     if (IS_BITFIELD(retype)) 
10213         genPackBits(retype,right,"dptr",FPOINTER);
10214     else {
10215         size = AOP_SIZE(right);
10216         offset = 0 ;
10217
10218         while (size--) {
10219             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10220             MOVA(l);
10221             pic16_emitcode("movx","@dptr,a");
10222             if (size)
10223                 pic16_emitcode("inc","dptr");
10224         }
10225     }
10226
10227     pic16_freeAsmop(right,NULL,ic,TRUE);
10228 }
10229
10230 /*-----------------------------------------------------------------*/
10231 /* genGenPointerSet - set value from generic pointer space         */
10232 /*-----------------------------------------------------------------*/
10233 static void genGenPointerSet (operand *right,
10234                               operand *result, iCode *ic)
10235 {
10236         int i, size, offset, lit;
10237         sym_link *retype = getSpec(operandType(right));
10238
10239         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10240
10241         pic16_aopOp(result,ic,FALSE);
10242         pic16_aopOp(right,ic,FALSE);
10243         size = AOP_SIZE(right);
10244         offset = 0;
10245
10246         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10247
10248         /* if the operand is already in dptr 
10249                 then we do nothing else we move the value to dptr */
10250         if (AOP_TYPE(result) != AOP_STR) {
10251                 /* if this is remateriazable */
10252                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10253                 // WARNING: anythig until "else" is untested!
10254                 if (AOP_TYPE(result) == AOP_IMMD) {
10255                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10256                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10257                         // load FSR0 from immediate
10258                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10259                         offset = 0;
10260                         while(size--) {
10261                                 if(size) {
10262                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10263                                 } else {
10264                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10265                                 }
10266                                 offset++;
10267                         }
10268                         goto release;
10269                 }
10270                 else { /* we need to get it byte by byte */
10271                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10272                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10273
10274                         // set up FSR0 with address of result
10275                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10276                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10277
10278                         /* hack hack! see if this the FSR. If so don't load W */
10279                         if(AOP_TYPE(right) != AOP_ACC) {
10280
10281                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10282
10283                                 if(AOP_TYPE(right) == AOP_LIT)
10284                                 {
10285                                         // copy literal
10286                                         // note: pic16_popGet handles sign extension
10287                                         for(i=0;i<size;i++) {
10288                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10289                                                 if(i < size-1)
10290                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10291                                                 else
10292                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10293                                         }
10294                                 } else {
10295                                         // copy regs
10296
10297                                         for(i=0;i<size;i++) {
10298                                                 if(i < size-1)
10299                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10300                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10301                                                 else
10302                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10303                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10304                                         }
10305                                 }
10306                                 goto release;
10307                         } 
10308                         // right = ACC
10309                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10310                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10311                         goto release;
10312         } // if (AOP_TYPE(result) != AOP_IMMD)
10313
10314         } // if (AOP_TYPE(result) != AOP_STR)
10315         /* so dptr know contains the address */
10316
10317
10318         /* if bit then unpack */
10319         if (IS_BITFIELD(retype)) 
10320                 genPackBits(retype,right,"dptr",GPOINTER);
10321         else {
10322                 size = AOP_SIZE(right);
10323                 offset = 0 ;
10324
10325                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10326
10327                 // set up FSR0 with address of result
10328                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10329                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10330         
10331                 while (size--) {
10332                         if (AOP_TYPE(right) == AOP_LIT) {
10333                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10334                                 if (size) {
10335                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10336                                 } else {
10337                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10338                                 }
10339                         } else { // no literal
10340                                 if(size) {
10341                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10342                                 } else {
10343                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10344                                 }
10345                         }
10346                         offset++;
10347                 }
10348         }
10349
10350         release:
10351         pic16_freeAsmop(right,NULL,ic,TRUE);
10352         pic16_freeAsmop(result,NULL,ic,TRUE);
10353 }
10354
10355 /*-----------------------------------------------------------------*/
10356 /* genPointerSet - stores the value into a pointer location        */
10357 /*-----------------------------------------------------------------*/
10358 static void genPointerSet (iCode *ic)
10359 {    
10360     operand *right, *result ;
10361     sym_link *type, *etype;
10362     int p_type;
10363
10364     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10365
10366     right = IC_RIGHT(ic);
10367     result = IC_RESULT(ic) ;
10368
10369     /* depending on the type of pointer we need to
10370     move it to the correct pointer register */
10371     type = operandType(result);
10372     etype = getSpec(type);
10373     /* if left is of type of pointer then it is simple */
10374     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10375         p_type = DCL_TYPE(type);
10376     }
10377     else {
10378         /* we have to go by the storage class */
10379         p_type = PTR_TYPE(SPEC_OCLS(etype));
10380
10381 /*      if (SPEC_OCLS(etype)->codesp ) { */
10382 /*          p_type = CPOINTER ;  */
10383 /*      } */
10384 /*      else */
10385 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10386 /*              p_type = FPOINTER ; */
10387 /*          else */
10388 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10389 /*                  p_type = PPOINTER ; */
10390 /*              else */
10391 /*                  if (SPEC_OCLS(etype) == idata ) */
10392 /*                      p_type = IPOINTER ; */
10393 /*                  else */
10394 /*                      p_type = POINTER ; */
10395     }
10396
10397     /* now that we have the pointer type we assign
10398     the pointer values */
10399     switch (p_type) {
10400
10401     case POINTER:
10402     case IPOINTER:
10403         genNearPointerSet (right,result,ic);
10404         break;
10405
10406     case PPOINTER:
10407         genPagedPointerSet (right,result,ic);
10408         break;
10409
10410     case FPOINTER:
10411         genFarPointerSet (right,result,ic);
10412         break;
10413
10414     case GPOINTER:
10415         genGenPointerSet (right,result,ic);
10416         break;
10417
10418     default:
10419       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10420               "genPointerSet: illegal pointer type");
10421     }
10422 }
10423
10424 /*-----------------------------------------------------------------*/
10425 /* genIfx - generate code for Ifx statement                        */
10426 /*-----------------------------------------------------------------*/
10427 static void genIfx (iCode *ic, iCode *popIc)
10428 {
10429   operand *cond = IC_COND(ic);
10430   int isbit =0;
10431
10432   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10433
10434   pic16_aopOp(cond,ic,FALSE);
10435
10436   /* get the value into acc */
10437   if (AOP_TYPE(cond) != AOP_CRY)
10438     pic16_toBoolean(cond);
10439   else
10440     isbit = 1;
10441   /* the result is now in the accumulator */
10442   pic16_freeAsmop(cond,NULL,ic,TRUE);
10443
10444   /* if there was something to be popped then do it */
10445   if (popIc)
10446     genIpop(popIc);
10447
10448   /* if the condition is  a bit variable */
10449   if (isbit && IS_ITEMP(cond) && 
10450       SPIL_LOC(cond)) {
10451     genIfxJump(ic,SPIL_LOC(cond)->rname);
10452     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10453   }
10454   else {
10455     if (isbit && !IS_ITEMP(cond))
10456       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10457     else
10458       genIfxJump(ic,"a");
10459   }
10460   ic->generated = 1;
10461
10462 }
10463
10464 /*-----------------------------------------------------------------*/
10465 /* genAddrOf - generates code for address of                       */
10466 /*-----------------------------------------------------------------*/
10467 static void genAddrOf (iCode *ic)
10468 {
10469   operand *result, *left;
10470   int size;
10471   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10472   pCodeOp *pcop0, *pcop1, *pcop2;
10473
10474         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10475
10476         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10477         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10478
10479         sym = OP_SYMBOL( left );
10480
10481         size = AOP_SIZE(IC_RESULT(ic));
10482
10483 //      if(pic16_debug_verbose) {
10484 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10485 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10486 //      }
10487         
10488         /* Assume that what we want the address of is in data space
10489          * since there is no stack on the PIC, yet! -- VR */
10490         /* low */
10491         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10492
10493         /* high */
10494         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10495         
10496         /* upper */
10497         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10498         
10499
10500         if (size == 3) {
10501                 pic16_emitpcode(POC_MOVLW, pcop0);
10502                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10503                 pic16_emitpcode(POC_MOVLW, pcop1);
10504                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10505                 pic16_emitpcode(POC_MOVLW, pcop2);
10506                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10507         } else
10508         if (size == 2) {
10509                 pic16_emitpcode(POC_MOVLW, pcop0);
10510                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10511                 pic16_emitpcode(POC_MOVLW, pcop1);
10512                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10513         } else {
10514                 pic16_emitpcode(POC_MOVLW, pcop0);
10515                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10516         }
10517
10518         pic16_freeAsmop(result,NULL,ic,TRUE);
10519         pic16_freeAsmop(left, NULL, ic, FALSE);
10520 }
10521
10522
10523 #if 0
10524 /*-----------------------------------------------------------------*/
10525 /* genFarFarAssign - assignment when both are in far space         */
10526 /*-----------------------------------------------------------------*/
10527 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10528 {
10529     int size = AOP_SIZE(right);
10530     int offset = 0;
10531     char *l ;
10532     /* first push the right side on to the stack */
10533     while (size--) {
10534         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10535         MOVA(l);
10536         pic16_emitcode ("push","acc");
10537     }
10538     
10539     pic16_freeAsmop(right,NULL,ic,FALSE);
10540     /* now assign DPTR to result */
10541     pic16_aopOp(result,ic,FALSE);
10542     size = AOP_SIZE(result);
10543     while (size--) {
10544         pic16_emitcode ("pop","acc");
10545         pic16_aopPut(AOP(result),"a",--offset);
10546     }
10547     pic16_freeAsmop(result,NULL,ic,FALSE);
10548         
10549 }
10550 #endif
10551
10552 /*-----------------------------------------------------------------*/
10553 /* genAssign - generate code for assignment                        */
10554 /*-----------------------------------------------------------------*/
10555 static void genAssign (iCode *ic)
10556 {
10557   operand *result, *right;
10558   int size, offset,know_W;
10559   unsigned long lit = 0L;
10560
10561   result = IC_RESULT(ic);
10562   right  = IC_RIGHT(ic) ;
10563
10564   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10565   
10566   /* if they are the same */
10567   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10568     return ;
10569
10570   pic16_aopOp(right,ic,FALSE);
10571   pic16_aopOp(result,ic,TRUE);
10572
10573   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10574
10575   /* if they are the same registers */
10576   if (pic16_sameRegs(AOP(right),AOP(result)))
10577     goto release;
10578
10579   /* if the result is a bit */
10580   if (AOP_TYPE(result) == AOP_CRY) {
10581     /* if the right size is a literal then
10582        we know what the value is */
10583     if (AOP_TYPE(right) == AOP_LIT) {
10584           
10585       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10586                   pic16_popGet(AOP(result),0));
10587
10588       if (((int) operandLitValue(right))) 
10589         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10590                        AOP(result)->aopu.aop_dir,
10591                        AOP(result)->aopu.aop_dir);
10592       else
10593         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10594                        AOP(result)->aopu.aop_dir,
10595                        AOP(result)->aopu.aop_dir);
10596       goto release;
10597     }
10598
10599     /* the right is also a bit variable */
10600     if (AOP_TYPE(right) == AOP_CRY) {
10601       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10602       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10603       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10604
10605       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10606                      AOP(result)->aopu.aop_dir,
10607                      AOP(result)->aopu.aop_dir);
10608       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10609                      AOP(right)->aopu.aop_dir,
10610                      AOP(right)->aopu.aop_dir);
10611       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10612                      AOP(result)->aopu.aop_dir,
10613                      AOP(result)->aopu.aop_dir);
10614       goto release ;
10615     }
10616
10617     /* we need to or */
10618     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10619     pic16_toBoolean(right);
10620     emitSKPZ;
10621     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10622     //pic16_aopPut(AOP(result),"a",0);
10623     goto release ;
10624   }
10625
10626   /* bit variables done */
10627   /* general case */
10628   size = AOP_SIZE(result);
10629   offset = 0 ;
10630
10631   if(AOP_TYPE(right) == AOP_LIT) {
10632         if(!IS_FLOAT(operandType( right )))
10633                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10634         else {
10635            union {
10636               unsigned long lit_int;
10637               float lit_float;
10638             } info;
10639         
10640                 /* take care if literal is a float */
10641                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10642                 lit = info.lit_int;
10643         }
10644   }
10645
10646 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10647 //                      sizeof(unsigned long int), sizeof(float));
10648
10649   if(AOP_TYPE(right) != AOP_LIT
10650         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10651         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10652
10653         // set up table pointer
10654         if( (AOP_TYPE(right) == AOP_PCODE)
10655                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10656                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10657         {
10658                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10659                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10660                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10661                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10662                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10663                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10664         } else {
10665                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10666                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10667                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10668                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10669                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10670                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10671         }
10672
10673         size = min(AOP_SIZE(right), AOP_SIZE(result));
10674         while(size--) {
10675                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10676                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10677                         pic16_popGet(AOP(result),offset)));
10678                 offset++;
10679         }
10680
10681         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10682                 size = AOP_SIZE(result) - AOP_SIZE(right);
10683                 while(size--) {
10684                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10685                         offset++;
10686                 }
10687         }
10688         goto release;
10689   }
10690
10691
10692
10693 /* VR - What is this?! */
10694   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10695   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10696     if(aopIdx(AOP(result),0) == 4) {
10697   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10698         assert(0);
10699       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10700       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10701       goto release;
10702     } else
10703 //      assert(0);
10704       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10705   }
10706
10707   know_W=-1;
10708   while (size--) {
10709   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10710     if(AOP_TYPE(right) == AOP_LIT) {
10711       if(lit&0xff) {
10712         if(know_W != (lit&0xff))
10713           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10714         know_W = lit&0xff;
10715         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10716       } else
10717         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10718
10719       lit >>= 8;
10720
10721     } else if (AOP_TYPE(right) == AOP_CRY) {
10722       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10723       if(offset == 0) {
10724         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10725         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10726       }
10727     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10728         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10729         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10730     } else {
10731   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10732
10733 #if 1
10734         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10735            normally should work, but mind that the W register live range
10736            is not checked, so if the code generator assumes that the W
10737            is already loaded after such a pair, wrong code will be generated.
10738            
10739            Checking the live range is the next step.
10740            This is experimental code yet and has not been fully tested yet.
10741            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10742            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10743            
10744         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10745 #else   
10746         /* This is the old code, which is assumed(?!) that works fine(!?) */
10747
10748         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10749         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10750 #endif
10751     }
10752             
10753     offset++;
10754   }
10755
10756     
10757  release:
10758   pic16_freeAsmop (right,NULL,ic,FALSE);
10759   pic16_freeAsmop (result,NULL,ic,TRUE);
10760 }   
10761
10762 /*-----------------------------------------------------------------*/
10763 /* genJumpTab - generates code for jump table                       */
10764 /*-----------------------------------------------------------------*/
10765 static void genJumpTab (iCode *ic)
10766 {
10767     symbol *jtab;
10768     char *l;
10769
10770     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10771
10772     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10773     /* get the condition into accumulator */
10774     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10775     MOVA(l);
10776     /* multiply by three */
10777     pic16_emitcode("add","a,acc");
10778     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10779
10780     jtab = newiTempLabel(NULL);
10781     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10782     pic16_emitcode("jmp","@a+dptr");
10783     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10784
10785     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10786     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10787     emitSKPNC;
10788     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10789     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10790     pic16_emitpLabel(jtab->key);
10791
10792     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10793
10794     /* now generate the jump labels */
10795     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10796          jtab = setNextItem(IC_JTLABELS(ic))) {
10797         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10798         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10799         
10800     }
10801
10802 }
10803
10804 /*-----------------------------------------------------------------*/
10805 /* genMixedOperation - gen code for operators between mixed types  */
10806 /*-----------------------------------------------------------------*/
10807 /*
10808   TSD - Written for the PIC port - but this unfortunately is buggy.
10809   This routine is good in that it is able to efficiently promote 
10810   types to different (larger) sizes. Unfortunately, the temporary
10811   variables that are optimized out by this routine are sometimes
10812   used in other places. So until I know how to really parse the 
10813   iCode tree, I'm going to not be using this routine :(.
10814 */
10815 static int genMixedOperation (iCode *ic)
10816 {
10817 #if 0
10818   operand *result = IC_RESULT(ic);
10819   sym_link *ctype = operandType(IC_LEFT(ic));
10820   operand *right = IC_RIGHT(ic);
10821   int ret = 0;
10822   int big,small;
10823   int offset;
10824
10825   iCode *nextic;
10826   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10827
10828   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10829
10830   nextic = ic->next;
10831   if(!nextic)
10832     return 0;
10833
10834   nextright = IC_RIGHT(nextic);
10835   nextleft  = IC_LEFT(nextic);
10836   nextresult = IC_RESULT(nextic);
10837
10838   pic16_aopOp(right,ic,FALSE);
10839   pic16_aopOp(result,ic,FALSE);
10840   pic16_aopOp(nextright,  nextic, FALSE);
10841   pic16_aopOp(nextleft,   nextic, FALSE);
10842   pic16_aopOp(nextresult, nextic, FALSE);
10843
10844   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10845
10846     operand *t = right;
10847     right = nextright;
10848     nextright = t; 
10849
10850     pic16_emitcode(";remove right +","");
10851
10852   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10853 /*
10854     operand *t = right;
10855     right = nextleft;
10856     nextleft = t; 
10857 */
10858     pic16_emitcode(";remove left +","");
10859   } else
10860     return 0;
10861
10862   big = AOP_SIZE(nextleft);
10863   small = AOP_SIZE(nextright);
10864
10865   switch(nextic->op) {
10866
10867   case '+':
10868     pic16_emitcode(";optimize a +","");
10869     /* if unsigned or not an integral type */
10870     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10871       pic16_emitcode(";add a bit to something","");
10872     } else {
10873
10874       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10875
10876       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10877         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10878         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10879       } else
10880         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10881
10882       offset = 0;
10883       while(--big) {
10884
10885         offset++;
10886
10887         if(--small) {
10888           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10889             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10890             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10891           }
10892
10893           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10894           emitSKPNC;
10895           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10896                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10897                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10898           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10899           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10900
10901         } else {
10902           pic16_emitcode("rlf","known_zero,w");
10903
10904           /*
10905             if right is signed
10906               btfsc  right,7
10907                addlw ff
10908           */
10909           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10910             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10911             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10912           } else {
10913             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10914           }
10915         }
10916       }
10917       ret = 1;
10918     }
10919   }
10920   ret = 1;
10921
10922 release:
10923   pic16_freeAsmop(right,NULL,ic,TRUE);
10924   pic16_freeAsmop(result,NULL,ic,TRUE);
10925   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10926   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10927   if(ret)
10928     nextic->generated = 1;
10929
10930   return ret;
10931 #else
10932   return 0;
10933 #endif
10934 }
10935 /*-----------------------------------------------------------------*/
10936 /* genCast - gen code for casting                                  */
10937 /*-----------------------------------------------------------------*/
10938 static void genCast (iCode *ic)
10939 {
10940   operand *result = IC_RESULT(ic);
10941   sym_link *ctype = operandType(IC_LEFT(ic));
10942   sym_link *rtype = operandType(IC_RIGHT(ic));
10943   operand *right = IC_RIGHT(ic);
10944   int size, offset ;
10945
10946         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10947         /* if they are equivalent then do nothing */
10948         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10949                 return ;
10950
10951         pic16_aopOp(right,ic,FALSE) ;
10952         pic16_aopOp(result,ic,FALSE);
10953
10954         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10955
10956         /* if the result is a bit */
10957         if (AOP_TYPE(result) == AOP_CRY) {
10958         
10959                 /* if the right size is a literal then
10960                  * we know what the value is */
10961                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10962
10963                 if (AOP_TYPE(right) == AOP_LIT) {
10964                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10965                                 pic16_popGet(AOP(result),0));
10966
10967                         if (((int) operandLitValue(right))) 
10968                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10969                                         AOP(result)->aopu.aop_dir,
10970                                         AOP(result)->aopu.aop_dir);
10971                         else
10972                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10973                                         AOP(result)->aopu.aop_dir,
10974                                         AOP(result)->aopu.aop_dir);
10975                         goto release;
10976                 }
10977
10978                 /* the right is also a bit variable */
10979                 if (AOP_TYPE(right) == AOP_CRY) {
10980                         emitCLRC;
10981                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10982
10983                         pic16_emitcode("clrc","");
10984                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10985                                 AOP(right)->aopu.aop_dir,
10986                                 AOP(right)->aopu.aop_dir);
10987                         pic16_aopPut(AOP(result),"c",0);
10988                         goto release ;
10989                 }
10990
10991                 /* we need to or */
10992                 if (AOP_TYPE(right) == AOP_REG) {
10993                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10994                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10995                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10996                 }
10997                 pic16_toBoolean(right);
10998                 pic16_aopPut(AOP(result),"a",0);
10999                 goto release ;
11000         }
11001
11002         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11003           int offset = 1;
11004
11005                 size = AOP_SIZE(result);
11006
11007                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11008
11009                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11010                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11011                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11012
11013                 while (size--)
11014                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11015
11016                 goto release;
11017         }
11018
11019         /* if they are the same size : or less */
11020         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11021
11022                 /* if they are in the same place */
11023                 if (pic16_sameRegs(AOP(right),AOP(result)))
11024                         goto release;
11025
11026                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11027 #if 0
11028                 if (IS_PTR_CONST(rtype))
11029 #else
11030                 if (IS_CODEPTR(rtype))
11031 #endif
11032                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11033
11034 #if 0
11035                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11036 #else
11037                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11038 #endif
11039                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11040
11041 #if 0
11042                 if(AOP_TYPE(right) == AOP_IMMD) {
11043                   pCodeOp *pcop0, *pcop1, *pcop2;
11044                   symbol *sym = OP_SYMBOL( right );
11045
11046                         size = AOP_SIZE(result);
11047                         /* low */
11048                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11049                         /* high */
11050                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11051                         /* upper */
11052                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11053         
11054                         if (size == 3) {
11055                                 pic16_emitpcode(POC_MOVLW, pcop0);
11056                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11057                                 pic16_emitpcode(POC_MOVLW, pcop1);
11058                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11059                                 pic16_emitpcode(POC_MOVLW, pcop2);
11060                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11061                         } else
11062                         if (size == 2) {
11063                                 pic16_emitpcode(POC_MOVLW, pcop0);
11064                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11065                                 pic16_emitpcode(POC_MOVLW, pcop1);
11066                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11067                         } else {
11068                                 pic16_emitpcode(POC_MOVLW, pcop0);
11069                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11070                         }
11071                 } else
11072 #endif
11073                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11074                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11075                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11076                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11077                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11078                         if(AOP_SIZE(result) <2)
11079                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11080                 } else {
11081                         /* if they in different places then copy */
11082                         size = AOP_SIZE(result);
11083                         offset = 0 ;
11084                         while (size--) {
11085                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11086                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11087                                 offset++;
11088                         }
11089                 }
11090                 goto release;
11091         }
11092
11093         /* if the result is of type pointer */
11094         if (IS_PTR(ctype)) {
11095           int p_type;
11096           sym_link *type = operandType(right);
11097           sym_link *etype = getSpec(type);
11098
11099                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11100
11101                 /* pointer to generic pointer */
11102                 if (IS_GENPTR(ctype)) {
11103                   char *l = zero;
11104             
11105                         if (IS_PTR(type)) 
11106                                 p_type = DCL_TYPE(type);
11107                         else {
11108                 /* we have to go by the storage class */
11109                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11110
11111 /*              if (SPEC_OCLS(etype)->codesp )  */
11112 /*                  p_type = CPOINTER ;  */
11113 /*              else */
11114 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11115 /*                      p_type = FPOINTER ; */
11116 /*                  else */
11117 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11118 /*                          p_type = PPOINTER; */
11119 /*                      else */
11120 /*                          if (SPEC_OCLS(etype) == idata ) */
11121 /*                              p_type = IPOINTER ; */
11122 /*                          else */
11123 /*                              p_type = POINTER ; */
11124             }
11125                 
11126             /* the first two bytes are known */
11127       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11128             size = GPTRSIZE - 1; 
11129             offset = 0 ;
11130             while (size--) {
11131               if(offset < AOP_SIZE(right)) {
11132       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11133                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11134                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11135                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11136                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11137                 } else { 
11138                   pic16_aopPut(AOP(result),
11139                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11140                          offset);
11141                 }
11142               } else 
11143                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11144               offset++;
11145             }
11146             /* the last byte depending on type */
11147             switch (p_type) {
11148             case IPOINTER:
11149             case POINTER:
11150                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11151                 break;
11152             case FPOINTER:
11153               pic16_emitcode(";BUG!? ","%d",__LINE__);
11154                 l = one;
11155                 break;
11156             case CPOINTER:
11157               pic16_emitcode(";BUG!? ","%d",__LINE__);
11158                 l = "#0x02";
11159                 break;                          
11160             case PPOINTER:
11161               pic16_emitcode(";BUG!? ","%d",__LINE__);
11162                 l = "#0x03";
11163                 break;
11164                 
11165             default:
11166                 /* this should never happen */
11167                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11168                        "got unknown pointer type");
11169                 exit(1);
11170             }
11171             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11172             goto release ;
11173         }
11174         
11175         /* just copy the pointers */
11176         size = AOP_SIZE(result);
11177         offset = 0 ;
11178         while (size--) {
11179             pic16_aopPut(AOP(result),
11180                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11181                    offset);
11182             offset++;
11183         }
11184         goto release ;
11185     }
11186     
11187
11188
11189     /* so we now know that the size of destination is greater
11190     than the size of the source.
11191     Now, if the next iCode is an operator then we might be
11192     able to optimize the operation without performing a cast.
11193     */
11194     if(genMixedOperation(ic))
11195       goto release;
11196
11197     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11198     
11199     /* we move to result for the size of source */
11200     size = AOP_SIZE(right);
11201     offset = 0 ;
11202     while (size--) {
11203       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11204       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11205       offset++;
11206     }
11207
11208     /* now depending on the sign of the destination */
11209     size = AOP_SIZE(result) - AOP_SIZE(right);
11210     /* if unsigned or not an integral type */
11211     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11212       while (size--)
11213         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11214     } else {
11215       /* we need to extend the sign :( */
11216
11217       if(size == 1) {
11218         /* Save one instruction of casting char to int */
11219         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11220         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11221         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11222       } else {
11223         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11224
11225         if(offset)
11226           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11227         else
11228           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11229         
11230         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11231
11232         while (size--)
11233           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11234       }
11235     }
11236
11237 release:
11238     pic16_freeAsmop(right,NULL,ic,TRUE);
11239     pic16_freeAsmop(result,NULL,ic,TRUE);
11240
11241 }
11242
11243 /*-----------------------------------------------------------------*/
11244 /* genDjnz - generate decrement & jump if not zero instrucion      */
11245 /*-----------------------------------------------------------------*/
11246 static int genDjnz (iCode *ic, iCode *ifx)
11247 {
11248     symbol *lbl, *lbl1;
11249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11250
11251     if (!ifx)
11252         return 0;
11253     
11254     /* if the if condition has a false label
11255        then we cannot save */
11256     if (IC_FALSE(ifx))
11257         return 0;
11258
11259     /* if the minus is not of the form 
11260        a = a - 1 */
11261     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11262         !IS_OP_LITERAL(IC_RIGHT(ic)))
11263         return 0;
11264
11265     if (operandLitValue(IC_RIGHT(ic)) != 1)
11266         return 0;
11267
11268     /* if the size of this greater than one then no
11269        saving */
11270     if (getSize(operandType(IC_RESULT(ic))) > 1)
11271         return 0;
11272
11273     /* otherwise we can save BIG */
11274     lbl = newiTempLabel(NULL);
11275     lbl1= newiTempLabel(NULL);
11276
11277     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11278     
11279     if (IS_AOP_PREG(IC_RESULT(ic))) {
11280         pic16_emitcode("dec","%s",
11281                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11282         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11283         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11284     } else {    
11285
11286
11287       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11288       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11289
11290       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11291       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11292
11293     }
11294 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11295 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11296 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11297 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11298
11299     
11300     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11301     ifx->generated = 1;
11302     return 1;
11303 }
11304
11305 /*-----------------------------------------------------------------*/
11306 /* genReceive - generate code for a receive iCode                  */
11307 /*-----------------------------------------------------------------*/
11308 static void genReceive (iCode *ic)
11309 {    
11310         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11311
11312         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11313                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11314                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11315
11316           int size = getSize(operandType(IC_RESULT(ic)));
11317           int offset =  pic16_fReturnSizePic - size;
11318
11319                 while (size--) {
11320                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11321                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11322                         offset++;
11323                 }
11324
11325                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11326
11327                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11328                 size = AOP_SIZE(IC_RESULT(ic));
11329                 offset = 0;
11330                 while (size--) {
11331                         pic16_emitcode ("pop","acc");
11332                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11333                 }
11334         } else {
11335                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11336
11337                 _G.accInUse++;
11338                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11339                 _G.accInUse--;
11340                 assignResultValue(IC_RESULT(ic), 0);
11341         }
11342
11343         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11344 }
11345
11346 /*-----------------------------------------------------------------*/
11347 /* genDummyRead - generate code for dummy read of volatiles        */
11348 /*-----------------------------------------------------------------*/
11349 static void
11350 genDummyRead (iCode * ic)
11351 {
11352   pic16_emitcode ("; genDummyRead","");
11353   pic16_emitcode ("; not implemented","");
11354
11355   ic = ic;
11356 }
11357
11358 /*-----------------------------------------------------------------*/
11359 /* genpic16Code - generate code for pic16 based controllers        */
11360 /*-----------------------------------------------------------------*/
11361 /*
11362  * At this point, ralloc.c has gone through the iCode and attempted
11363  * to optimize in a way suitable for a PIC. Now we've got to generate
11364  * PIC instructions that correspond to the iCode.
11365  *
11366  * Once the instructions are generated, we'll pass through both the
11367  * peep hole optimizer and the pCode optimizer.
11368  *-----------------------------------------------------------------*/
11369
11370 void genpic16Code (iCode *lic)
11371 {
11372     iCode *ic;
11373     int cln = 0;
11374
11375     lineHead = lineCurr = NULL;
11376
11377     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11378     pic16_addpBlock(pb);
11379
11380 #if 0
11381     /* if debug information required */
11382     if (options.debug && currFunc) {
11383       if (currFunc) {
11384         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11385       }
11386     }
11387 #endif
11388
11389     for (ic = lic ; ic ; ic = ic->next ) {
11390
11391       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11392         if ( cln != ic->lineno ) {
11393             if ( options.debug ) {
11394               debugFile->writeCLine (ic);
11395             }
11396             
11397             if(!options.noCcodeInAsm) {
11398                 pic16_addpCode2pBlock(pb,
11399                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11400                                 printCLine(ic->filename, ic->lineno)));
11401             }
11402
11403             cln = ic->lineno ;
11404         }
11405         
11406         if(options.iCodeInAsm) {
11407                 char *l;
11408                 /* insert here code to print iCode as comment */
11409                 l = Safe_strdup(printILine(ic));
11410                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11411         }
11412         
11413         /* if the result is marked as
11414            spilt and rematerializable or code for
11415            this has already been generated then
11416            do nothing */
11417         if (resultRemat(ic) || ic->generated ) 
11418             continue ;
11419         
11420         /* depending on the operation */
11421         switch (ic->op) {
11422         case '!' :
11423             pic16_genNot(ic);
11424             break;
11425             
11426         case '~' :
11427             pic16_genCpl(ic);
11428             break;
11429             
11430         case UNARYMINUS:
11431             genUminus (ic);
11432             break;
11433             
11434         case IPUSH:
11435             genIpush (ic);
11436             break;
11437             
11438         case IPOP:
11439             /* IPOP happens only when trying to restore a 
11440                spilt live range, if there is an ifx statement
11441                following this pop then the if statement might
11442                be using some of the registers being popped which
11443                would destroy the contents of the register so
11444                we need to check for this condition and handle it */
11445             if (ic->next            && 
11446                 ic->next->op == IFX &&
11447                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11448                 genIfx (ic->next,ic);
11449             else
11450                 genIpop (ic);
11451             break; 
11452             
11453         case CALL:
11454             genCall (ic);
11455             break;
11456             
11457         case PCALL:
11458             genPcall (ic);
11459             break;
11460             
11461         case FUNCTION:
11462             genFunction (ic);
11463             break;
11464             
11465         case ENDFUNCTION:
11466             genEndFunction (ic);
11467             break;
11468             
11469         case RETURN:
11470             genRet (ic);
11471             break;
11472             
11473         case LABEL:
11474             genLabel (ic);
11475             break;
11476             
11477         case GOTO:
11478             genGoto (ic);
11479             break;
11480             
11481         case '+' :
11482             pic16_genPlus (ic) ;
11483             break;
11484             
11485         case '-' :
11486             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11487                 pic16_genMinus (ic);
11488             break;
11489             
11490         case '*' :
11491             genMult (ic);
11492             break;
11493             
11494         case '/' :
11495             genDiv (ic) ;
11496             break;
11497             
11498         case '%' :
11499             genMod (ic);
11500             break;
11501             
11502         case '>' :
11503             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11504             break;
11505             
11506         case '<' :
11507             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11508             break;
11509             
11510         case LE_OP:
11511         case GE_OP:
11512         case NE_OP:
11513             
11514             /* note these two are xlated by algebraic equivalence
11515                during parsing SDCC.y */
11516             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11517                    "got '>=' or '<=' shouldn't have come here");
11518             break;      
11519             
11520         case EQ_OP:
11521             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11522             break;          
11523             
11524         case AND_OP:
11525             genAndOp (ic);
11526             break;
11527             
11528         case OR_OP:
11529             genOrOp (ic);
11530             break;
11531             
11532         case '^' :
11533             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11534             break;
11535             
11536         case '|' :
11537                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11538             break;
11539             
11540         case BITWISEAND:
11541             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11542             break;
11543             
11544         case INLINEASM:
11545             genInline (ic);
11546             break;
11547             
11548         case RRC:
11549             genRRC (ic);
11550             break;
11551             
11552         case RLC:
11553             genRLC (ic);
11554             break;
11555             
11556         case GETHBIT:
11557             genGetHbit (ic);
11558             break;
11559             
11560         case LEFT_OP:
11561             genLeftShift (ic);
11562             break;
11563             
11564         case RIGHT_OP:
11565             genRightShift (ic);
11566             break;
11567             
11568         case GET_VALUE_AT_ADDRESS:
11569             genPointerGet(ic);
11570             break;
11571             
11572         case '=' :
11573             if (POINTER_SET(ic))
11574                 genPointerSet(ic);
11575             else
11576                 genAssign(ic);
11577             break;
11578             
11579         case IFX:
11580             genIfx (ic,NULL);
11581             break;
11582             
11583         case ADDRESS_OF:
11584             genAddrOf (ic);
11585             break;
11586             
11587         case JUMPTABLE:
11588             genJumpTab (ic);
11589             break;
11590             
11591         case CAST:
11592             genCast (ic);
11593             break;
11594             
11595         case RECEIVE:
11596             genReceive(ic);
11597             break;
11598             
11599         case SEND:
11600             addSet(&_G.sendSet,ic);
11601             break;
11602
11603         case DUMMY_READ_VOLATILE:
11604           genDummyRead (ic);
11605           break;
11606
11607         default :
11608             ic = ic;
11609         }
11610     }
11611
11612
11613     /* now we are ready to call the
11614        peep hole optimizer */
11615     if (!options.nopeep) {
11616       peepHole (&lineHead);
11617     }
11618     /* now do the actual printing */
11619     printLine (lineHead,codeOutFile);
11620
11621 #ifdef PCODE_DEBUG
11622     DFPRINTF((stderr,"printing pBlock\n\n"));
11623     pic16_printpBlock(stdout,pb);
11624 #endif
11625
11626     return;
11627 }
11628