fd6d3295088dd1b3e2453341f015789daaba14cc
[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
3293                         /* relocate interrupt vectors if needed */
3294                         abSym->address += pic16_options.ivt_loc;
3295
3296                         addSet(&absSymSet, abSym);
3297                 }
3298         }
3299
3300
3301         /* create the function header */
3302         pic16_emitcode(";","-----------------------------------------");
3303         pic16_emitcode(";"," function %s",sym->name);
3304         pic16_emitcode(";","-----------------------------------------");
3305
3306         pic16_emitcode("","%s:",sym->rname);
3307         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3308
3309
3310         {
3311           absSym *ab;
3312
3313                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3314                         if(!strcmp(ab->name, sym->name)) {
3315                                 pic16_pBlockConvert2Absolute(pb);
3316                                 break;
3317                         }
3318
3319         }
3320
3321
3322         if(IFFUNC_ISNAKED(ftype)) {
3323                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3324                 return;
3325         }
3326         
3327         /* if critical function then turn interrupts off */
3328         if (IFFUNC_ISCRITICAL(ftype))
3329                 pic16_emitcode("clr","ea");
3330
3331         /* if this is an interrupt service routine then
3332          * save acc, b, dpl, dph  */
3333         if (IFFUNC_ISISR(sym->type)) {
3334           int i;
3335                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3336                 if(!(_G.interruptvector == 1)) {
3337
3338                         /* do not save WREG,STATUS,BSR for high priority interrupts
3339                          * because they are stored in the hardware shadow registers already */
3340                          
3341                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3342                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3343                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3344                 }
3345
3346                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3347                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3348                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3349                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3350
3351 //                pic16_pBlockConvert2ISR(pb);
3352                 
3353                 /* if any registers used */
3354                 if (sym->regsUsed) {
3355                         /* save the registers used */
3356                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3357                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3358                                 if (bitVectBitValue(sym->regsUsed,i)) {
3359 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3360 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3361 //                                                      pic16_regWithIdx(i)->name);
3362
3363                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3364                                         _G.nRegsSaved++;
3365                                 }
3366                         }
3367                 }
3368         } else {
3369                 /* emit code to setup stack frame if user enabled,
3370                  * and function is not main() */
3371          
3372 //              fprintf(stderr, "function name: %s\n", sym->name);
3373                 if(strcmp(sym->name, "main")) {
3374                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3375                         /* setup the stack frame */
3376                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3377                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3378                                 if(STACK_MODEL_LARGE)
3379                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3380                         }
3381                 }
3382
3383                 /* if callee-save to be used for this function
3384                 * then save the registers being used in this function */
3385 //              if (IFFUNC_CALLEESAVES(sym->type))
3386                 {
3387                   int i;
3388
3389 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3390
3391 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3392
3393                         /* if any registers used */
3394                         if (sym->regsUsed) {
3395                                 /* save the registers used */
3396                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3397                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3398                                         if (bitVectBitValue(sym->regsUsed,i)) {
3399
3400 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3401 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3402 //                                                              pic16_regWithIdx(i)->name);
3403
3404                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3405
3406 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3407 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3408 //                                                      &pic16_pc_postdec1, 0));
3409
3410                                                 _G.nRegsSaved++;
3411                                         }
3412                                 }
3413                         }
3414                 }
3415         }
3416
3417
3418         
3419 #if 0
3420         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3421
3422                 if (options.useXstack) {
3423                         pic16_emitcode("mov","r0,%s",spname);
3424                         pic16_emitcode("mov","a,_bp");
3425                         pic16_emitcode("movx","@r0,a");
3426                         pic16_emitcode("inc","%s",spname);
3427                 } else {
3428                         /* set up the stack */
3429                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3430                 }
3431                 pic16_emitcode ("mov","_bp,%s",spname);
3432         }
3433 #endif
3434         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3435
3436         /* adjust the stack for the function */
3437         if (sym->stack) {
3438           int i = sym->stack;
3439
3440                 if (i > 127 ) 
3441                         werror(W_STACK_OVERFLOW,sym->name);
3442
3443                 if (i > 3 && sym->recvSize < 4) {              
3444                         pic16_emitcode ("mov","a,sp");
3445                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3446                         pic16_emitcode ("mov","sp,a");
3447                 } else
3448                         while(i--)
3449                                 pic16_emitcode("inc","sp");
3450         }
3451
3452         if (sym->xstack) {
3453                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3454
3455                 pic16_emitcode ("mov","a,_spx");
3456                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3457                 pic16_emitcode ("mov","_spx,a");
3458         }
3459     
3460 }
3461
3462 /*-----------------------------------------------------------------*/
3463 /* genEndFunction - generates epilogue for functions               */
3464 /*-----------------------------------------------------------------*/
3465 static void genEndFunction (iCode *ic)
3466 {
3467     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3468
3469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3470
3471     if(IFFUNC_ISNAKED(sym->type)) {
3472         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3473         return;
3474     }
3475
3476 #if 0
3477     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3478     {
3479         pic16_emitcode ("mov","%s,_bp",spname);
3480     }
3481 #endif
3482
3483     /* if use external stack but some variables were
3484     added to the local stack then decrement the
3485     local stack */
3486     if (options.useXstack && sym->stack) {      
3487         pic16_emitcode("mov","a,sp");
3488         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3489         pic16_emitcode("mov","sp,a");
3490     }
3491
3492
3493 #if 0
3494     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3495         if (options.useXstack) {
3496             pic16_emitcode("mov","r0,%s",spname);
3497             pic16_emitcode("movx","a,@r0");
3498             pic16_emitcode("mov","_bp,a");
3499             pic16_emitcode("dec","%s",spname);
3500         }
3501         else
3502         {
3503             pic16_emitcode ("pop","_bp");
3504         }
3505     }
3506 #endif
3507
3508         if (IFFUNC_ISISR(sym->type)) {
3509                 /* now we need to restore the registers */
3510                 /* if any registers used */
3511                 if (sym->regsUsed) {
3512                   int i;
3513
3514                         /* restore registers used */
3515                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3516                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3517                                 if (bitVectBitValue(sym->regsUsed,i)) {
3518
3519 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3520 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3521 //                                                      pic16_regWithIdx(i)->name);
3522
3523                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3524
3525 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3526 //                                                      &pic16_pc_preinc1,
3527 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3528
3529                                 }
3530                         }
3531                 }
3532         
3533                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3534                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3535                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3536                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3537
3538                 if(!(_G.interruptvector == 1)) {
3539                         /* do not restore interrupt vector for WREG,STATUS,BSR
3540                          * for high priority interrupt, see genFunction */
3541                          
3542                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3543                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3544                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3545                 }
3546         
3547                 _G.interruptvector = 0;         /* sanity check */
3548
3549 //              pic16_pBlockConvert2ISR(pb);
3550
3551
3552                 /* if debug then send end of function */
3553 /*      if (options.debug && currFunc)  */
3554                 if (currFunc) {
3555                         debugFile->writeEndFunction (currFunc, ic, 1);
3556                 }
3557         
3558                 pic16_emitpcodeNULLop(POC_RETFIE);
3559         } else {
3560                 if (IFFUNC_ISCRITICAL(sym->type))
3561                         pic16_emitcode("setb","ea");
3562         
3563
3564 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3565
3566                 /* if any registers used */
3567                 if (sym->regsUsed) {
3568                   int i;
3569                         /* save the registers used */
3570                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3571                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3572                                 if (bitVectBitValue(sym->regsUsed,i)) {
3573         
3574 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3575 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3576 //                                                      pic16_regWithIdx(i)->name);
3577         
3578                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3579                                         
3580 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3581 //                                              &pic16_pc_preinc1,
3582 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3583
3584                                         _G.nRegsSaved--;
3585                                 }
3586                         }
3587                 }
3588         
3589                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3590                 /* if debug then send end of function */
3591                 if (currFunc) {
3592                         debugFile->writeEndFunction (currFunc, ic, 1);
3593                 }
3594
3595                 /* insert code to restore stack frame, if user enabled it
3596                  * and function is not main() */
3597          
3598
3599                 if(strcmp(sym->name, "main")) {
3600                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3601                                 /* restore stack frame */
3602                                 if(STACK_MODEL_LARGE)
3603                                         pic16_emitpcode(POC_MOVFF,
3604                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3605                                 pic16_emitpcode(POC_MOVFF,
3606                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3607                         }
3608                 }
3609
3610                 pic16_emitcode ("return","");
3611                 pic16_emitpcodeNULLop(POC_RETURN);
3612
3613                 /* Mark the end of a function */
3614                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3615         }
3616
3617 }
3618
3619
3620 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3621 {
3622
3623         if(is_LitOp(op)) {
3624                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3625
3626                 if(dest->type != PO_WREG)
3627                         pic16_emitpcode(POC_MOVWF, dest);
3628         } else {
3629                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3630                         pic16_popGet(AOP(op), offset), dest));
3631         }
3632 }
3633
3634 /*-----------------------------------------------------------------*/
3635 /* genRet - generate code for return statement                     */
3636 /*-----------------------------------------------------------------*/
3637 static void genRet (iCode *ic)
3638 {
3639   int size;
3640   operand *left;
3641
3642         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3643         /* if we have no return value then
3644          * just generate the "ret" */
3645         
3646         if (!IC_LEFT(ic)) 
3647                 goto jumpret;       
3648     
3649         /* we have something to return then
3650          * move the return value into place */
3651         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3652         size = AOP_SIZE(IC_LEFT(ic));
3653
3654         if(size <= 4) {
3655                 if(size>3) {
3656                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3657 //                      pic16_emitpcode(POC_MOVFF,
3658 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3659                 }
3660                 if(size>2) {
3661                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3662 //                      pic16_emitpcode(POC_MOVFF,
3663 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3664                 }
3665                 if(size>1) {
3666                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3667 //                      pic16_emitpcode(POC_MOVFF,
3668 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3669                 }
3670
3671 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3672
3673                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3674 //              pic16_emitpcode(POC_MOVFF,
3675 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3676
3677         } else {
3678                 /* >32-bits, setup stack and FSR0 */
3679                 while (size--) {
3680 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3681 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3682
3683                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3684
3685 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3686                         GpsuedoStkPtr++;
3687                 }
3688                         
3689                 /* setup FSR0 */
3690                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3691                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3692
3693                 if(STACK_MODEL_LARGE) {
3694                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3695                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3696                 } else {
3697                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3698                 }
3699         }
3700                                 
3701 #if 0
3702         /* old code, left here for reference -- VR */    
3703         while (size--) {
3704           char *l ;
3705
3706                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3707                         /* #NOCHANGE */
3708                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3709                         pic16_emitpcomment("push %s",l);
3710                         pushed++;
3711                 } else {
3712                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3713                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3714                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3715                         
3716                         if (strcmp(fReturn[offset],l)) {
3717                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3718                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3719                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3720                                 } else {
3721                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3722                                 }
3723                                 
3724                                 if(size) {
3725                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3726                                 }
3727                                 offset++;
3728                         }
3729                 }
3730         }    
3731
3732         if (pushed) {
3733                 while(pushed) {
3734                         pushed--;
3735                         if (strcmp(fReturn[pushed],"a"))
3736                                 pic16_emitcode("pop",fReturn[pushed]);
3737                         else
3738                                 pic16_emitcode("pop","acc");
3739                 }
3740         }
3741 #endif
3742
3743
3744         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3745     
3746 jumpret:
3747         /* generate a jump to the return label
3748          * if the next is not the return statement */
3749         if (!(ic->next && ic->next->op == LABEL
3750                 && IC_LABEL(ic->next) == returnLabel)) {
3751         
3752                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3753                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3754         }
3755 }
3756
3757 /*-----------------------------------------------------------------*/
3758 /* genLabel - generates a label                                    */
3759 /*-----------------------------------------------------------------*/
3760 static void genLabel (iCode *ic)
3761 {
3762
3763
3764     /* special case never generate */
3765     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3766     if (IC_LABEL(ic) == entryLabel)
3767         return ;
3768
3769     pic16_emitpLabel(IC_LABEL(ic)->key);
3770     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3771 }
3772
3773 /*-----------------------------------------------------------------*/
3774 /* genGoto - generates a goto                                      */
3775 /*-----------------------------------------------------------------*/
3776 //tsd
3777 static void genGoto (iCode *ic)
3778 {
3779   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3780   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3781 }
3782
3783
3784 /*-----------------------------------------------------------------*/
3785 /* genMultbits :- multiplication of bits                           */
3786 /*-----------------------------------------------------------------*/
3787 static void genMultbits (operand *left, 
3788                          operand *right, 
3789                          operand *result)
3790 {
3791   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3792
3793   if(!pic16_sameRegs(AOP(result),AOP(right)))
3794     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3795
3796   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3797   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3798   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3799
3800 }
3801
3802
3803 /*-----------------------------------------------------------------*/
3804 /* genMultOneByte : 8 bit multiplication & division                */
3805 /*-----------------------------------------------------------------*/
3806 static void genMultOneByte (operand *left,
3807                             operand *right,
3808                             operand *result)
3809 {
3810
3811   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3812   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3813   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3814
3815   /* (if two literals, the value is computed before) */
3816   /* if one literal, literal on the right */
3817   if (AOP_TYPE(left) == AOP_LIT){
3818     operand *t = right;
3819     right = left;
3820     left = t;
3821   }
3822
3823         /* size is already checked in genMult == 1 */
3824 //      size = AOP_SIZE(result);
3825
3826         if (AOP_TYPE(right) == AOP_LIT){
3827                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3828                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3829                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3830                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3831         } else {
3832                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3833                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3834                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3835                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3836         }
3837         
3838         pic16_genMult8X8_8 (left, right,result);
3839 }
3840
3841 /*-----------------------------------------------------------------*/
3842 /* genMultOneWord : 16 bit multiplication                          */
3843 /*-----------------------------------------------------------------*/
3844 static void genMultOneWord (operand *left,
3845                             operand *right,
3846                             operand *result)
3847 {
3848
3849         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3850         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3851         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3852
3853         /* (if two literals, the value is computed before)
3854          * if one literal, literal on the right */
3855         if (AOP_TYPE(left) == AOP_LIT){
3856           operand *t = right;
3857                 right = left;
3858                 left = t;
3859         }
3860
3861         /* size is checked already == 2 */
3862 //      size = AOP_SIZE(result);
3863
3864         if (AOP_TYPE(right) == AOP_LIT) {
3865                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3866                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3867                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3868                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3869         } else {
3870                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3871                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3872                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3873                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3874         }
3875         
3876         pic16_genMult16X16_16(left, right,result);
3877 }
3878
3879 /*-----------------------------------------------------------------*/
3880 /* genMultOneLong : 32 bit multiplication                          */
3881 /*-----------------------------------------------------------------*/
3882 static void genMultOneLong (operand *left,
3883                             operand *right,
3884                             operand *result)
3885 {
3886
3887         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3888         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3889         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3890
3891         /* (if two literals, the value is computed before)
3892          * if one literal, literal on the right */
3893         if (AOP_TYPE(left) == AOP_LIT){
3894           operand *t = right;
3895                 right = left;
3896                 left = t;
3897         }
3898
3899         /* size is checked already == 4 */
3900 //      size = AOP_SIZE(result);
3901
3902         if (AOP_TYPE(right) == AOP_LIT) {
3903                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3904                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3905                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3906                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3907         } else {
3908                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3909                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3910                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3911                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3912         }
3913         
3914         pic16_genMult32X32_32(left, right,result);
3915 }
3916
3917
3918
3919 /*-----------------------------------------------------------------*/
3920 /* genMult - generates code for multiplication                     */
3921 /*-----------------------------------------------------------------*/
3922 static void genMult (iCode *ic)
3923 {
3924   operand *left = IC_LEFT(ic);
3925   operand *right = IC_RIGHT(ic);
3926   operand *result= IC_RESULT(ic);   
3927
3928         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3929         /* assign the amsops */
3930         pic16_aopOp (left,ic,FALSE);
3931         pic16_aopOp (right,ic,FALSE);
3932         pic16_aopOp (result,ic,TRUE);
3933
3934         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3935
3936         /* special cases first *
3937         * both are bits */
3938         if (AOP_TYPE(left) == AOP_CRY
3939                 && AOP_TYPE(right)== AOP_CRY) {
3940                 genMultbits(left,right,result);
3941           goto release ;
3942         }
3943
3944         /* if both are of size == 1 */
3945         if(AOP_SIZE(left) == 1
3946                 && AOP_SIZE(right) == 1) {
3947                 genMultOneByte(left,right,result);
3948           goto release ;
3949         }
3950
3951         /* if both are of size == 2 */
3952         if(AOP_SIZE(left) == 2
3953                 && AOP_SIZE(right) == 2) {
3954                 genMultOneWord(left, right, result);
3955           goto release;
3956         }
3957         
3958         /* if both are of size == 4 */
3959         if(AOP_SIZE(left) == 4
3960                 && AOP_SIZE(right) == 4) {
3961                 genMultOneLong(left, right, result);
3962           goto release;
3963         }
3964         
3965         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3966
3967
3968         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3969         /* should have been converted to function call */
3970         assert(0) ;
3971
3972 release :
3973         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3974         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3975         pic16_freeAsmop(result,NULL,ic,TRUE); 
3976 }
3977
3978 /*-----------------------------------------------------------------*/
3979 /* genDivbits :- division of bits                                  */
3980 /*-----------------------------------------------------------------*/
3981 static void genDivbits (operand *left, 
3982                         operand *right, 
3983                         operand *result)
3984 {
3985
3986     char *l;
3987
3988     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3989     /* the result must be bit */    
3990     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3991     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3992
3993     MOVA(l);    
3994
3995     pic16_emitcode("div","ab");
3996     pic16_emitcode("rrc","a");
3997     pic16_aopPut(AOP(result),"c",0);
3998 }
3999
4000 /*-----------------------------------------------------------------*/
4001 /* genDivOneByte : 8 bit division                                  */
4002 /*-----------------------------------------------------------------*/
4003 static void genDivOneByte (operand *left,
4004                            operand *right,
4005                            operand *result)
4006 {
4007     sym_link *opetype = operandType(result);
4008     char *l ;
4009     symbol *lbl ;
4010     int size,offset;
4011
4012         /* result = divident / divisor
4013          * - divident may be a register or a literal,
4014          * - divisor may be a register or a literal,
4015          * so there are 3 cases (literal / literal is optimized
4016          * by the front-end) to handle.
4017          * In addition we must handle signed and unsigned, which
4018          * result in 6 final different cases -- VR */
4019
4020     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4021     size = AOP_SIZE(result) - 1;
4022     offset = 1;
4023     /* signed or unsigned */
4024     if (SPEC_USIGN(opetype)) {
4025       pCodeOp *pct1,    /* count */
4026                 *pct2,  /* reste */
4027                 *pct3;  /* temp */
4028       symbol *label1, *label2, *label3;;
4029
4030
4031         /* unsigned is easy */
4032
4033         pct1 = pic16_popGetTempReg();
4034         pct2 = pic16_popGetTempReg();
4035         pct3 = pic16_popGetTempReg();
4036         
4037         label1 = newiTempLabel(NULL);
4038         label2 = newiTempLabel(NULL);
4039         label3 = newiTempLabel(NULL);
4040
4041         /* the following algorithm is extracted from divuint.c */
4042
4043         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4044         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4045         
4046         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4047
4048         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4049         
4050         pic16_emitpLabel(label1->key);
4051         
4052         emitCLRC;
4053         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4054
4055
4056         emitCLRC;
4057         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4058         
4059
4060         emitSKPNC;
4061         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4062         
4063         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4064         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4065         
4066         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4067         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4068         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4069         
4070         pic16_emitpLabel( label3->key );
4071         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4072         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4073         
4074         
4075
4076         pic16_emitpLabel(label2->key);
4077         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4078         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4079         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4080         
4081         /* result is in wreg */
4082         if(AOP_TYPE(result) != AOP_ACC)
4083                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4084
4085         pic16_popReleaseTempReg( pct3 );
4086         pic16_popReleaseTempReg( pct2 );
4087         pic16_popReleaseTempReg( pct1 );
4088
4089         return ;
4090     }
4091
4092     /* signed is a little bit more difficult */
4093
4094     /* save the signs of the operands */
4095     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4096     MOVA(l);    
4097     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4098     pic16_emitcode("push","acc"); /* save it on the stack */
4099
4100     /* now sign adjust for both left & right */
4101     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4102     MOVA(l);       
4103     lbl = newiTempLabel(NULL);
4104     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4105     pic16_emitcode("cpl","a");   
4106     pic16_emitcode("inc","a");
4107     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4108     pic16_emitcode("mov","b,a");
4109
4110     /* sign adjust left side */
4111     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4112     MOVA(l);
4113
4114     lbl = newiTempLabel(NULL);
4115     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4116     pic16_emitcode("cpl","a");
4117     pic16_emitcode("inc","a");
4118     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4119
4120     /* now the division */
4121     pic16_emitcode("div","ab");
4122     /* we are interested in the lower order
4123     only */
4124     pic16_emitcode("mov","b,a");
4125     lbl = newiTempLabel(NULL);
4126     pic16_emitcode("pop","acc");   
4127     /* if there was an over flow we don't 
4128     adjust the sign of the result */
4129     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4130     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4131     CLRC;
4132     pic16_emitcode("clr","a");
4133     pic16_emitcode("subb","a,b");
4134     pic16_emitcode("mov","b,a");
4135     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4136
4137     /* now we are done */
4138     pic16_aopPut(AOP(result),"b",0);
4139     if(size > 0){
4140         pic16_emitcode("mov","c,b.7");
4141         pic16_emitcode("subb","a,acc");   
4142     }
4143     while (size--)
4144         pic16_aopPut(AOP(result),"a",offset++);
4145
4146 }
4147
4148 /*-----------------------------------------------------------------*/
4149 /* genDiv - generates code for division                            */
4150 /*-----------------------------------------------------------------*/
4151 static void genDiv (iCode *ic)
4152 {
4153     operand *left = IC_LEFT(ic);
4154     operand *right = IC_RIGHT(ic);
4155     operand *result= IC_RESULT(ic);   
4156
4157
4158         /* Division is a very lengthy algorithm, so it is better
4159          * to call support routines than inlining algorithm.
4160          * Division functions written here just in case someone
4161          * wants to inline and not use the support libraries -- VR */
4162
4163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4164     /* assign the amsops */
4165     pic16_aopOp (left,ic,FALSE);
4166     pic16_aopOp (right,ic,FALSE);
4167     pic16_aopOp (result,ic,TRUE);
4168
4169     /* special cases first */
4170     /* both are bits */
4171     if (AOP_TYPE(left) == AOP_CRY &&
4172         AOP_TYPE(right)== AOP_CRY) {
4173         genDivbits(left,right,result);
4174         goto release ;
4175     }
4176
4177     /* if both are of size == 1 */
4178     if (AOP_SIZE(left) == 1 &&
4179         AOP_SIZE(right) == 1 ) {
4180         genDivOneByte(left,right,result);
4181         goto release ;
4182     }
4183
4184     /* should have been converted to function call */
4185     assert(0);
4186 release :
4187     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4188     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4189     pic16_freeAsmop(result,NULL,ic,TRUE); 
4190 }
4191
4192 /*-----------------------------------------------------------------*/
4193 /* genModbits :- modulus of bits                                   */
4194 /*-----------------------------------------------------------------*/
4195 static void genModbits (operand *left, 
4196                         operand *right, 
4197                         operand *result)
4198 {
4199
4200     char *l;
4201
4202     /* the result must be bit */    
4203     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4204     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4205
4206     MOVA(l);       
4207
4208     pic16_emitcode("div","ab");
4209     pic16_emitcode("mov","a,b");
4210     pic16_emitcode("rrc","a");
4211     pic16_aopPut(AOP(result),"c",0);
4212 }
4213
4214 /*-----------------------------------------------------------------*/
4215 /* genModOneByte : 8 bit modulus                                   */
4216 /*-----------------------------------------------------------------*/
4217 static void genModOneByte (operand *left,
4218                            operand *right,
4219                            operand *result)
4220 {
4221     sym_link *opetype = operandType(result);
4222     char *l ;
4223     symbol *lbl ;
4224
4225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4226     /* signed or unsigned */
4227     if (SPEC_USIGN(opetype)) {
4228         /* unsigned is easy */
4229         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4230         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4231         MOVA(l);    
4232         pic16_emitcode("div","ab");
4233         pic16_aopPut(AOP(result),"b",0);
4234         return ;
4235     }
4236
4237     /* signed is a little bit more difficult */
4238
4239     /* save the signs of the operands */
4240     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4241     MOVA(l);
4242
4243     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4244     pic16_emitcode("push","acc"); /* save it on the stack */
4245
4246     /* now sign adjust for both left & right */
4247     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4248     MOVA(l);
4249
4250     lbl = newiTempLabel(NULL);
4251     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4252     pic16_emitcode("cpl","a");   
4253     pic16_emitcode("inc","a");
4254     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4255     pic16_emitcode("mov","b,a"); 
4256
4257     /* sign adjust left side */
4258     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4259     MOVA(l);
4260
4261     lbl = newiTempLabel(NULL);
4262     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4263     pic16_emitcode("cpl","a");   
4264     pic16_emitcode("inc","a");
4265     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4266
4267     /* now the multiplication */
4268     pic16_emitcode("div","ab");
4269     /* we are interested in the lower order
4270     only */
4271     lbl = newiTempLabel(NULL);
4272     pic16_emitcode("pop","acc");   
4273     /* if there was an over flow we don't 
4274     adjust the sign of the result */
4275     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4276     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4277     CLRC ;
4278     pic16_emitcode("clr","a");
4279     pic16_emitcode("subb","a,b");
4280     pic16_emitcode("mov","b,a");
4281     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4282
4283     /* now we are done */
4284     pic16_aopPut(AOP(result),"b",0);
4285
4286 }
4287
4288 /*-----------------------------------------------------------------*/
4289 /* genMod - generates code for division                            */
4290 /*-----------------------------------------------------------------*/
4291 static void genMod (iCode *ic)
4292 {
4293     operand *left = IC_LEFT(ic);
4294     operand *right = IC_RIGHT(ic);
4295     operand *result= IC_RESULT(ic);  
4296
4297     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4298     /* assign the amsops */
4299     pic16_aopOp (left,ic,FALSE);
4300     pic16_aopOp (right,ic,FALSE);
4301     pic16_aopOp (result,ic,TRUE);
4302
4303     /* special cases first */
4304     /* both are bits */
4305     if (AOP_TYPE(left) == AOP_CRY &&
4306         AOP_TYPE(right)== AOP_CRY) {
4307         genModbits(left,right,result);
4308         goto release ;
4309     }
4310
4311     /* if both are of size == 1 */
4312     if (AOP_SIZE(left) == 1 &&
4313         AOP_SIZE(right) == 1 ) {
4314         genModOneByte(left,right,result);
4315         goto release ;
4316     }
4317
4318     /* should have been converted to function call */
4319     assert(0);
4320
4321 release :
4322     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4323     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4324     pic16_freeAsmop(result,NULL,ic,TRUE); 
4325 }
4326
4327 /*-----------------------------------------------------------------*/
4328 /* genIfxJump :- will create a jump depending on the ifx           */
4329 /*-----------------------------------------------------------------*/
4330 /*
4331   note: May need to add parameter to indicate when a variable is in bit space.
4332 */
4333 static void genIfxJump (iCode *ic, char *jval)
4334 {
4335
4336     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4337     /* if true label then we jump if condition
4338     supplied is true */
4339     if ( IC_TRUE(ic) ) {
4340
4341         if(strcmp(jval,"a") == 0)
4342           emitSKPZ;
4343         else if (strcmp(jval,"c") == 0)
4344           emitSKPC;
4345         else {
4346           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4347           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4348         }
4349
4350         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4351         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4352
4353     }
4354     else {
4355         /* false label is present */
4356         if(strcmp(jval,"a") == 0)
4357           emitSKPNZ;
4358         else if (strcmp(jval,"c") == 0)
4359           emitSKPNC;
4360         else {
4361           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4362           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4363         }
4364
4365         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4366         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4367
4368     }
4369
4370
4371     /* mark the icode as generated */
4372     ic->generated = 1;
4373 }
4374
4375 #if 0
4376 // not needed ATM
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genSkip                                                         */
4380 /*-----------------------------------------------------------------*/
4381 static void genSkip(iCode *ifx,int status_bit)
4382 {
4383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4384   if(!ifx)
4385     return;
4386
4387   if ( IC_TRUE(ifx) ) {
4388     switch(status_bit) {
4389     case 'z':
4390       emitSKPNZ;
4391       break;
4392
4393     case 'c':
4394       emitSKPNC;
4395       break;
4396
4397     case 'd':
4398       emitSKPDC;
4399       break;
4400
4401     }
4402
4403     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4404     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4405
4406   } else {
4407
4408     switch(status_bit) {
4409
4410     case 'z':
4411       emitSKPZ;
4412       break;
4413
4414     case 'c':
4415       emitSKPC;
4416       break;
4417
4418     case 'd':
4419       emitSKPDC;
4420       break;
4421     }
4422     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4423     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4424
4425   }
4426
4427 }
4428 #endif
4429
4430 /*-----------------------------------------------------------------*/
4431 /* genSkipc                                                        */
4432 /*-----------------------------------------------------------------*/
4433 static void genSkipc(resolvedIfx *rifx)
4434 {
4435   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4436   
4437   if(!rifx)
4438     return;
4439
4440   if(rifx->condition)
4441     emitSKPC;
4442   else
4443     emitSKPNC;
4444
4445   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4446   rifx->generated = 1;
4447 }
4448
4449 /*-----------------------------------------------------------------*/
4450 /* genSkipz2                                                       */
4451 /*-----------------------------------------------------------------*/
4452 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4453 {
4454   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4455   
4456   if(!rifx)
4457     return;
4458
4459   if( (rifx->condition ^ invert_condition) & 1)
4460     emitSKPZ;
4461   else
4462     emitSKPNZ;
4463
4464   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4465   rifx->generated = 1;
4466 }
4467
4468 #if 0
4469 /*-----------------------------------------------------------------*/
4470 /* genSkipz                                                        */
4471 /*-----------------------------------------------------------------*/
4472 static void genSkipz(iCode *ifx, int condition)
4473 {
4474   if(!ifx)
4475     return;
4476
4477   if(condition)
4478     emitSKPNZ;
4479   else
4480     emitSKPZ;
4481
4482   if ( IC_TRUE(ifx) )
4483     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4484   else
4485     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4486
4487   if ( IC_TRUE(ifx) )
4488     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4489   else
4490     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4491
4492 }
4493 #endif
4494
4495 /*-----------------------------------------------------------------*/
4496 /* genSkipCond                                                     */
4497 /*-----------------------------------------------------------------*/
4498 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4499 {
4500   if(!rifx)
4501     return;
4502
4503   if(rifx->condition)
4504     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4505   else
4506     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4507
4508
4509   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4510   rifx->generated = 1;
4511 }
4512
4513 #if 0
4514 /*-----------------------------------------------------------------*/
4515 /* genChkZeroes :- greater or less than comparison                 */
4516 /*     For each byte in a literal that is zero, inclusive or the   */
4517 /*     the corresponding byte in the operand with W                */
4518 /*     returns true if any of the bytes are zero                   */
4519 /*-----------------------------------------------------------------*/
4520 static int genChkZeroes(operand *op, int lit,  int size)
4521 {
4522
4523   int i;
4524   int flag =1;
4525
4526   while(size--) {
4527     i = (lit >> (size*8)) & 0xff;
4528
4529     if(i==0) {
4530       if(flag) 
4531         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4532       else
4533         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4534       flag = 0;
4535     }
4536   }
4537
4538   return (flag==0);
4539 }
4540 #endif
4541
4542 /*-----------------------------------------------------------------*/
4543 /* genCmp :- greater or less than comparison                       */
4544 /*-----------------------------------------------------------------*/
4545 static void genCmp (operand *left,operand *right,
4546                     operand *result, iCode *ifx, int sign)
4547 {
4548   int size; //, offset = 0 ;
4549   unsigned long lit = 0L,i = 0;
4550   resolvedIfx rFalseIfx;
4551   //  resolvedIfx rTrueIfx;
4552   symbol *truelbl;
4553   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4554 /*
4555   if(ifx) {
4556     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4557     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4558   }
4559 */
4560
4561   resolveIfx(&rFalseIfx,ifx);
4562   truelbl  = newiTempLabel(NULL);
4563   size = max(AOP_SIZE(left),AOP_SIZE(right));
4564
4565   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4566
4567 #define _swapp
4568
4569   /* if literal is on the right then swap with left */
4570   if ((AOP_TYPE(right) == AOP_LIT)) {
4571     operand *tmp = right ;
4572     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4573     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4574 #ifdef _swapp
4575
4576     lit = (lit - 1) & mask;
4577     right = left;
4578     left = tmp;
4579     rFalseIfx.condition ^= 1;
4580 #endif
4581
4582   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4583     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4584   }
4585
4586
4587   //if(IC_TRUE(ifx) == NULL)
4588   /* if left & right are bit variables */
4589   if (AOP_TYPE(left) == AOP_CRY &&
4590       AOP_TYPE(right) == AOP_CRY ) {
4591     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4592     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4593   } else {
4594     /* subtract right from left if at the
4595        end the carry flag is set then we know that
4596        left is greater than right */
4597
4598     symbol *lbl  = newiTempLabel(NULL);
4599
4600 #if 0
4601         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4602                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4603 #endif
4604
4605 #ifndef _swapp
4606     if(AOP_TYPE(right) == AOP_LIT) {
4607
4608       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4609
4610       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4611
4612       /* special cases */
4613
4614       if(lit == 0) {
4615
4616         if(sign != 0) 
4617           genSkipCond(&rFalseIfx,left,size-1,7);
4618         else 
4619           /* no need to compare to 0...*/
4620           /* NOTE: this is a de-generate compare that most certainly 
4621            *       creates some dead code. */
4622           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4623
4624         if(ifx) ifx->generated = 1;
4625         return;
4626
4627       }
4628       size--;
4629
4630       if(size == 0) {
4631         //i = (lit >> (size*8)) & 0xff;
4632         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4633         
4634         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4635
4636         i = ((0-lit) & 0xff);
4637         if(sign) {
4638           if( i == 0x81) { 
4639             /* lit is 0x7f, all signed chars are less than
4640              * this except for 0x7f itself */
4641             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4642             genSkipz2(&rFalseIfx,0);
4643           } else {
4644             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4645             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4646             genSkipc(&rFalseIfx);
4647           }
4648
4649         } else {
4650           if(lit == 1) {
4651             genSkipz2(&rFalseIfx,1);
4652           } else {
4653             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4654             genSkipc(&rFalseIfx);
4655           }
4656         }
4657
4658         if(ifx) ifx->generated = 1;
4659         return;
4660       }
4661
4662       /* chars are out of the way. now do ints and longs */
4663
4664
4665       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4666         
4667       /* special cases */
4668
4669       if(sign) {
4670
4671         if(lit == 0) {
4672           genSkipCond(&rFalseIfx,left,size,7);
4673           if(ifx) ifx->generated = 1;
4674           return;
4675         }
4676
4677         if(lit <0x100) {
4678           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4679
4680           //rFalseIfx.condition ^= 1;
4681           //genSkipCond(&rFalseIfx,left,size,7);
4682           //rFalseIfx.condition ^= 1;
4683
4684           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4685           if(rFalseIfx.condition)
4686             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4687           else
4688             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4689
4690           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4691           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4692           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4693
4694           while(size > 1)
4695             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4696
4697           if(rFalseIfx.condition) {
4698             emitSKPZ;
4699             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4700
4701           } else {
4702             emitSKPNZ;
4703           }
4704
4705           genSkipc(&rFalseIfx);
4706           pic16_emitpLabel(truelbl->key);
4707           if(ifx) ifx->generated = 1;
4708           return;
4709
4710         }
4711
4712         if(size == 1) {
4713
4714           if( (lit & 0xff) == 0) {
4715             /* lower byte is zero */
4716             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4717             i = ((lit >> 8) & 0xff) ^0x80;
4718             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4719             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4720             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4721             genSkipc(&rFalseIfx);
4722
4723
4724             if(ifx) ifx->generated = 1;
4725             return;
4726
4727           }
4728         } else {
4729           /* Special cases for signed longs */
4730           if( (lit & 0xffffff) == 0) {
4731             /* lower byte is zero */
4732             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4733             i = ((lit >> 8*3) & 0xff) ^0x80;
4734             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4735             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4736             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4737             genSkipc(&rFalseIfx);
4738
4739
4740             if(ifx) ifx->generated = 1;
4741             return;
4742
4743           }
4744
4745         }
4746
4747
4748         if(lit & (0x80 << (size*8))) {
4749           /* lit is negative */
4750           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4751
4752           //genSkipCond(&rFalseIfx,left,size,7);
4753
4754           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4755
4756           if(rFalseIfx.condition)
4757             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4758           else
4759             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4760
4761
4762         } else {
4763           /* lit is positive */
4764           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4765           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4766           if(rFalseIfx.condition)
4767             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4768           else
4769             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4770
4771         }
4772
4773         /*
4774           This works, but is only good for ints.
4775           It also requires a "known zero" register.
4776           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4777           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4778           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4779           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4780           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4781           genSkipc(&rFalseIfx);
4782
4783           pic16_emitpLabel(truelbl->key);
4784           if(ifx) ifx->generated = 1;
4785           return;
4786         **/
4787           
4788         /* There are no more special cases, so perform a general compare */
4789   
4790         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4791         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4792
4793         while(size--) {
4794
4795           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4796           emitSKPNZ;
4797           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4798         }
4799         //rFalseIfx.condition ^= 1;
4800         genSkipc(&rFalseIfx);
4801
4802         pic16_emitpLabel(truelbl->key);
4803
4804         if(ifx) ifx->generated = 1;
4805         return;
4806
4807
4808       }
4809
4810
4811       /* sign is out of the way. So now do an unsigned compare */
4812       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4813
4814
4815       /* General case - compare to an unsigned literal on the right.*/
4816
4817       i = (lit >> (size*8)) & 0xff;
4818       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4819       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4820       while(size--) {
4821         i = (lit >> (size*8)) & 0xff;
4822
4823         if(i) {
4824           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4825           emitSKPNZ;
4826           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4827         } else {
4828           /* this byte of the lit is zero, 
4829            *if it's not the last then OR in the variable */
4830           if(size)
4831             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4832         }
4833       }
4834
4835
4836       pic16_emitpLabel(lbl->key);
4837 //      pic16_emitpLabel(truelbl->key);
4838       //if(emitFinalCheck)
4839       genSkipc(&rFalseIfx);
4840       if(sign)
4841         pic16_emitpLabel(truelbl->key);
4842
4843       if(ifx) ifx->generated = 1;
4844       return;
4845
4846
4847     }
4848 #endif  // _swapp
4849
4850     if(AOP_TYPE(left) == AOP_LIT) {
4851       //symbol *lbl = newiTempLabel(NULL);
4852
4853       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4854
4855
4856       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4857
4858       /* Special cases */
4859       if((lit == 0) && (sign == 0)){
4860
4861         size--;
4862         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4863         while(size) 
4864           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4865
4866         genSkipz2(&rFalseIfx,0);
4867         if(ifx) ifx->generated = 1;
4868         return;
4869       }
4870
4871       if(size==1) {
4872         /* Special cases */
4873         lit &= 0xff;
4874         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4875           /* degenerate compare can never be true */
4876           if(rFalseIfx.condition == 0)
4877             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4878
4879           if(ifx) ifx->generated = 1;
4880           return;
4881         }
4882
4883         if(sign) {
4884           /* signed comparisons to a literal byte */
4885
4886           int lp1 = (lit+1) & 0xff;
4887
4888           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4889           switch (lp1) {
4890           case 0:
4891             rFalseIfx.condition ^= 1;
4892             genSkipCond(&rFalseIfx,right,0,7);
4893             break;
4894           case 0x7f:
4895             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4896             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4897             genSkipz2(&rFalseIfx,1);
4898             break;
4899           default:
4900             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4901             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4902             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4903             rFalseIfx.condition ^= 1;
4904             genSkipc(&rFalseIfx);
4905             break;
4906           }
4907         } else {
4908           /* unsigned comparisons to a literal byte */
4909
4910           switch(lit & 0xff ) {
4911           case 0:
4912             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4913             genSkipz2(&rFalseIfx,0);
4914             break;
4915           case 0x7f:
4916             rFalseIfx.condition ^= 1;
4917             genSkipCond(&rFalseIfx,right,0,7);
4918             break;
4919
4920           default:
4921             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4922             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4923             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4924             rFalseIfx.condition ^= 1;
4925             if (AOP_TYPE(result) == AOP_CRY)
4926               genSkipc(&rFalseIfx);
4927             else {
4928               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4929               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4930             }         
4931             break;
4932           }
4933         }
4934
4935         if(ifx) ifx->generated = 1;
4936         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4937                 goto check_carry;
4938         return;
4939
4940       } else {
4941
4942         /* Size is greater than 1 */
4943
4944         if(sign) {
4945           int lp1 = lit+1;
4946
4947           size--;
4948
4949           if(lp1 == 0) {
4950             /* this means lit = 0xffffffff, or -1 */
4951
4952
4953             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4954             rFalseIfx.condition ^= 1;
4955             genSkipCond(&rFalseIfx,right,size,7);
4956             if(ifx) ifx->generated = 1;
4957             return;
4958           }
4959
4960           if(lit == 0) {
4961             int s = size;
4962
4963             if(rFalseIfx.condition) {
4964               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4965               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4966             }
4967
4968             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4969             while(size--)
4970               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4971
4972
4973             emitSKPZ;
4974             if(rFalseIfx.condition) {
4975               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4976               pic16_emitpLabel(truelbl->key);
4977             }else {
4978               rFalseIfx.condition ^= 1;
4979               genSkipCond(&rFalseIfx,right,s,7);
4980             }
4981
4982             if(ifx) ifx->generated = 1;
4983             return;
4984           }
4985
4986           if((size == 1) &&  (0 == (lp1&0xff))) {
4987             /* lower byte of signed word is zero */
4988             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4989             i = ((lp1 >> 8) & 0xff) ^0x80;
4990             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4991             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4992             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4993             rFalseIfx.condition ^= 1;
4994             genSkipc(&rFalseIfx);
4995
4996
4997             if(ifx) ifx->generated = 1;
4998             return;
4999           }
5000
5001           if(lit & (0x80 << (size*8))) {
5002             /* Lit is less than zero */
5003             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5004             //rFalseIfx.condition ^= 1;
5005             //genSkipCond(&rFalseIfx,left,size,7);
5006             //rFalseIfx.condition ^= 1;
5007             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5008             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5009
5010             if(rFalseIfx.condition)
5011               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5012             else
5013               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5014
5015
5016           } else {
5017             /* Lit is greater than or equal to zero */
5018             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5019             //rFalseIfx.condition ^= 1;
5020             //genSkipCond(&rFalseIfx,right,size,7);
5021             //rFalseIfx.condition ^= 1;
5022
5023             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5024             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5025
5026             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5027             if(rFalseIfx.condition)
5028               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5029             else
5030               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5031
5032           }
5033
5034
5035           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5036           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5037
5038           while(size--) {
5039
5040             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5041             emitSKPNZ;
5042             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5043           }
5044           rFalseIfx.condition ^= 1;
5045           //rFalseIfx.condition = 1;
5046           genSkipc(&rFalseIfx);
5047
5048           pic16_emitpLabel(truelbl->key);
5049
5050           if(ifx) ifx->generated = 1;
5051           return;
5052           // end of if (sign)
5053         } else {
5054
5055           /* compare word or long to an unsigned literal on the right.*/
5056
5057
5058           size--;
5059           if(lit < 0xff) {
5060             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5061             switch (lit) {
5062             case 0:
5063               break; /* handled above */
5064 /*
5065             case 0xff:
5066               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5067               while(size--)
5068                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5069               genSkipz2(&rFalseIfx,0);
5070               break;
5071 */
5072             default:
5073               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5074               while(--size)
5075                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5076
5077               emitSKPZ;
5078               if(rFalseIfx.condition)
5079                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5080               else
5081                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5082
5083
5084               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5085               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5086
5087               rFalseIfx.condition ^= 1;
5088               genSkipc(&rFalseIfx);
5089             }
5090
5091             pic16_emitpLabel(truelbl->key);
5092
5093             if(ifx) ifx->generated = 1;
5094             return;
5095           }
5096
5097
5098           lit++;
5099           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5100           i = (lit >> (size*8)) & 0xff;
5101
5102           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5103           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5104
5105           while(size--) {
5106             i = (lit >> (size*8)) & 0xff;
5107
5108             if(i) {
5109               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5110               emitSKPNZ;
5111               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5112             } else {
5113               /* this byte of the lit is zero, 
5114                * if it's not the last then OR in the variable */
5115               if(size)
5116                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5117             }
5118           }
5119
5120
5121           pic16_emitpLabel(lbl->key);
5122
5123           rFalseIfx.condition ^= 1;
5124
5125           genSkipc(&rFalseIfx);
5126         }
5127
5128         if(sign)
5129           pic16_emitpLabel(truelbl->key);
5130         if(ifx) ifx->generated = 1;
5131         return;
5132       }
5133     }
5134     /* Compare two variables */
5135
5136     DEBUGpic16_emitcode(";sign","%d",sign);
5137
5138     size--;
5139     if(sign) {
5140       /* Sigh. thus sucks... */
5141       if(size) {
5142         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5143         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5144         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5145         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5146         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5147         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5148       } else {
5149         /* Signed char comparison */
5150         /* Special thanks to Nikolai Golovchenko for this snippet */
5151         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5152         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5153         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5154         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5155         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5156         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5157
5158         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5159         genSkipc(&rFalseIfx);
5160           
5161         if(ifx) ifx->generated = 1;
5162         return;
5163       }
5164
5165     } else {
5166
5167       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5168       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5169     }
5170
5171
5172     /* The rest of the bytes of a multi-byte compare */
5173     while (size) {
5174
5175       emitSKPZ;
5176       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5177       size--;
5178
5179       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5180       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5181
5182
5183     }
5184
5185     pic16_emitpLabel(lbl->key);
5186
5187     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5188     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5189         (AOP_TYPE(result) == AOP_REG)) {
5190       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5191       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5192     } else {
5193       genSkipc(&rFalseIfx);
5194     }         
5195     //genSkipc(&rFalseIfx);
5196     if(ifx) ifx->generated = 1;
5197
5198     return;
5199
5200   }
5201
5202 check_carry:
5203   if ((AOP_TYPE(result) != AOP_CRY) 
5204         && AOP_SIZE(result)) {
5205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206 //    pic16_emitpLabel( rFalseIfx.lbl->key );
5207
5208     pic16_outBitC(result);
5209   } else {
5210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5211     /* if the result is used in the next
5212        ifx conditional branch then generate
5213        code a little differently */
5214     if (ifx )
5215       genIfxJump (ifx,"c");
5216     else
5217       pic16_outBitC(result);
5218     /* leave the result in acc */
5219   }
5220
5221 }
5222
5223 /*-----------------------------------------------------------------*/
5224 /* genCmpGt :- greater than comparison                             */
5225 /*-----------------------------------------------------------------*/
5226 static void genCmpGt (iCode *ic, iCode *ifx)
5227 {
5228     operand *left, *right, *result;
5229     sym_link *letype , *retype;
5230     int sign ;
5231
5232     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5233     left = IC_LEFT(ic);
5234     right= IC_RIGHT(ic);
5235     result = IC_RESULT(ic);
5236
5237     letype = getSpec(operandType(left));
5238     retype =getSpec(operandType(right));
5239     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5240     /* assign the amsops */
5241     pic16_aopOp (left,ic,FALSE);
5242     pic16_aopOp (right,ic,FALSE);
5243     pic16_aopOp (result,ic,TRUE);
5244
5245     genCmp(right, left, result, ifx, sign);
5246
5247     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5248     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5249     pic16_freeAsmop(result,NULL,ic,TRUE); 
5250 }
5251
5252 /*-----------------------------------------------------------------*/
5253 /* genCmpLt - less than comparisons                                */
5254 /*-----------------------------------------------------------------*/
5255 static void genCmpLt (iCode *ic, iCode *ifx)
5256 {
5257     operand *left, *right, *result;
5258     sym_link *letype , *retype;
5259     int sign ;
5260
5261     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5262     left = IC_LEFT(ic);
5263     right= IC_RIGHT(ic);
5264     result = IC_RESULT(ic);
5265
5266     letype = getSpec(operandType(left));
5267     retype =getSpec(operandType(right));
5268     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5269
5270     /* assign the amsops */
5271     pic16_aopOp (left,ic,FALSE);
5272     pic16_aopOp (right,ic,FALSE);
5273     pic16_aopOp (result,ic,TRUE);
5274
5275     genCmp(left, right, result, ifx, sign);
5276
5277     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5278     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5279     pic16_freeAsmop(result,NULL,ic,TRUE); 
5280 }
5281
5282 #if 0
5283 // not needed ATM
5284 // FIXME reenable literal optimisation when the pic16 port is stable
5285
5286 /*-----------------------------------------------------------------*/
5287 /* genc16bit2lit - compare a 16 bit value to a literal             */
5288 /*-----------------------------------------------------------------*/
5289 static void genc16bit2lit(operand *op, int lit, int offset)
5290 {
5291   int i;
5292
5293   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5294   if( (lit&0xff) == 0) 
5295     i=1;
5296   else
5297     i=0;
5298
5299   switch( BYTEofLONG(lit,i)) { 
5300   case 0:
5301     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5302     break;
5303   case 1:
5304     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5305     break;
5306   case 0xff:
5307     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5308     break;
5309   default:
5310     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5311     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5312   }
5313
5314   i ^= 1;
5315
5316   switch( BYTEofLONG(lit,i)) { 
5317   case 0:
5318     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5319     break;
5320   case 1:
5321     emitSKPNZ;
5322     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5323     break;
5324   case 0xff:
5325     emitSKPNZ;
5326     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5327     break;
5328   default:
5329     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5330     emitSKPNZ;
5331     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5332
5333   }
5334
5335 }
5336 #endif
5337
5338 #if 0
5339 // not needed ATM
5340 /*-----------------------------------------------------------------*/
5341 /* gencjneshort - compare and jump if not equal                    */
5342 /*-----------------------------------------------------------------*/
5343 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5344 {
5345   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5346   int offset = 0;
5347   int res_offset = 0;  /* the result may be a different size then left or right */
5348   int res_size = AOP_SIZE(result);
5349   resolvedIfx rIfx;
5350   symbol *lbl, *lbl_done;
5351
5352   unsigned long lit = 0L;
5353   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5354
5355   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5356   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5357   if(result)
5358     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5359   resolveIfx(&rIfx,ifx);
5360   lbl =  newiTempLabel(NULL);
5361   lbl_done =  newiTempLabel(NULL);
5362
5363
5364   /* if the left side is a literal or 
5365      if the right is in a pointer register and left 
5366      is not */
5367   if ((AOP_TYPE(left) == AOP_LIT) || 
5368       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5369     operand *t = right;
5370     right = left;
5371     left = t;
5372   }
5373   if(AOP_TYPE(right) == AOP_LIT)
5374     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5375
5376   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5377     preserve_result = 1;
5378
5379   if(result && !preserve_result)
5380     {
5381       int i;
5382       for(i = 0; i < AOP_SIZE(result); i++)
5383         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5384     }
5385
5386
5387   /* if the right side is a literal then anything goes */
5388   if (AOP_TYPE(right) == AOP_LIT &&
5389       AOP_TYPE(left) != AOP_DIR ) {
5390     switch(size) {
5391     case 2:
5392       genc16bit2lit(left, lit, 0);
5393       emitSKPZ;
5394       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5395       break;
5396     default:
5397       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5398       while (size--) {
5399         if(lit & 0xff) {
5400           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5401           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5402         } else {
5403           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5404         }
5405
5406         emitSKPZ;
5407         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5408         offset++;
5409         if(res_offset < res_size-1)
5410           res_offset++;
5411         lit >>= 8;
5412       }
5413       break;
5414     }
5415   }
5416
5417   /* if the right side is in a register or in direct space or
5418      if the left is a pointer register & right is not */    
5419   else if (AOP_TYPE(right) == AOP_REG ||
5420            AOP_TYPE(right) == AOP_DIR || 
5421            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5422            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5423     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5424     int lbl_key = lbl->key;
5425
5426     if(result) {
5427       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5428       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5429     }else {
5430       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5431       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5432               __FUNCTION__,__LINE__);
5433       return;
5434     }
5435    
5436 /*     switch(size) { */
5437 /*     case 2: */
5438 /*       genc16bit2lit(left, lit, 0); */
5439 /*       emitSKPNZ; */
5440 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5441 /*       break; */
5442 /*     default: */
5443     while (size--) {
5444       int emit_skip=1;
5445       if((AOP_TYPE(left) == AOP_DIR) && 
5446          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5447
5448         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5449         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5450
5451       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5452             
5453         switch (lit & 0xff) {
5454         case 0:
5455           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5456           break;
5457         case 1:
5458           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5459           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5460           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5461           emit_skip=0;
5462           break;
5463         case 0xff:
5464           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5465           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5466           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5467           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5468           emit_skip=0;
5469           break;
5470         default:
5471           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5472           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5473         }
5474         lit >>= 8;
5475
5476       } else {
5477         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5478       }
5479       if(emit_skip) {
5480         if(AOP_TYPE(result) == AOP_CRY) {
5481           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5482           if(rIfx.condition)
5483             emitSKPNZ;
5484           else
5485             emitSKPZ;
5486           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5487         } else {
5488           /* fix me. probably need to check result size too */
5489           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5490           if(rIfx.condition)
5491             emitSKPZ;
5492           else
5493             emitSKPNZ;
5494           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5495           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5496         }
5497         if(ifx)
5498           ifx->generated=1;
5499       }
5500       emit_skip++;
5501       offset++;
5502       if(res_offset < res_size-1)
5503         res_offset++;
5504     }
5505 /*       break; */
5506 /*     } */
5507   } else if(AOP_TYPE(right) == AOP_REG &&
5508             AOP_TYPE(left) != AOP_DIR){
5509
5510     while(size--) {
5511       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5512       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5513       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5514       if(rIfx.condition)
5515         emitSKPNZ;
5516       else
5517         emitSKPZ;
5518       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5519       offset++;
5520       if(res_offset < res_size-1)
5521         res_offset++;
5522     }
5523       
5524   }else{
5525     /* right is a pointer reg need both a & b */
5526     while(size--) {
5527       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5528       if(strcmp(l,"b"))
5529         pic16_emitcode("mov","b,%s",l);
5530       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5531       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5532       offset++;
5533     }
5534   }
5535
5536   if(result && preserve_result)
5537     {
5538       int i;
5539       for(i = 0; i < AOP_SIZE(result); i++)
5540         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5541     }
5542
5543   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5544
5545   if(result && preserve_result)
5546     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5547
5548   if(!rIfx.condition)
5549     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5550
5551   pic16_emitpLabel(lbl->key);
5552
5553   if(result && preserve_result)
5554     {
5555       int i;
5556       for(i = 0; i < AOP_SIZE(result); i++)
5557         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5558
5559       pic16_emitpLabel(lbl_done->key);
5560    }
5561
5562   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5563
5564   if(ifx)
5565     ifx->generated = 1;
5566 }
5567 #endif
5568
5569 #if 0
5570 /*-----------------------------------------------------------------*/
5571 /* gencjne - compare and jump if not equal                         */
5572 /*-----------------------------------------------------------------*/
5573 static void gencjne(operand *left, operand *right, iCode *ifx)
5574 {
5575     symbol *tlbl  = newiTempLabel(NULL);
5576
5577     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5578     gencjneshort(left, right, lbl);
5579
5580     pic16_emitcode("mov","a,%s",one);
5581     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5582     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5583     pic16_emitcode("clr","a");
5584     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5585
5586     pic16_emitpLabel(lbl->key);
5587     pic16_emitpLabel(tlbl->key);
5588
5589 }
5590 #endif
5591
5592
5593 /*-----------------------------------------------------------------*/
5594 /* is_LitOp - check if operand has to be treated as literal        */
5595 /*-----------------------------------------------------------------*/
5596 static bool is_LitOp(operand *op)
5597 {
5598   return (AOP_TYPE(op) == AOP_LIT)
5599       || ( (AOP_TYPE(op) == AOP_PCODE)
5600           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5601               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5602 }
5603
5604 /*-----------------------------------------------------------------*/
5605 /* is_LitAOp - check if operand has to be treated as literal        */
5606 /*-----------------------------------------------------------------*/
5607 static bool is_LitAOp(asmop *aop)
5608 {
5609   return (aop->type == AOP_LIT)
5610       || ( (aop->type == AOP_PCODE)
5611           && ( (aop->aopu.pcop->type == PO_LITERAL)
5612               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5613 }
5614
5615
5616
5617 /*-----------------------------------------------------------------*/
5618 /* genCmpEq - generates code for equal to                          */
5619 /*-----------------------------------------------------------------*/
5620 static void genCmpEq (iCode *ic, iCode *ifx)
5621 {
5622   operand *left, *right, *result;
5623   symbol *falselbl = newiTempLabel(NULL);
5624   symbol *donelbl = newiTempLabel(NULL);
5625
5626   int preserve_result = 0;
5627   int generate_result = 0;
5628   int i=0;
5629
5630   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5631   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5632   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5633  
5634   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5635   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5636
5637   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5638     {
5639       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5640       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5641       goto release;
5642     }
5643
5644   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5645     {
5646       operand *tmp = right ;
5647       right = left;
5648       left = tmp;
5649     }
5650
5651   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5652     preserve_result = 1;
5653
5654   if(result && AOP_SIZE(result))
5655     generate_result = 1;
5656
5657   if(generate_result && !preserve_result)
5658     {
5659       for(i = 0; i < AOP_SIZE(result); i++)
5660         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5661     }
5662
5663   for(i=0; i < AOP_SIZE(left); i++)
5664     {
5665       if(AOP_TYPE(left) != AOP_ACC)
5666         {
5667           if(is_LitOp(left))
5668             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5669           else
5670             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5671         }
5672       if(is_LitOp(right))
5673         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5674       else
5675         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5676
5677       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5678     }
5679
5680   // result == true
5681
5682   if(generate_result && preserve_result)
5683     {
5684       for(i = 0; i < AOP_SIZE(result); i++)
5685         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5686     }
5687
5688   if(generate_result)
5689     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5690
5691   if(generate_result && preserve_result)
5692     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5693
5694   if(ifx && IC_TRUE(ifx))
5695     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5696
5697   if(ifx && IC_FALSE(ifx))
5698     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5699
5700   pic16_emitpLabel(falselbl->key);
5701
5702   // result == false
5703
5704   if(ifx && IC_FALSE(ifx))
5705     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5706
5707   if(generate_result && preserve_result)
5708     {
5709       for(i = 0; i < AOP_SIZE(result); i++)
5710         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5711     }
5712
5713   pic16_emitpLabel(donelbl->key);
5714
5715   if(ifx)
5716     ifx->generated = 1;
5717
5718 release:
5719   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5720   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5721   pic16_freeAsmop(result,NULL,ic,TRUE);
5722
5723 }
5724
5725
5726 #if 0
5727 // old version kept for reference
5728
5729 /*-----------------------------------------------------------------*/
5730 /* genCmpEq - generates code for equal to                          */
5731 /*-----------------------------------------------------------------*/
5732 static void genCmpEq (iCode *ic, iCode *ifx)
5733 {
5734     operand *left, *right, *result;
5735     unsigned long lit = 0L;
5736     int size,offset=0;
5737     symbol *falselbl  = newiTempLabel(NULL);
5738
5739
5740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5741
5742     if(ifx)
5743       DEBUGpic16_emitcode ("; ifx is non-null","");
5744     else
5745       DEBUGpic16_emitcode ("; ifx is null","");
5746
5747     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5748     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5749     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5750
5751     size = max(AOP_SIZE(left),AOP_SIZE(right));
5752
5753     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5754
5755     /* if literal, literal on the right or 
5756     if the right is in a pointer register and left 
5757     is not */
5758     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5759         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5760       operand *tmp = right ;
5761       right = left;
5762       left = tmp;
5763     }
5764
5765
5766     if(ifx && !AOP_SIZE(result)){
5767         symbol *tlbl;
5768         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5769         /* if they are both bit variables */
5770         if (AOP_TYPE(left) == AOP_CRY &&
5771             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5772                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5773             if(AOP_TYPE(right) == AOP_LIT){
5774                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5775                 if(lit == 0L){
5776                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5777                     pic16_emitcode("cpl","c");
5778                 } else if(lit == 1L) {
5779                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5780                 } else {
5781                     pic16_emitcode("clr","c");
5782                 }
5783                 /* AOP_TYPE(right) == AOP_CRY */
5784             } else {
5785                 symbol *lbl = newiTempLabel(NULL);
5786                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5787                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5788                 pic16_emitcode("cpl","c");
5789                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5790             }
5791             /* if true label then we jump if condition
5792             supplied is true */
5793             tlbl = newiTempLabel(NULL);
5794             if ( IC_TRUE(ifx) ) {
5795                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5796                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5797             } else {
5798                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5799                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5800             }
5801             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5802
5803                 {
5804                 /* left and right are both bit variables, result is carry */
5805                         resolvedIfx rIfx;
5806               
5807                         resolveIfx(&rIfx,ifx);
5808
5809                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5810                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5811                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5812                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5813                         genSkipz2(&rIfx,0);
5814                 }
5815         } else {
5816
5817                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5818
5819                         /* They're not both bit variables. Is the right a literal? */
5820                         if(AOP_TYPE(right) == AOP_LIT) {
5821                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5822             
5823                         switch(size) {
5824
5825                                 case 1:
5826                                         switch(lit & 0xff) {
5827                                                 case 1:
5828                                                                 if ( IC_TRUE(ifx) ) {
5829                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5830                                                                         emitSKPNZ;
5831                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5832                                                                 } else {
5833                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5834                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5835                                                                 }
5836                                                                 break;
5837                                                 case 0xff:
5838                                                                 if ( IC_TRUE(ifx) ) {
5839                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5840                                                                         emitSKPNZ;
5841                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5842                                                                 } else {
5843                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5844                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5845                                                                 }
5846                                                                 break;
5847                                                 default:
5848                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5849                                                                 if(lit)
5850                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5851                                                                 genSkip(ifx,'z');
5852                                         } // switch lit
5853
5854
5855                                         /* end of size == 1 */
5856                                         break;
5857               
5858                                 case 2:
5859                                         genc16bit2lit(left,lit,offset);
5860                                         genSkip(ifx,'z');
5861                                         break;
5862                                         /* end of size == 2 */
5863
5864                                 default:
5865                                         /* size is 4 */
5866                                         if(lit==0) {
5867                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5868                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5869                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5870                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5871                                                 genSkip(ifx,'z');
5872                                         } else {
5873                                                 /* search for patterns that can be optimized */
5874
5875                                                 genc16bit2lit(left,lit,0);
5876                                                 lit >>= 16;
5877                                                 if(lit) {
5878                                                                 if(IC_TRUE(ifx))
5879                                                                 emitSKPZ; // if hi word unequal
5880                                                                 else
5881                                                                 emitSKPNZ; // if hi word equal
5882                                                                 // fail early
5883                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5884                                                         genc16bit2lit(left,lit,2);
5885                                                         genSkip(ifx,'z');
5886                                                 } else {
5887                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5888                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5889                                                         genSkip(ifx,'z');
5890                                                 }
5891                                         }
5892                                                 pic16_emitpLabel(falselbl->key);
5893                                                 break;
5894
5895                         } // switch size
5896           
5897                         ifx->generated = 1;
5898                         goto release ;
5899             
5900
5901           } else if(AOP_TYPE(right) == AOP_CRY ) {
5902             /* we know the left is not a bit, but that the right is */
5903             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5904             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5905                       pic16_popGet(AOP(right),offset));
5906             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5907
5908             /* if the two are equal, then W will be 0 and the Z bit is set
5909              * we could test Z now, or go ahead and check the high order bytes if
5910              * the variable we're comparing is larger than a byte. */
5911
5912             while(--size)
5913               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5914
5915             if ( IC_TRUE(ifx) ) {
5916               emitSKPNZ;
5917               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5918               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5919             } else {
5920               emitSKPZ;
5921               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5922               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5923             }
5924
5925           } else {
5926             /* They're both variables that are larger than bits */
5927             int s = size;
5928
5929             tlbl = newiTempLabel(NULL);
5930
5931             while(size--) {
5932               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5933               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5934
5935               if ( IC_TRUE(ifx) ) {
5936                 if(size) {
5937                   emitSKPZ;
5938                 
5939                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5940
5941                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5942                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5943                 } else {
5944                   emitSKPNZ;
5945
5946                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5947
5948
5949                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5950                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5951                 }
5952               } else {
5953                 emitSKPZ;
5954
5955                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5956
5957                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5958                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5959               }
5960               offset++;
5961             }
5962             if(s>1 && IC_TRUE(ifx)) {
5963               pic16_emitpLabel(tlbl->key);
5964               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5965             }
5966           }
5967         }
5968         /* mark the icode as generated */
5969         ifx->generated = 1;
5970         goto release ;
5971     }
5972
5973     /* if they are both bit variables */
5974     if (AOP_TYPE(left) == AOP_CRY &&
5975         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5976         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5977         if(AOP_TYPE(right) == AOP_LIT){
5978             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5979             if(lit == 0L){
5980                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5981                 pic16_emitcode("cpl","c");
5982             } else if(lit == 1L) {
5983                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5984             } else {
5985                 pic16_emitcode("clr","c");
5986             }
5987             /* AOP_TYPE(right) == AOP_CRY */
5988         } else {
5989             symbol *lbl = newiTempLabel(NULL);
5990             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5991             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5992             pic16_emitcode("cpl","c");
5993             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5994         }
5995         /* c = 1 if egal */
5996         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5997             pic16_outBitC(result);
5998             goto release ;
5999         }
6000         if (ifx) {
6001             genIfxJump (ifx,"c");
6002             goto release ;
6003         }
6004         /* if the result is used in an arithmetic operation
6005         then put the result in place */
6006         pic16_outBitC(result);
6007     } else {
6008       
6009       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6010       gencjne(left,right,result,ifx);
6011 /*
6012       if(ifx) 
6013         gencjne(left,right,newiTempLabel(NULL));
6014       else {
6015         if(IC_TRUE(ifx)->key)
6016           gencjne(left,right,IC_TRUE(ifx)->key);
6017         else
6018           gencjne(left,right,IC_FALSE(ifx)->key);
6019         ifx->generated = 1;
6020         goto release ;
6021       }
6022       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6023         pic16_aopPut(AOP(result),"a",0);
6024         goto release ;
6025       }
6026
6027       if (ifx) {
6028         genIfxJump (ifx,"a");
6029         goto release ;
6030       }
6031 */
6032       /* if the result is used in an arithmetic operation
6033          then put the result in place */
6034 /*
6035       if (AOP_TYPE(result) != AOP_CRY) 
6036         pic16_outAcc(result);
6037 */
6038       /* leave the result in acc */
6039     }
6040
6041 release:
6042     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6043     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6044     pic16_freeAsmop(result,NULL,ic,TRUE);
6045 }
6046 #endif
6047
6048 /*-----------------------------------------------------------------*/
6049 /* ifxForOp - returns the icode containing the ifx for operand     */
6050 /*-----------------------------------------------------------------*/
6051 static iCode *ifxForOp ( operand *op, iCode *ic )
6052 {
6053     /* if true symbol then needs to be assigned */
6054     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6055     if (IS_TRUE_SYMOP(op))
6056         return NULL ;
6057
6058     /* if this has register type condition and
6059     the next instruction is ifx with the same operand
6060     and live to of the operand is upto the ifx only then */
6061     if (ic->next
6062         && ic->next->op == IFX
6063         && IC_COND(ic->next)->key == op->key
6064         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6065         ) {
6066                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6067           return ic->next;
6068     }
6069
6070     if (ic->next &&
6071         ic->next->op == IFX &&
6072         IC_COND(ic->next)->key == op->key) {
6073       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6074       return ic->next;
6075     }
6076
6077     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6078     if (ic->next &&
6079         ic->next->op == IFX)
6080       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6081
6082     if (ic->next &&
6083         ic->next->op == IFX &&
6084         IC_COND(ic->next)->key == op->key) {
6085       DEBUGpic16_emitcode ("; "," key is okay");
6086       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6087                            OP_SYMBOL(op)->liveTo,
6088                            ic->next->seq);
6089     }
6090
6091 #if 0
6092     /* the code below is completely untested
6093      * it just allows ulong2fs.c compile -- VR */
6094          
6095     ic = ic->next;
6096     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6097                                         __FILE__, __FUNCTION__, __LINE__);
6098         
6099     /* if this has register type condition and
6100     the next instruction is ifx with the same operand
6101     and live to of the operand is upto the ifx only then */
6102     if (ic->next &&
6103         ic->next->op == IFX &&
6104         IC_COND(ic->next)->key == op->key &&
6105         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6106         return ic->next;
6107
6108     if (ic->next &&
6109         ic->next->op == IFX &&
6110         IC_COND(ic->next)->key == op->key) {
6111       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6112       return ic->next;
6113     }
6114
6115     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6116                                         __FILE__, __FUNCTION__, __LINE__);
6117
6118 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6119 #endif
6120
6121     return NULL;
6122 }
6123 /*-----------------------------------------------------------------*/
6124 /* genAndOp - for && operation                                     */
6125 /*-----------------------------------------------------------------*/
6126 static void genAndOp (iCode *ic)
6127 {
6128     operand *left,*right, *result;
6129 /*     symbol *tlbl; */
6130
6131     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6132     /* note here that && operations that are in an
6133     if statement are taken away by backPatchLabels
6134     only those used in arthmetic operations remain */
6135     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6136     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6137     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6138
6139     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6140
6141     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6142     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6143     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6144
6145     /* if both are bit variables */
6146 /*     if (AOP_TYPE(left) == AOP_CRY && */
6147 /*         AOP_TYPE(right) == AOP_CRY ) { */
6148 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6149 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6150 /*         pic16_outBitC(result); */
6151 /*     } else { */
6152 /*         tlbl = newiTempLabel(NULL); */
6153 /*         pic16_toBoolean(left);     */
6154 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6155 /*         pic16_toBoolean(right); */
6156 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6157 /*         pic16_outBitAcc(result); */
6158 /*     } */
6159
6160     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6161     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6162     pic16_freeAsmop(result,NULL,ic,TRUE);
6163 }
6164
6165
6166 /*-----------------------------------------------------------------*/
6167 /* genOrOp - for || operation                                      */
6168 /*-----------------------------------------------------------------*/
6169 /*
6170   tsd pic port -
6171   modified this code, but it doesn't appear to ever get called
6172 */
6173
6174 static void genOrOp (iCode *ic)
6175 {
6176     operand *left,*right, *result;
6177     symbol *tlbl;
6178
6179     /* note here that || operations that are in an
6180     if statement are taken away by backPatchLabels
6181     only those used in arthmetic operations remain */
6182     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6183     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6184     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6185     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6186
6187     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6188
6189     /* if both are bit variables */
6190     if (AOP_TYPE(left) == AOP_CRY &&
6191         AOP_TYPE(right) == AOP_CRY ) {
6192       pic16_emitcode("clrc","");
6193       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6194                AOP(left)->aopu.aop_dir,
6195                AOP(left)->aopu.aop_dir);
6196       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6197                AOP(right)->aopu.aop_dir,
6198                AOP(right)->aopu.aop_dir);
6199       pic16_emitcode("setc","");
6200
6201     } else {
6202         tlbl = newiTempLabel(NULL);
6203         pic16_toBoolean(left);
6204         emitSKPZ;
6205         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6206         pic16_toBoolean(right);
6207         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6208
6209         pic16_outBitAcc(result);
6210     }
6211
6212     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6213     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6214     pic16_freeAsmop(result,NULL,ic,TRUE);            
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* isLiteralBit - test if lit == 2^n                               */
6219 /*-----------------------------------------------------------------*/
6220 static int isLiteralBit(unsigned long lit)
6221 {
6222     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6223     0x100L,0x200L,0x400L,0x800L,
6224     0x1000L,0x2000L,0x4000L,0x8000L,
6225     0x10000L,0x20000L,0x40000L,0x80000L,
6226     0x100000L,0x200000L,0x400000L,0x800000L,
6227     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6228     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6229     int idx;
6230     
6231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6232     for(idx = 0; idx < 32; idx++)
6233         if(lit == pw[idx])
6234             return idx+1;
6235     return 0;
6236 }
6237
6238 /*-----------------------------------------------------------------*/
6239 /* continueIfTrue -                                                */
6240 /*-----------------------------------------------------------------*/
6241 static void continueIfTrue (iCode *ic)
6242 {
6243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6244     if(IC_TRUE(ic))
6245         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6246     ic->generated = 1;
6247 }
6248
6249 /*-----------------------------------------------------------------*/
6250 /* jmpIfTrue -                                                     */
6251 /*-----------------------------------------------------------------*/
6252 static void jumpIfTrue (iCode *ic)
6253 {
6254     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6255     if(!IC_TRUE(ic))
6256         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6257     ic->generated = 1;
6258 }
6259
6260 /*-----------------------------------------------------------------*/
6261 /* jmpTrueOrFalse -                                                */
6262 /*-----------------------------------------------------------------*/
6263 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6264 {
6265     // ugly but optimized by peephole
6266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6267     if(IC_TRUE(ic)){
6268         symbol *nlbl = newiTempLabel(NULL);
6269         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6270         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6271         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6272         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6273     }
6274     else{
6275         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6276         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6277     }
6278     ic->generated = 1;
6279 }
6280
6281 /*-----------------------------------------------------------------*/
6282 /* genAnd  - code for and                                          */
6283 /*-----------------------------------------------------------------*/
6284 static void genAnd (iCode *ic, iCode *ifx)
6285 {
6286   operand *left, *right, *result;
6287   int size, offset=0;  
6288   unsigned long lit = 0L;
6289   int bytelit = 0;
6290   resolvedIfx rIfx;
6291
6292
6293   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6294   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6295   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6296   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6297
6298   resolveIfx(&rIfx,ifx);
6299
6300   /* if left is a literal & right is not then exchange them */
6301   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6302       AOP_NEEDSACC(left)) {
6303     operand *tmp = right ;
6304     right = left;
6305     left = tmp;
6306   }
6307
6308   /* if result = right then exchange them */
6309   if(pic16_sameRegs(AOP(result),AOP(right))){
6310     operand *tmp = right ;
6311     right = left;
6312     left = tmp;
6313   }
6314
6315   /* if right is bit then exchange them */
6316   if (AOP_TYPE(right) == AOP_CRY &&
6317       AOP_TYPE(left) != AOP_CRY){
6318     operand *tmp = right ;
6319     right = left;
6320     left = tmp;
6321   }
6322   if(AOP_TYPE(right) == AOP_LIT)
6323     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6324
6325   size = AOP_SIZE(result);
6326
6327   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6328
6329   // if(bit & yy)
6330   // result = bit & yy;
6331   if (AOP_TYPE(left) == AOP_CRY){
6332     // c = bit & literal;
6333     if(AOP_TYPE(right) == AOP_LIT){
6334       if(lit & 1) {
6335         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6336           // no change
6337           goto release;
6338         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6339       } else {
6340         // bit(result) = 0;
6341         if(size && (AOP_TYPE(result) == AOP_CRY)){
6342           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6343           goto release;
6344         }
6345         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6346           jumpIfTrue(ifx);
6347           goto release;
6348         }
6349         pic16_emitcode("clr","c");
6350       }
6351     } else {
6352       if (AOP_TYPE(right) == AOP_CRY){
6353         // c = bit & bit;
6354         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6355         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6356       } else {
6357         // c = bit & val;
6358         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6359         // c = lsb
6360         pic16_emitcode("rrc","a");
6361         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6362       }
6363     }
6364     // bit = c
6365     // val = c
6366     if(size)
6367       pic16_outBitC(result);
6368     // if(bit & ...)
6369     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6370       genIfxJump(ifx, "c");           
6371     goto release ;
6372   }
6373
6374   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6375   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6376   if((AOP_TYPE(right) == AOP_LIT) &&
6377      (AOP_TYPE(result) == AOP_CRY) &&
6378      (AOP_TYPE(left) != AOP_CRY)){
6379     int posbit = isLiteralBit(lit);
6380     /* left &  2^n */
6381     if(posbit){
6382       posbit--;
6383       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6384       // bit = left & 2^n
6385       if(size)
6386         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6387       // if(left &  2^n)
6388       else{
6389         if(ifx){
6390 /*
6391           if(IC_TRUE(ifx)) {
6392             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6393             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6394           } else {
6395             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6396             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6397           }
6398 */
6399         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6400         size = AOP_SIZE(left);
6401
6402         {
6403           int bp = posbit, ofs=0;
6404           
6405             while(bp > 7) {
6406               bp -= 8;
6407               ofs++;
6408             }
6409         
6410           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6411                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6412
6413         }
6414 /*
6415           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6416                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6417 */
6418           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6419           
6420           ifx->generated = 1;
6421         }
6422         goto release;
6423       }
6424     } else {
6425       symbol *tlbl = newiTempLabel(NULL);
6426       int sizel = AOP_SIZE(left);
6427       if(size)
6428         pic16_emitcode("setb","c");
6429       while(sizel--){
6430         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6431           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6432           // byte ==  2^n ?
6433           if((posbit = isLiteralBit(bytelit)) != 0)
6434             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6435           else{
6436             if(bytelit != 0x0FFL)
6437               pic16_emitcode("anl","a,%s",
6438                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6439             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6440           }
6441         }
6442         offset++;
6443       }
6444       // bit = left & literal
6445       if(size){
6446         pic16_emitcode("clr","c");
6447         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6448       }
6449       // if(left & literal)
6450       else{
6451         if(ifx)
6452           jmpTrueOrFalse(ifx, tlbl);
6453         goto release ;
6454       }
6455     }
6456     pic16_outBitC(result);
6457     goto release ;
6458   }
6459
6460   /* if left is same as result */
6461   if(pic16_sameRegs(AOP(result),AOP(left))){
6462     int know_W = -1;
6463     for(;size--; offset++,lit>>=8) {
6464       if(AOP_TYPE(right) == AOP_LIT){
6465         switch(lit & 0xff) {
6466         case 0x00:
6467           /*  and'ing with 0 has clears the result */
6468 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6469           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6470           break;
6471         case 0xff:
6472           /* and'ing with 0xff is a nop when the result and left are the same */
6473           break;
6474
6475         default:
6476           {
6477             int p = my_powof2( (~lit) & 0xff );
6478             if(p>=0) {
6479               /* only one bit is set in the literal, so use a bcf instruction */
6480 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6481               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6482
6483             } else {
6484               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6485               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6486               if(know_W != (lit&0xff))
6487                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6488               know_W = lit &0xff;
6489               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6490             }
6491           }    
6492         }
6493       } else {
6494         if (AOP_TYPE(left) == AOP_ACC) {
6495           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6496         } else {                    
6497           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6498           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6499
6500         }
6501       }
6502     }
6503
6504   } else {
6505     // left & result in different registers
6506     if(AOP_TYPE(result) == AOP_CRY){
6507       // result = bit
6508       // if(size), result in bit
6509       // if(!size && ifx), conditional oper: if(left & right)
6510       symbol *tlbl = newiTempLabel(NULL);
6511       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6512       if(size)
6513         pic16_emitcode("setb","c");
6514       while(sizer--){
6515         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6516         pic16_emitcode("anl","a,%s",
6517                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6518         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6519         offset++;
6520       }
6521       if(size){
6522         CLRC;
6523         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6524         pic16_outBitC(result);
6525       } else if(ifx)
6526         jmpTrueOrFalse(ifx, tlbl);
6527     } else {
6528       for(;(size--);offset++) {
6529         // normal case
6530         // result = left & right
6531         if(AOP_TYPE(right) == AOP_LIT){
6532           int t = (lit >> (offset*8)) & 0x0FFL;
6533           switch(t) { 
6534           case 0x00:
6535             pic16_emitcode("clrf","%s",
6536                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6537             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6538             break;
6539           case 0xff:
6540             pic16_emitcode("movf","%s,w",
6541                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6542             pic16_emitcode("movwf","%s",
6543                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6544             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6545             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6546             break;
6547           default:
6548             pic16_emitcode("movlw","0x%x",t);
6549             pic16_emitcode("andwf","%s,w",
6550                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6551             pic16_emitcode("movwf","%s",
6552                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6553               
6554             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6555             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6556             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6557           }
6558           continue;
6559         }
6560
6561         if (AOP_TYPE(left) == AOP_ACC) {
6562           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6563           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6564         } else {
6565           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6566           pic16_emitcode("andwf","%s,w",
6567                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6568           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6569           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6570         }
6571         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6572         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6573       }
6574     }
6575   }
6576
6577   release :
6578     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6579   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580   pic16_freeAsmop(result,NULL,ic,TRUE);     
6581 }
6582
6583 /*-----------------------------------------------------------------*/
6584 /* genOr  - code for or                                            */
6585 /*-----------------------------------------------------------------*/
6586 static void genOr (iCode *ic, iCode *ifx)
6587 {
6588     operand *left, *right, *result;
6589     int size, offset=0;
6590     unsigned long lit = 0L;
6591
6592     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6593
6594     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6595     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6596     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6597
6598     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6599
6600     /* if left is a literal & right is not then exchange them */
6601     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6602         AOP_NEEDSACC(left)) {
6603         operand *tmp = right ;
6604         right = left;
6605         left = tmp;
6606     }
6607
6608     /* if result = right then exchange them */
6609     if(pic16_sameRegs(AOP(result),AOP(right))){
6610         operand *tmp = right ;
6611         right = left;
6612         left = tmp;
6613     }
6614
6615     /* if right is bit then exchange them */
6616     if (AOP_TYPE(right) == AOP_CRY &&
6617         AOP_TYPE(left) != AOP_CRY){
6618         operand *tmp = right ;
6619         right = left;
6620         left = tmp;
6621     }
6622
6623     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6624
6625     if(AOP_TYPE(right) == AOP_LIT)
6626         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6627
6628     size = AOP_SIZE(result);
6629
6630     // if(bit | yy)
6631     // xx = bit | yy;
6632     if (AOP_TYPE(left) == AOP_CRY){
6633         if(AOP_TYPE(right) == AOP_LIT){
6634             // c = bit & literal;
6635             if(lit){
6636                 // lit != 0 => result = 1
6637                 if(AOP_TYPE(result) == AOP_CRY){
6638                   if(size)
6639                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6640                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6641                   //     AOP(result)->aopu.aop_dir,
6642                   //     AOP(result)->aopu.aop_dir);
6643                     else if(ifx)
6644                         continueIfTrue(ifx);
6645                     goto release;
6646                 }
6647             } else {
6648                 // lit == 0 => result = left
6649                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6650                     goto release;
6651                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6652             }
6653         } else {
6654             if (AOP_TYPE(right) == AOP_CRY){
6655               if(pic16_sameRegs(AOP(result),AOP(left))){
6656                 // c = bit | bit;
6657                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6658                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6659                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6660
6661                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6662                          AOP(result)->aopu.aop_dir,
6663                          AOP(result)->aopu.aop_dir);
6664                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6665                          AOP(right)->aopu.aop_dir,
6666                          AOP(right)->aopu.aop_dir);
6667                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6668                          AOP(result)->aopu.aop_dir,
6669                          AOP(result)->aopu.aop_dir);
6670               } else {
6671                 if( AOP_TYPE(result) == AOP_ACC) {
6672                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6673                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6674                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6675                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6676
6677                 } else {
6678
6679                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6680                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6681                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6682                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6683
6684                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6685                                  AOP(result)->aopu.aop_dir,
6686                                  AOP(result)->aopu.aop_dir);
6687                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6688                                  AOP(right)->aopu.aop_dir,
6689                                  AOP(right)->aopu.aop_dir);
6690                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6691                                  AOP(left)->aopu.aop_dir,
6692                                  AOP(left)->aopu.aop_dir);
6693                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6694                                  AOP(result)->aopu.aop_dir,
6695                                  AOP(result)->aopu.aop_dir);
6696                 }
6697               }
6698             } else {
6699                 // c = bit | val;
6700                 symbol *tlbl = newiTempLabel(NULL);
6701                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6702
6703
6704                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6705                 if( AOP_TYPE(right) == AOP_ACC) {
6706                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6707                   emitSKPNZ;
6708                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6709                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6710                 }
6711
6712
6713
6714                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6715                     pic16_emitcode(";XXX setb","c");
6716                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6717                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6718                 pic16_toBoolean(right);
6719                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6720                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6721                     jmpTrueOrFalse(ifx, tlbl);
6722                     goto release;
6723                 } else {
6724                     CLRC;
6725                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6726                 }
6727             }
6728         }
6729         // bit = c
6730         // val = c
6731         if(size)
6732             pic16_outBitC(result);
6733         // if(bit | ...)
6734         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6735             genIfxJump(ifx, "c");           
6736         goto release ;
6737     }
6738
6739     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6740     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6741     if((AOP_TYPE(right) == AOP_LIT) &&
6742        (AOP_TYPE(result) == AOP_CRY) &&
6743        (AOP_TYPE(left) != AOP_CRY)){
6744         if(lit){
6745           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6746             // result = 1
6747             if(size)
6748                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6749             else 
6750                 continueIfTrue(ifx);
6751             goto release;
6752         } else {
6753           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6754             // lit = 0, result = boolean(left)
6755             if(size)
6756                 pic16_emitcode(";XXX setb","c");
6757             pic16_toBoolean(right);
6758             if(size){
6759                 symbol *tlbl = newiTempLabel(NULL);
6760                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6761                 CLRC;
6762                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6763             } else {
6764                 genIfxJump (ifx,"a");
6765                 goto release;
6766             }
6767         }
6768         pic16_outBitC(result);
6769         goto release ;
6770     }
6771
6772     /* if left is same as result */
6773     if(pic16_sameRegs(AOP(result),AOP(left))){
6774       int know_W = -1;
6775       for(;size--; offset++,lit>>=8) {
6776         if(AOP_TYPE(right) == AOP_LIT){
6777           if((lit & 0xff) == 0)
6778             /*  or'ing with 0 has no effect */
6779             continue;
6780           else {
6781             int p = my_powof2(lit & 0xff);
6782             if(p>=0) {
6783               /* only one bit is set in the literal, so use a bsf instruction */
6784               pic16_emitpcode(POC_BSF,
6785                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6786             } else {
6787               if(know_W != (lit & 0xff))
6788                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6789               know_W = lit & 0xff;
6790               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6791             }
6792                     
6793           }
6794         } else {
6795           if (AOP_TYPE(left) == AOP_ACC) {
6796             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6797             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6798           } else {                  
6799             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6800             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6801
6802             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6803             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6804
6805           }
6806         }
6807       }
6808     } else {
6809         // left & result in different registers
6810         if(AOP_TYPE(result) == AOP_CRY){
6811             // result = bit
6812             // if(size), result in bit
6813             // if(!size && ifx), conditional oper: if(left | right)
6814             symbol *tlbl = newiTempLabel(NULL);
6815             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6816             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6817
6818
6819             if(size)
6820                 pic16_emitcode(";XXX setb","c");
6821             while(sizer--){
6822                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6823                 pic16_emitcode(";XXX orl","a,%s",
6824                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6825                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6826                 offset++;
6827             }
6828             if(size){
6829                 CLRC;
6830                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6831                 pic16_outBitC(result);
6832             } else if(ifx)
6833                 jmpTrueOrFalse(ifx, tlbl);
6834         } else for(;(size--);offset++){
6835           // normal case
6836           // result = left & right
6837           if(AOP_TYPE(right) == AOP_LIT){
6838             int t = (lit >> (offset*8)) & 0x0FFL;
6839             switch(t) { 
6840             case 0x00:
6841               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6842               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6843
6844               pic16_emitcode("movf","%s,w",
6845                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6846               pic16_emitcode("movwf","%s",
6847                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6848               break;
6849             default:
6850               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6851               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6852               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6853
6854               pic16_emitcode("movlw","0x%x",t);
6855               pic16_emitcode("iorwf","%s,w",
6856                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6857               pic16_emitcode("movwf","%s",
6858                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6859               
6860             }
6861             continue;
6862           }
6863
6864           // faster than result <- left, anl result,right
6865           // and better if result is SFR
6866           if (AOP_TYPE(left) == AOP_ACC) {
6867             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6868             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6869           } else {
6870             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6871             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6872
6873             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6874             pic16_emitcode("iorwf","%s,w",
6875                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6876           }
6877           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6878           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6879         }
6880     }
6881
6882 release :
6883     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6884     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6885     pic16_freeAsmop(result,NULL,ic,TRUE);     
6886 }
6887
6888 /*-----------------------------------------------------------------*/
6889 /* genXor - code for xclusive or                                   */
6890 /*-----------------------------------------------------------------*/
6891 static void genXor (iCode *ic, iCode *ifx)
6892 {
6893   operand *left, *right, *result;
6894   int size, offset=0;
6895   unsigned long lit = 0L;
6896
6897   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6898
6899   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6900   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6901   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6902
6903   /* if left is a literal & right is not ||
6904      if left needs acc & right does not */
6905   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6906       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6907     operand *tmp = right ;
6908     right = left;
6909     left = tmp;
6910   }
6911
6912   /* if result = right then exchange them */
6913   if(pic16_sameRegs(AOP(result),AOP(right))){
6914     operand *tmp = right ;
6915     right = left;
6916     left = tmp;
6917   }
6918
6919   /* if right is bit then exchange them */
6920   if (AOP_TYPE(right) == AOP_CRY &&
6921       AOP_TYPE(left) != AOP_CRY){
6922     operand *tmp = right ;
6923     right = left;
6924     left = tmp;
6925   }
6926   if(AOP_TYPE(right) == AOP_LIT)
6927     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6928
6929   size = AOP_SIZE(result);
6930
6931   // if(bit ^ yy)
6932   // xx = bit ^ yy;
6933   if (AOP_TYPE(left) == AOP_CRY){
6934     if(AOP_TYPE(right) == AOP_LIT){
6935       // c = bit & literal;
6936       if(lit>>1){
6937         // lit>>1  != 0 => result = 1
6938         if(AOP_TYPE(result) == AOP_CRY){
6939           if(size)
6940             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6941             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6942           else if(ifx)
6943             continueIfTrue(ifx);
6944           goto release;
6945         }
6946         pic16_emitcode("setb","c");
6947       } else{
6948         // lit == (0 or 1)
6949         if(lit == 0){
6950           // lit == 0, result = left
6951           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6952             goto release;
6953           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6954         } else{
6955           // lit == 1, result = not(left)
6956           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6957             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6958             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6959             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6960             goto release;
6961           } else {
6962             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6963             pic16_emitcode("cpl","c");
6964           }
6965         }
6966       }
6967
6968     } else {
6969       // right != literal
6970       symbol *tlbl = newiTempLabel(NULL);
6971       if (AOP_TYPE(right) == AOP_CRY){
6972         // c = bit ^ bit;
6973         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6974       }
6975       else{
6976         int sizer = AOP_SIZE(right);
6977         // c = bit ^ val
6978         // if val>>1 != 0, result = 1
6979         pic16_emitcode("setb","c");
6980         while(sizer){
6981           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6982           if(sizer == 1)
6983             // test the msb of the lsb
6984             pic16_emitcode("anl","a,#0xfe");
6985           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6986           sizer--;
6987         }
6988         // val = (0,1)
6989         pic16_emitcode("rrc","a");
6990       }
6991       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6992       pic16_emitcode("cpl","c");
6993       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6994     }
6995     // bit = c
6996     // val = c
6997     if(size)
6998       pic16_outBitC(result);
6999     // if(bit | ...)
7000     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7001       genIfxJump(ifx, "c");           
7002     goto release ;
7003   }
7004
7005   if(pic16_sameRegs(AOP(result),AOP(left))){
7006     /* if left is same as result */
7007     for(;size--; offset++) {
7008       if(AOP_TYPE(right) == AOP_LIT){
7009         int t  = (lit >> (offset*8)) & 0x0FFL;
7010         if(t == 0x00L)
7011           continue;
7012         else
7013           if (IS_AOP_PREG(left)) {
7014             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7015             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7016             pic16_aopPut(AOP(result),"a",offset);
7017           } else {
7018             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7019             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7020             pic16_emitcode("xrl","%s,%s",
7021                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7022                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7023           }
7024       } else {
7025         if (AOP_TYPE(left) == AOP_ACC)
7026           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7027         else {
7028           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7029           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7030 /*
7031           if (IS_AOP_PREG(left)) {
7032             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7033             pic16_aopPut(AOP(result),"a",offset);
7034           } else
7035             pic16_emitcode("xrl","%s,a",
7036                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7037 */
7038         }
7039       }
7040     }
7041   } else {
7042     // left & result in different registers
7043     if(AOP_TYPE(result) == AOP_CRY){
7044       // result = bit
7045       // if(size), result in bit
7046       // if(!size && ifx), conditional oper: if(left ^ right)
7047       symbol *tlbl = newiTempLabel(NULL);
7048       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7049       if(size)
7050         pic16_emitcode("setb","c");
7051       while(sizer--){
7052         if((AOP_TYPE(right) == AOP_LIT) &&
7053            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7054           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7055         } else {
7056           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7057           pic16_emitcode("xrl","a,%s",
7058                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7059         }
7060         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7061         offset++;
7062       }
7063       if(size){
7064         CLRC;
7065         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7066         pic16_outBitC(result);
7067       } else if(ifx)
7068         jmpTrueOrFalse(ifx, tlbl);
7069     } else for(;(size--);offset++){
7070       // normal case
7071       // result = left & right
7072       if(AOP_TYPE(right) == AOP_LIT){
7073         int t = (lit >> (offset*8)) & 0x0FFL;
7074         switch(t) { 
7075         case 0x00:
7076           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7077           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7078           pic16_emitcode("movf","%s,w",
7079                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7080           pic16_emitcode("movwf","%s",
7081                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7082           break;
7083         case 0xff:
7084           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7085           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7086           pic16_emitcode("comf","%s,w",
7087                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7088           pic16_emitcode("movwf","%s",
7089                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7090           break;
7091         default:
7092           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7093           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7094           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7095           pic16_emitcode("movlw","0x%x",t);
7096           pic16_emitcode("xorwf","%s,w",
7097                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7098           pic16_emitcode("movwf","%s",
7099                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7100
7101         }
7102         continue;
7103       }
7104
7105       // faster than result <- left, anl result,right
7106       // and better if result is SFR
7107       if (AOP_TYPE(left) == AOP_ACC) {
7108         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7109         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7110       } else {
7111         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7112         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7113         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7114         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7115       }
7116       if ( AOP_TYPE(result) != AOP_ACC){
7117         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7118         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7119       }
7120     }
7121   }
7122
7123   release :
7124     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7125   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7126   pic16_freeAsmop(result,NULL,ic,TRUE);     
7127 }
7128
7129 /*-----------------------------------------------------------------*/
7130 /* genInline - write the inline code out                           */
7131 /*-----------------------------------------------------------------*/
7132 static void genInline (iCode *ic)
7133 {
7134   char *buffer, *bp, *bp1;
7135     
7136         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7137
7138         _G.inLine += (!options.asmpeep);
7139
7140         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7141         strcpy(buffer,IC_INLINE(ic));
7142
7143 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7144
7145         /* emit each line as a code */
7146         while (*bp) {
7147                 if (*bp == '\n') {
7148                         *bp++ = '\0';
7149
7150                         if(*bp1)
7151                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7152                         bp1 = bp;
7153                 } else {
7154                         if (*bp == ':') {
7155                                 bp++;
7156                                 *bp = '\0';
7157                                 bp++;
7158
7159                                 /* print label, use this special format with NULL directive
7160                                  * to denote that the argument should not be indented with tab */
7161                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7162                                 bp1 = bp;
7163                         } else
7164                                 bp++;
7165                 }
7166         }
7167
7168         if ((bp1 != bp) && *bp1)
7169                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7170
7171
7172     Safe_free(buffer);
7173
7174     _G.inLine -= (!options.asmpeep);
7175 }
7176
7177 /*-----------------------------------------------------------------*/
7178 /* genRRC - rotate right with carry                                */
7179 /*-----------------------------------------------------------------*/
7180 static void genRRC (iCode *ic)
7181 {
7182   operand *left , *result ;
7183   int size, offset = 0, same;
7184
7185   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7186
7187   /* rotate right with carry */
7188   left = IC_LEFT(ic);
7189   result=IC_RESULT(ic);
7190   pic16_aopOp (left,ic,FALSE);
7191   pic16_aopOp (result,ic,FALSE);
7192
7193   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7194
7195   same = pic16_sameRegs(AOP(result),AOP(left));
7196
7197   size = AOP_SIZE(result);    
7198
7199   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7200
7201   /* get the lsb and put it into the carry */
7202   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7203
7204   offset = 0 ;
7205
7206   while(size--) {
7207
7208     if(same) {
7209       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7210     } else {
7211       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7212       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7213     }
7214
7215     offset++;
7216   }
7217
7218   pic16_freeAsmop(left,NULL,ic,TRUE);
7219   pic16_freeAsmop(result,NULL,ic,TRUE);
7220 }
7221
7222 /*-----------------------------------------------------------------*/
7223 /* genRLC - generate code for rotate left with carry               */
7224 /*-----------------------------------------------------------------*/
7225 static void genRLC (iCode *ic)
7226 {    
7227   operand *left , *result ;
7228   int size, offset = 0;
7229   int same;
7230
7231   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7232   /* rotate right with carry */
7233   left = IC_LEFT(ic);
7234   result=IC_RESULT(ic);
7235   pic16_aopOp (left,ic,FALSE);
7236   pic16_aopOp (result,ic,FALSE);
7237
7238   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7239
7240   same = pic16_sameRegs(AOP(result),AOP(left));
7241
7242   /* move it to the result */
7243   size = AOP_SIZE(result);    
7244
7245   /* get the msb and put it into the carry */
7246   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7247
7248   offset = 0 ;
7249
7250   while(size--) {
7251
7252     if(same) {
7253       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7254     } else {
7255       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7256       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7257     }
7258
7259     offset++;
7260   }
7261
7262
7263   pic16_freeAsmop(left,NULL,ic,TRUE);
7264   pic16_freeAsmop(result,NULL,ic,TRUE);
7265 }
7266
7267
7268 /* gpasm can get the highest order bit with HIGH/UPPER
7269  * so the following probably is not needed -- VR */
7270  
7271 /*-----------------------------------------------------------------*/
7272 /* genGetHbit - generates code get highest order bit               */
7273 /*-----------------------------------------------------------------*/
7274 static void genGetHbit (iCode *ic)
7275 {
7276     operand *left, *result;
7277     left = IC_LEFT(ic);
7278     result=IC_RESULT(ic);
7279     pic16_aopOp (left,ic,FALSE);
7280     pic16_aopOp (result,ic,FALSE);
7281
7282     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7283     /* get the highest order byte into a */
7284     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7285     if(AOP_TYPE(result) == AOP_CRY){
7286         pic16_emitcode("rlc","a");
7287         pic16_outBitC(result);
7288     }
7289     else{
7290         pic16_emitcode("rl","a");
7291         pic16_emitcode("anl","a,#0x01");
7292         pic16_outAcc(result);
7293     }
7294
7295
7296     pic16_freeAsmop(left,NULL,ic,TRUE);
7297     pic16_freeAsmop(result,NULL,ic,TRUE);
7298 }
7299
7300 #if 0
7301 /*-----------------------------------------------------------------*/
7302 /* AccRol - rotate left accumulator by known count                 */
7303 /*-----------------------------------------------------------------*/
7304 static void AccRol (int shCount)
7305 {
7306     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7307     shCount &= 0x0007;              // shCount : 0..7
7308     switch(shCount){
7309         case 0 :
7310             break;
7311         case 1 :
7312             pic16_emitcode("rl","a");
7313             break;
7314         case 2 :
7315             pic16_emitcode("rl","a");
7316             pic16_emitcode("rl","a");
7317             break;
7318         case 3 :
7319             pic16_emitcode("swap","a");
7320             pic16_emitcode("rr","a");
7321             break;
7322         case 4 :
7323             pic16_emitcode("swap","a");
7324             break;
7325         case 5 :
7326             pic16_emitcode("swap","a");
7327             pic16_emitcode("rl","a");
7328             break;
7329         case 6 :
7330             pic16_emitcode("rr","a");
7331             pic16_emitcode("rr","a");
7332             break;
7333         case 7 :
7334             pic16_emitcode("rr","a");
7335             break;
7336     }
7337 }
7338 #endif
7339
7340 /*-----------------------------------------------------------------*/
7341 /* AccLsh - left shift accumulator by known count                  */
7342 /*-----------------------------------------------------------------*/
7343 static void AccLsh (int shCount)
7344 {
7345         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7346         switch(shCount){
7347                 case 0 :
7348                         return;
7349                         break;
7350                 case 1 :
7351                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7352                         break;
7353                 case 2 :
7354                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7355                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7356                         break;
7357                 case 3 :
7358                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7359                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7360                         break;
7361                 case 4 :
7362                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7363                         break;
7364                 case 5 :
7365                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7366                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7367                         break;
7368                 case 6 :
7369                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7370                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7371                         break;
7372                 case 7 :
7373                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7374                         break;
7375         }
7376
7377         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7378 }
7379
7380 /*-----------------------------------------------------------------*/
7381 /* AccRsh - right shift accumulator by known count                 */
7382 /*-----------------------------------------------------------------*/
7383 static void AccRsh (int shCount, int andmask)
7384 {
7385         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7386         switch(shCount){
7387                 case 0 :
7388                         return; break;
7389                 case 1 :
7390                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7391 //                      andmask = 0;    /* no need */
7392                         break;
7393                 case 2 :
7394                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7395                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7396 //                      andmask = 0;    /* no need */
7397                         break;
7398                 case 3 :
7399                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7400                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7401                         break;
7402                 case 4 :
7403                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7404                         break;
7405                 case 5 :
7406                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7407                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7408                         break;
7409                 case 6 :
7410                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7411                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7412                         break;
7413                 case 7 :
7414                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7415                         break;
7416         }
7417         
7418         if(andmask)
7419                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7420         else
7421                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7422 }
7423
7424 #if 0
7425 /*-----------------------------------------------------------------*/
7426 /* AccSRsh - signed right shift accumulator by known count                 */
7427 /*-----------------------------------------------------------------*/
7428 static void AccSRsh (int shCount)
7429 {
7430     symbol *tlbl ;
7431     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7432     if(shCount != 0){
7433         if(shCount == 1){
7434             pic16_emitcode("mov","c,acc.7");
7435             pic16_emitcode("rrc","a");
7436         } else if(shCount == 2){
7437             pic16_emitcode("mov","c,acc.7");
7438             pic16_emitcode("rrc","a");
7439             pic16_emitcode("mov","c,acc.7");
7440             pic16_emitcode("rrc","a");
7441         } else {
7442             tlbl = newiTempLabel(NULL);
7443             /* rotate right accumulator */
7444             AccRol(8 - shCount);
7445             /* and kill the higher order bits */
7446             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7447             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7448             pic16_emitcode("orl","a,#0x%02x",
7449                      (unsigned char)~SRMask[shCount]);
7450             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7451         }
7452     }
7453 }
7454 #endif
7455 /*-----------------------------------------------------------------*/
7456 /* shiftR1Left2Result - shift right one byte from left to result   */
7457 /*-----------------------------------------------------------------*/
7458 static void shiftR1Left2ResultSigned (operand *left, int offl,
7459                                 operand *result, int offr,
7460                                 int shCount)
7461 {
7462   int same;
7463
7464   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7465
7466   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7467
7468   switch(shCount) {
7469   case 1:
7470     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7471     if(same) 
7472       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7473     else {
7474       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7475       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7476     }
7477
7478     break;
7479   case 2:
7480
7481     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7482     if(same) 
7483       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7484     else {
7485       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7486       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7487     }
7488     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7489     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7490
7491     break;
7492
7493   case 3:
7494     if(same)
7495       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7496     else {
7497       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7498       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7499     }
7500
7501     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7502     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7503     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7504
7505     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7506     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7507
7508     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7509     break;
7510
7511   case 4:
7512     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7513     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7514     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7515     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7516     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7517     break;
7518   case 5:
7519     if(same) {
7520       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7521     } else {
7522       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7523       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7524     }
7525     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7526     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7527     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7528     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7529     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7530     break;
7531
7532   case 6:
7533     if(same) {
7534       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7535       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7536       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7537       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7538       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7539       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7540     } else {
7541       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7542       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7543       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7544       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7545       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7546     }
7547     break;
7548
7549   case 7:
7550     if(same) {
7551       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7552       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7553       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7554       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7555     } else {
7556       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7557       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7558       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7559     }
7560
7561   default:
7562     break;
7563   }
7564 }
7565
7566 /*-----------------------------------------------------------------*/
7567 /* shiftR1Left2Result - shift right one byte from left to result   */
7568 /*-----------------------------------------------------------------*/
7569 static void shiftR1Left2Result (operand *left, int offl,
7570                                 operand *result, int offr,
7571                                 int shCount, int sign)
7572 {
7573   int same;
7574
7575   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7576
7577   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7578
7579   /* Copy the msb into the carry if signed. */
7580   if(sign) {
7581     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7582     return;
7583   }
7584
7585
7586
7587   switch(shCount) {
7588   case 1:
7589     emitCLRC;
7590     if(same) 
7591       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7592     else {
7593       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7594       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7595     }
7596     break;
7597   case 2:
7598     emitCLRC;
7599     if(same) {
7600       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7601     } else {
7602       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7603       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7604     }
7605     emitCLRC;
7606     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7607
7608     break;
7609   case 3:
7610     if(same)
7611       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7612     else {
7613       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7614       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7615     }
7616
7617     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7618     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7619     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7620     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7621     break;
7622       
7623   case 4:
7624     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7625     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7626     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7627     break;
7628
7629   case 5:
7630     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7631     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7632     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7633     emitCLRC;
7634     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7635
7636     break;
7637   case 6:
7638
7639     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7640     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7641     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7642     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7643     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7644     break;
7645
7646   case 7:
7647
7648     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7649     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7650     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7651
7652     break;
7653
7654   default:
7655     break;
7656   }
7657 }
7658
7659 /*-----------------------------------------------------------------*/
7660 /* shiftL1Left2Result - shift left one byte from left to result    */
7661 /*-----------------------------------------------------------------*/
7662 static void shiftL1Left2Result (operand *left, int offl,
7663                                 operand *result, int offr, int shCount)
7664 {
7665   int same;
7666
7667   //    char *l;
7668   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7669
7670   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7671   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7672     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7673     //    MOVA(l);
7674     /* shift left accumulator */
7675     //AccLsh(shCount); // don't comment out just yet...
7676   //    pic16_aopPut(AOP(result),"a",offr);
7677
7678   switch(shCount) {
7679   case 1:
7680     /* Shift left 1 bit position */
7681     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7682     if(same) {
7683       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7684     } else {
7685       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7686       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7687     }
7688     break;
7689   case 2:
7690     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7691     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7692     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7693     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7694     break;
7695   case 3:
7696     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7697     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7698     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7699     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7700     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7701     break;
7702   case 4:
7703     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7704     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7705     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7706     break;
7707   case 5:
7708     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7709     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7710     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7711     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7712     break;
7713   case 6:
7714     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7715     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7716     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7717     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7718     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7719     break;
7720   case 7:
7721     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7722     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7723     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7724     break;
7725
7726   default:
7727     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7728   }
7729
7730 }
7731
7732 /*-----------------------------------------------------------------*/
7733 /* movLeft2Result - move byte from left to result                  */
7734 /*-----------------------------------------------------------------*/
7735 static void movLeft2Result (operand *left, int offl,
7736                             operand *result, int offr)
7737 {
7738   char *l;
7739   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7740   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7741     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7742
7743     if (*l == '@' && (IS_AOP_PREG(result))) {
7744       pic16_emitcode("mov","a,%s",l);
7745       pic16_aopPut(AOP(result),"a",offr);
7746     } else {
7747       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7748       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7749     }
7750   }
7751 }
7752
7753 /*-----------------------------------------------------------------*/
7754 /* shiftL2Left2Result - shift left two bytes from left to result   */
7755 /*-----------------------------------------------------------------*/
7756 static void shiftL2Left2Result (operand *left, int offl,
7757                                 operand *result, int offr, int shCount)
7758 {
7759   int same = pic16_sameRegs(AOP(result), AOP(left));
7760   int i;
7761
7762   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7763
7764   if (same && (offl != offr)) { // shift bytes
7765     if (offr > offl) {
7766        for(i=1;i>-1;i--) {
7767          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7768          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7769        }
7770     } else { // just treat as different later on
7771                 same = 0;
7772     }
7773   }
7774
7775   if(same) {
7776     switch(shCount) {
7777     case 0:
7778       break;
7779     case 1:
7780     case 2:
7781     case 3:
7782
7783       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7784       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7785       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7786
7787       while(--shCount) {
7788                 emitCLRC;
7789                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7790                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7791       }
7792
7793       break;
7794     case 4:
7795     case 5:
7796       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7797       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7798       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7799       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7800       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7801       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7802       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7803       if(shCount >=5) {
7804                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7805                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7806       }
7807       break;
7808     case 6:
7809       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7810       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7811       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7812       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7813       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7814       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7815       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7816       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7817       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7818       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7819       break;
7820     case 7:
7821       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7822       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7823       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7824       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7825       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7826     }
7827
7828   } else {
7829     switch(shCount) {
7830     case 0:
7831       break;
7832     case 1:
7833     case 2:
7834     case 3:
7835       /* note, use a mov/add for the shift since the mov has a
7836          chance of getting optimized out */
7837       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7838       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7839       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7840       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7841       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7842
7843       while(--shCount) {
7844                 emitCLRC;
7845                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7846                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7847       }
7848       break;
7849
7850     case 4:
7851     case 5:
7852       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7853       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7854       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7855       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7857       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7858       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7859       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7860
7861
7862       if(shCount == 5) {
7863                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7864                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7865       }
7866       break;
7867     case 6:
7868       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7869       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7870       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7871       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7872
7873       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7874       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7875       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7876       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7877       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7878       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7879       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7880       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7881       break;
7882     case 7:
7883       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7884       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7885       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7886       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7887       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7888     }
7889   }
7890
7891 }
7892 /*-----------------------------------------------------------------*/
7893 /* shiftR2Left2Result - shift right two bytes from left to result  */
7894 /*-----------------------------------------------------------------*/
7895 static void shiftR2Left2Result (operand *left, int offl,
7896                                 operand *result, int offr,
7897                                 int shCount, int sign)
7898 {
7899   int same = pic16_sameRegs(AOP(result), AOP(left));
7900   int i;
7901   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7902
7903   if (same && (offl != offr)) { // shift right bytes
7904     if (offr < offl) {
7905        for(i=0;i<2;i++) {
7906          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7907          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7908        }
7909     } else { // just treat as different later on
7910                 same = 0;
7911     }
7912   }
7913
7914   switch(shCount) {
7915   case 0:
7916     break;
7917   case 1:
7918   case 2:
7919   case 3:
7920     if(sign)
7921       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7922     else
7923       emitCLRC;
7924
7925     if(same) {
7926       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7927       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7928     } else {
7929       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7930       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7931       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7932       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933     }
7934
7935     while(--shCount) {
7936       if(sign)
7937                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7938       else
7939                 emitCLRC;
7940       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7941       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7942     }
7943     break;
7944   case 4:
7945   case 5:
7946     if(same) {
7947
7948       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7949       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7950       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7951
7952       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7953       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7954       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7955       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7956     } else {
7957       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7958       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7959       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7960
7961       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7962       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7963       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7964       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7965       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7966     }
7967
7968     if(shCount >=5) {
7969       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7970       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7971     }
7972
7973     if(sign) {
7974       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7975       pic16_emitpcode(POC_BTFSC, 
7976                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7977       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7978     }
7979
7980     break;
7981
7982   case 6:
7983     if(same) {
7984
7985       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7986       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7987
7988       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7989       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7990       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7991       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7992       if(sign) {
7993         pic16_emitpcode(POC_BTFSC, 
7994                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7995         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7996       }
7997       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7998       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7999       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8000       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8001     } else {
8002       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8003       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8004       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8005       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8006       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8007       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8008       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8009       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8010       if(sign) {
8011         pic16_emitpcode(POC_BTFSC, 
8012                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8013         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8014       }
8015       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8016       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8017
8018         
8019     }
8020
8021     break;
8022   case 7:
8023     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8024     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8025     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8026     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8027     if(sign) {
8028       emitSKPNC;
8029       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8030     } else 
8031       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8032   }
8033 }
8034
8035
8036 /*-----------------------------------------------------------------*/
8037 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8038 /*-----------------------------------------------------------------*/
8039 static void shiftLLeftOrResult (operand *left, int offl,
8040                                 operand *result, int offr, int shCount)
8041 {
8042     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8043
8044     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8045     /* shift left accumulator */
8046     AccLsh(shCount);
8047     /* or with result */
8048     /* back to result */
8049     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8054 /*-----------------------------------------------------------------*/
8055 static void shiftRLeftOrResult (operand *left, int offl,
8056                                 operand *result, int offr, int shCount)
8057 {
8058     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8059     
8060     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8061     /* shift right accumulator */
8062     AccRsh(shCount, 1);
8063     /* or with result */
8064     /* back to result */
8065     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8066 }
8067
8068 /*-----------------------------------------------------------------*/
8069 /* genlshOne - left shift a one byte quantity by known count       */
8070 /*-----------------------------------------------------------------*/
8071 static void genlshOne (operand *result, operand *left, int shCount)
8072 {       
8073     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8074     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8075 }
8076
8077 /*-----------------------------------------------------------------*/
8078 /* genlshTwo - left shift two bytes by known amount != 0           */
8079 /*-----------------------------------------------------------------*/
8080 static void genlshTwo (operand *result,operand *left, int shCount)
8081 {
8082     int size;
8083     
8084     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8085     size = pic16_getDataSize(result);
8086
8087     /* if shCount >= 8 */
8088     if (shCount >= 8) {
8089         shCount -= 8 ;
8090
8091         if (size > 1){
8092             if (shCount)
8093                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8094             else 
8095                 movLeft2Result(left, LSB, result, MSB16);
8096         }
8097         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8098     }
8099
8100     /*  1 <= shCount <= 7 */
8101     else {  
8102         if(size == 1)
8103             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8104         else 
8105             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8106     }
8107 }
8108
8109 /*-----------------------------------------------------------------*/
8110 /* shiftLLong - shift left one long from left to result            */
8111 /* offr = LSB or MSB16                                             */
8112 /*-----------------------------------------------------------------*/
8113 static void shiftLLong (operand *left, operand *result, int offr )
8114 {
8115     int size = AOP_SIZE(result);
8116     int same = pic16_sameRegs(AOP(left),AOP(result));
8117         int i;
8118
8119     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8120
8121         if (same && (offr == MSB16)) { //shift one byte
8122                 for(i=size-1;i>=MSB16;i--) {
8123                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8124                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8125                 }
8126         } else {
8127                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8128         }
8129         
8130     if (size >= LSB+offr ){
8131                 if (same) {
8132                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8133                 } else {
8134                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8135                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8136                 }
8137          }
8138
8139     if(size >= MSB16+offr){
8140                 if (same) {
8141                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8142                 } else {
8143                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8144                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8145                 }
8146     }
8147
8148     if(size >= MSB24+offr){
8149                 if (same) {
8150                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8151                 } else {
8152                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8153                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8154                 }
8155     }
8156
8157     if(size > MSB32+offr){
8158                 if (same) {
8159                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8160                 } else {
8161                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8162                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8163                 }
8164     }
8165     if(offr != LSB)
8166                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8167
8168 }
8169
8170 /*-----------------------------------------------------------------*/
8171 /* genlshFour - shift four byte by a known amount != 0             */
8172 /*-----------------------------------------------------------------*/
8173 static void genlshFour (operand *result, operand *left, int shCount)
8174 {
8175     int size;
8176
8177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8178     size = AOP_SIZE(result);
8179
8180     /* if shifting more that 3 bytes */
8181     if (shCount >= 24 ) {
8182         shCount -= 24;
8183         if (shCount)
8184             /* lowest order of left goes to the highest
8185             order of the destination */
8186             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8187         else
8188             movLeft2Result(left, LSB, result, MSB32);
8189
8190                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8191                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8192                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8193
8194         return;
8195     }
8196
8197     /* more than two bytes */
8198     else if ( shCount >= 16 ) {
8199         /* lower order two bytes goes to higher order two bytes */
8200         shCount -= 16;
8201         /* if some more remaining */
8202         if (shCount)
8203             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8204         else {
8205             movLeft2Result(left, MSB16, result, MSB32);
8206             movLeft2Result(left, LSB, result, MSB24);
8207         }
8208                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8209                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8210         return;
8211     }    
8212
8213     /* if more than 1 byte */
8214     else if ( shCount >= 8 ) {
8215         /* lower order three bytes goes to higher order  three bytes */
8216         shCount -= 8;
8217         if(size == 2){
8218             if(shCount)
8219                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8220             else
8221                 movLeft2Result(left, LSB, result, MSB16);
8222         }
8223         else{   /* size = 4 */
8224             if(shCount == 0){
8225                 movLeft2Result(left, MSB24, result, MSB32);
8226                 movLeft2Result(left, MSB16, result, MSB24);
8227                 movLeft2Result(left, LSB, result, MSB16);
8228                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8229             }
8230             else if(shCount == 1)
8231                 shiftLLong(left, result, MSB16);
8232             else{
8233                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8234                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8235                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8236                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8237             }
8238         }
8239     }
8240
8241     /* 1 <= shCount <= 7 */
8242     else if(shCount <= 3)
8243     { 
8244         shiftLLong(left, result, LSB);
8245         while(--shCount >= 1)
8246             shiftLLong(result, result, LSB);
8247     }
8248     /* 3 <= shCount <= 7, optimize */
8249     else{
8250         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8251         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8252         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8253     }
8254 }
8255
8256 /*-----------------------------------------------------------------*/
8257 /* genLeftShiftLiteral - left shifting by known count              */
8258 /*-----------------------------------------------------------------*/
8259 static void genLeftShiftLiteral (operand *left,
8260                                  operand *right,
8261                                  operand *result,
8262                                  iCode *ic)
8263 {    
8264     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8265     int size;
8266
8267     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8268     pic16_freeAsmop(right,NULL,ic,TRUE);
8269
8270     pic16_aopOp(left,ic,FALSE);
8271     pic16_aopOp(result,ic,FALSE);
8272
8273     size = getSize(operandType(result));
8274
8275 #if VIEW_SIZE
8276     pic16_emitcode("; shift left ","result %d, left %d",size,
8277              AOP_SIZE(left));
8278 #endif
8279
8280     /* I suppose that the left size >= result size */
8281     if(shCount == 0){
8282         while(size--){
8283             movLeft2Result(left, size, result, size);
8284         }
8285     }
8286
8287     else if(shCount >= (size * 8))
8288         while(size--)
8289             pic16_aopPut(AOP(result),zero,size);
8290     else{
8291         switch (size) {
8292             case 1:
8293                 genlshOne (result,left,shCount);
8294                 break;
8295
8296             case 2:
8297             case 3:
8298                 genlshTwo (result,left,shCount);
8299                 break;
8300
8301             case 4:
8302                 genlshFour (result,left,shCount);
8303                 break;
8304         }
8305     }
8306     pic16_freeAsmop(left,NULL,ic,TRUE);
8307     pic16_freeAsmop(result,NULL,ic,TRUE);
8308 }
8309
8310 /*-----------------------------------------------------------------*
8311  * genMultiAsm - repeat assembly instruction for size of register.
8312  * if endian == 1, then the high byte (i.e base address + size of 
8313  * register) is used first else the low byte is used first;
8314  *-----------------------------------------------------------------*/
8315 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8316 {
8317
8318   int offset = 0;
8319
8320   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8321
8322   if(!reg)
8323     return;
8324
8325   if(!endian) {
8326     endian = 1;
8327   } else {
8328     endian = -1;
8329     offset = size-1;
8330   }
8331
8332   while(size--) {
8333     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8334     offset += endian;
8335   }
8336
8337 }
8338 /*-----------------------------------------------------------------*/
8339 /* genLeftShift - generates code for left shifting                 */
8340 /*-----------------------------------------------------------------*/
8341 static void genLeftShift (iCode *ic)
8342 {
8343   operand *left,*right, *result;
8344   int size, offset;
8345   char *l;
8346   symbol *tlbl , *tlbl1;
8347   pCodeOp *pctemp;
8348
8349   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8350
8351   right = IC_RIGHT(ic);
8352   left  = IC_LEFT(ic);
8353   result = IC_RESULT(ic);
8354
8355   pic16_aopOp(right,ic,FALSE);
8356
8357   /* if the shift count is known then do it 
8358      as efficiently as possible */
8359   if (AOP_TYPE(right) == AOP_LIT) {
8360     genLeftShiftLiteral (left,right,result,ic);
8361     return ;
8362   }
8363
8364   /* shift count is unknown then we have to form 
8365      a loop get the loop count in B : Note: we take
8366      only the lower order byte since shifting
8367      more that 32 bits make no sense anyway, ( the
8368      largest size of an object can be only 32 bits ) */  
8369
8370     
8371   pic16_aopOp(left,ic,FALSE);
8372   pic16_aopOp(result,ic,FALSE);
8373
8374   /* now move the left to the result if they are not the
8375      same */
8376   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8377       AOP_SIZE(result) > 1) {
8378
8379     size = AOP_SIZE(result);
8380     offset=0;
8381     while (size--) {
8382       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8383       if (*l == '@' && (IS_AOP_PREG(result))) {
8384
8385         pic16_emitcode("mov","a,%s",l);
8386         pic16_aopPut(AOP(result),"a",offset);
8387       } else {
8388         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8389         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8390         //pic16_aopPut(AOP(result),l,offset);
8391       }
8392       offset++;
8393     }
8394   }
8395
8396   size = AOP_SIZE(result);
8397
8398   /* if it is only one byte then */
8399   if (size == 1) {
8400     if(optimized_for_speed) {
8401       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8402       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8403       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8404       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8405       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8406       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8407       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8408       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8409       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8410       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8411       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8412       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8413     } else {
8414
8415       tlbl = newiTempLabel(NULL);
8416       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8417                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8418                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8419       }
8420
8421       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8422       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8423       pic16_emitpLabel(tlbl->key);
8424       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8425       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8426       emitSKPC;
8427       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8428     }
8429     goto release ;
8430   }
8431     
8432   if (pic16_sameRegs(AOP(left),AOP(result))) {
8433
8434     tlbl = newiTempLabel(NULL);
8435     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8436     genMultiAsm(POC_RRCF, result, size,1);
8437     pic16_emitpLabel(tlbl->key);
8438     genMultiAsm(POC_RLCF, result, size,0);
8439     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8440     emitSKPC;
8441     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8442     goto release;
8443   }
8444
8445   //tlbl = newiTempLabel(NULL);
8446   //offset = 0 ;   
8447   //tlbl1 = newiTempLabel(NULL);
8448
8449   //reAdjustPreg(AOP(result));    
8450     
8451   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8452   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8453   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8454   //MOVA(l);
8455   //pic16_emitcode("add","a,acc");         
8456   //pic16_aopPut(AOP(result),"a",offset++);
8457   //while (--size) {
8458   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8459   //  MOVA(l);
8460   //  pic16_emitcode("rlc","a");         
8461   //  pic16_aopPut(AOP(result),"a",offset++);
8462   //}
8463   //reAdjustPreg(AOP(result));
8464
8465   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8466   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8467
8468
8469   tlbl = newiTempLabel(NULL);
8470   tlbl1= newiTempLabel(NULL);
8471
8472   size = AOP_SIZE(result);
8473   offset = 1;
8474
8475   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8476
8477   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8478
8479   /* offset should be 0, 1 or 3 */
8480   
8481   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8482   emitSKPNZ;
8483   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8484
8485   pic16_emitpcode(POC_MOVWF, pctemp);
8486
8487
8488   pic16_emitpLabel(tlbl->key);
8489
8490   emitCLRC;
8491   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8492   while(--size)
8493     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8494
8495   pic16_emitpcode(POC_DECFSZ,  pctemp);
8496   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8497   pic16_emitpLabel(tlbl1->key);
8498
8499   pic16_popReleaseTempReg(pctemp);
8500
8501
8502  release:
8503   pic16_freeAsmop (right,NULL,ic,TRUE);
8504   pic16_freeAsmop(left,NULL,ic,TRUE);
8505   pic16_freeAsmop(result,NULL,ic,TRUE);
8506 }
8507
8508 /*-----------------------------------------------------------------*/
8509 /* genrshOne - right shift a one byte quantity by known count      */
8510 /*-----------------------------------------------------------------*/
8511 static void genrshOne (operand *result, operand *left,
8512                        int shCount, int sign)
8513 {
8514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8515     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8516 }
8517
8518 /*-----------------------------------------------------------------*/
8519 /* genrshTwo - right shift two bytes by known amount != 0          */
8520 /*-----------------------------------------------------------------*/
8521 static void genrshTwo (operand *result,operand *left,
8522                        int shCount, int sign)
8523 {
8524   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8525   /* if shCount >= 8 */
8526   if (shCount >= 8) {
8527     shCount -= 8 ;
8528     if (shCount)
8529       shiftR1Left2Result(left, MSB16, result, LSB,
8530                          shCount, sign);
8531     else
8532       movLeft2Result(left, MSB16, result, LSB);
8533
8534     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8535
8536     if(sign) {
8537       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8538       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8539     }
8540   }
8541
8542   /*  1 <= shCount <= 7 */
8543   else
8544     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8545 }
8546
8547 /*-----------------------------------------------------------------*/
8548 /* shiftRLong - shift right one long from left to result           */
8549 /* offl = LSB or MSB16                                             */
8550 /*-----------------------------------------------------------------*/
8551 static void shiftRLong (operand *left, int offl,
8552                         operand *result, int sign)
8553 {
8554     int size = AOP_SIZE(result);
8555     int same = pic16_sameRegs(AOP(left),AOP(result));
8556     int i;
8557     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8558
8559         if (same && (offl == MSB16)) { //shift one byte right
8560                 for(i=MSB16;i<size;i++) {
8561                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8562                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8563                 }
8564         }
8565
8566     if(sign)
8567                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8568         else
8569                 emitCLRC;
8570
8571         if (same) {
8572                 if (offl == LSB)
8573                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8574         } else {
8575         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8576         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8577         }
8578
8579     if(offl == MSB16) {
8580         /* add sign of "a" */
8581         pic16_addSign(result, MSB32, sign);
8582         }
8583
8584         if (same) {
8585         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8586         } else {
8587         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8588         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8589         }
8590         
8591         if (same) {
8592         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8593         } else {
8594         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8595         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8596         }
8597
8598         if (same) {
8599         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8600         } else {
8601         if(offl == LSB){
8602                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8603                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8604         }
8605         }
8606 }
8607
8608 /*-----------------------------------------------------------------*/
8609 /* genrshFour - shift four byte by a known amount != 0             */
8610 /*-----------------------------------------------------------------*/
8611 static void genrshFour (operand *result, operand *left,
8612                         int shCount, int sign)
8613 {
8614   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8615   /* if shifting more that 3 bytes */
8616   if(shCount >= 24 ) {
8617     shCount -= 24;
8618     if(shCount)
8619       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8620     else
8621       movLeft2Result(left, MSB32, result, LSB);
8622
8623     pic16_addSign(result, MSB16, sign);
8624   }
8625   else if(shCount >= 16){
8626     shCount -= 16;
8627     if(shCount)
8628       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8629     else{
8630       movLeft2Result(left, MSB24, result, LSB);
8631       movLeft2Result(left, MSB32, result, MSB16);
8632     }
8633     pic16_addSign(result, MSB24, sign);
8634   }
8635   else if(shCount >= 8){
8636     shCount -= 8;
8637     if(shCount == 1)
8638       shiftRLong(left, MSB16, result, sign);
8639     else if(shCount == 0){
8640       movLeft2Result(left, MSB16, result, LSB);
8641       movLeft2Result(left, MSB24, result, MSB16);
8642       movLeft2Result(left, MSB32, result, MSB24);
8643       pic16_addSign(result, MSB32, sign);
8644     }
8645     else{ //shcount >= 2
8646       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8647       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8648       /* the last shift is signed */
8649       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8650       pic16_addSign(result, MSB32, sign);
8651     }
8652   }
8653   else{   /* 1 <= shCount <= 7 */
8654     if(shCount <= 2){
8655       shiftRLong(left, LSB, result, sign);
8656       if(shCount == 2)
8657         shiftRLong(result, LSB, result, sign);
8658     }
8659     else{
8660       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8661       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8662       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8663     }
8664   }
8665 }
8666
8667 /*-----------------------------------------------------------------*/
8668 /* genRightShiftLiteral - right shifting by known count            */
8669 /*-----------------------------------------------------------------*/
8670 static void genRightShiftLiteral (operand *left,
8671                                   operand *right,
8672                                   operand *result,
8673                                   iCode *ic,
8674                                   int sign)
8675 {    
8676   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8677   int lsize,res_size;
8678
8679   pic16_freeAsmop(right,NULL,ic,TRUE);
8680
8681   pic16_aopOp(left,ic,FALSE);
8682   pic16_aopOp(result,ic,FALSE);
8683
8684   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8685
8686 #if VIEW_SIZE
8687   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8688                  AOP_SIZE(left));
8689 #endif
8690
8691   lsize = pic16_getDataSize(left);
8692   res_size = pic16_getDataSize(result);
8693   /* test the LEFT size !!! */
8694
8695   /* I suppose that the left size >= result size */
8696   if(shCount == 0){
8697     while(res_size--)
8698       movLeft2Result(left, lsize, result, res_size);
8699   }
8700
8701   else if(shCount >= (lsize * 8)){
8702
8703     if(res_size == 1) {
8704       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8705       if(sign) {
8706         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8707         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8708       }
8709     } else {
8710
8711       if(sign) {
8712         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8713         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8714         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8715         while(res_size--)
8716           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8717
8718       } else {
8719
8720         while(res_size--)
8721           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8722       }
8723     }
8724   } else {
8725
8726     switch (res_size) {
8727     case 1:
8728       genrshOne (result,left,shCount,sign);
8729       break;
8730
8731     case 2:
8732       genrshTwo (result,left,shCount,sign);
8733       break;
8734
8735     case 4:
8736       genrshFour (result,left,shCount,sign);
8737       break;
8738     default :
8739       break;
8740     }
8741
8742   }
8743
8744   pic16_freeAsmop(left,NULL,ic,TRUE);
8745   pic16_freeAsmop(result,NULL,ic,TRUE);
8746 }
8747
8748 /*-----------------------------------------------------------------*/
8749 /* genSignedRightShift - right shift of signed number              */
8750 /*-----------------------------------------------------------------*/
8751 static void genSignedRightShift (iCode *ic)
8752 {
8753   operand *right, *left, *result;
8754   int size, offset;
8755   //  char *l;
8756   symbol *tlbl, *tlbl1 ;
8757   pCodeOp *pctemp;
8758
8759   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8760
8761   /* we do it the hard way put the shift count in b
8762      and loop thru preserving the sign */
8763   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8764
8765   right = IC_RIGHT(ic);
8766   left  = IC_LEFT(ic);
8767   result = IC_RESULT(ic);
8768
8769   pic16_aopOp(right,ic,FALSE);  
8770   pic16_aopOp(left,ic,FALSE);
8771   pic16_aopOp(result,ic,FALSE);
8772
8773
8774   if ( AOP_TYPE(right) == AOP_LIT) {
8775     genRightShiftLiteral (left,right,result,ic,1);
8776     return ;
8777   }
8778   /* shift count is unknown then we have to form 
8779      a loop get the loop count in B : Note: we take
8780      only the lower order byte since shifting
8781      more that 32 bits make no sense anyway, ( the
8782      largest size of an object can be only 32 bits ) */  
8783
8784   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8785   //pic16_emitcode("inc","b");
8786   //pic16_freeAsmop (right,NULL,ic,TRUE);
8787   //pic16_aopOp(left,ic,FALSE);
8788   //pic16_aopOp(result,ic,FALSE);
8789
8790   /* now move the left to the result if they are not the
8791      same */
8792   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8793       AOP_SIZE(result) > 1) {
8794
8795     size = AOP_SIZE(result);
8796     offset=0;
8797     while (size--) { 
8798       /*
8799         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8800         if (*l == '@' && IS_AOP_PREG(result)) {
8801
8802         pic16_emitcode("mov","a,%s",l);
8803         pic16_aopPut(AOP(result),"a",offset);
8804         } else
8805         pic16_aopPut(AOP(result),l,offset);
8806       */
8807       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8808       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8809
8810       offset++;
8811     }
8812   }
8813
8814   /* mov the highest order bit to OVR */    
8815   tlbl = newiTempLabel(NULL);
8816   tlbl1= newiTempLabel(NULL);
8817
8818   size = AOP_SIZE(result);
8819   offset = size - 1;
8820
8821   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8822
8823   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8824
8825   /* offset should be 0, 1 or 3 */
8826   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8827   emitSKPNZ;
8828   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8829
8830   pic16_emitpcode(POC_MOVWF, pctemp);
8831
8832
8833   pic16_emitpLabel(tlbl->key);
8834
8835   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8836   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8837
8838   while(--size) {
8839     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8840   }
8841
8842   pic16_emitpcode(POC_DECFSZ,  pctemp);
8843   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8844   pic16_emitpLabel(tlbl1->key);
8845
8846   pic16_popReleaseTempReg(pctemp);
8847 #if 0
8848   size = AOP_SIZE(result);
8849   offset = size - 1;
8850   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8851   pic16_emitcode("rlc","a");
8852   pic16_emitcode("mov","ov,c");
8853   /* if it is only one byte then */
8854   if (size == 1) {
8855     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8856     MOVA(l);
8857     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8858     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8859     pic16_emitcode("mov","c,ov");
8860     pic16_emitcode("rrc","a");
8861     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8862     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8863     pic16_aopPut(AOP(result),"a",0);
8864     goto release ;
8865   }
8866
8867   reAdjustPreg(AOP(result));
8868   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8869   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8870   pic16_emitcode("mov","c,ov");
8871   while (size--) {
8872     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8873     MOVA(l);
8874     pic16_emitcode("rrc","a");         
8875     pic16_aopPut(AOP(result),"a",offset--);
8876   }
8877   reAdjustPreg(AOP(result));
8878   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8879   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8880
8881  release:
8882 #endif
8883
8884   pic16_freeAsmop(left,NULL,ic,TRUE);
8885   pic16_freeAsmop(result,NULL,ic,TRUE);
8886   pic16_freeAsmop(right,NULL,ic,TRUE);
8887 }
8888
8889 /*-----------------------------------------------------------------*/
8890 /* genRightShift - generate code for right shifting                */
8891 /*-----------------------------------------------------------------*/
8892 static void genRightShift (iCode *ic)
8893 {
8894     operand *right, *left, *result;
8895     sym_link *letype ;
8896     int size, offset;
8897     char *l;
8898     symbol *tlbl, *tlbl1 ;
8899
8900     /* if signed then we do it the hard way preserve the
8901     sign bit moving it inwards */
8902     letype = getSpec(operandType(IC_LEFT(ic)));
8903     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8904
8905     if (!SPEC_USIGN(letype)) {
8906         genSignedRightShift (ic);
8907         return ;
8908     }
8909
8910     /* signed & unsigned types are treated the same : i.e. the
8911     signed is NOT propagated inwards : quoting from the
8912     ANSI - standard : "for E1 >> E2, is equivalent to division
8913     by 2**E2 if unsigned or if it has a non-negative value,
8914     otherwise the result is implementation defined ", MY definition
8915     is that the sign does not get propagated */
8916
8917     right = IC_RIGHT(ic);
8918     left  = IC_LEFT(ic);
8919     result = IC_RESULT(ic);
8920
8921     pic16_aopOp(right,ic,FALSE);
8922
8923     /* if the shift count is known then do it 
8924     as efficiently as possible */
8925     if (AOP_TYPE(right) == AOP_LIT) {
8926         genRightShiftLiteral (left,right,result,ic, 0);
8927         return ;
8928     }
8929
8930     /* shift count is unknown then we have to form 
8931     a loop get the loop count in B : Note: we take
8932     only the lower order byte since shifting
8933     more that 32 bits make no sense anyway, ( the
8934     largest size of an object can be only 32 bits ) */  
8935
8936     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8937     pic16_emitcode("inc","b");
8938     pic16_aopOp(left,ic,FALSE);
8939     pic16_aopOp(result,ic,FALSE);
8940
8941     /* now move the left to the result if they are not the
8942     same */
8943     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8944         AOP_SIZE(result) > 1) {
8945
8946         size = AOP_SIZE(result);
8947         offset=0;
8948         while (size--) {
8949             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8950             if (*l == '@' && IS_AOP_PREG(result)) {
8951
8952                 pic16_emitcode("mov","a,%s",l);
8953                 pic16_aopPut(AOP(result),"a",offset);
8954             } else
8955                 pic16_aopPut(AOP(result),l,offset);
8956             offset++;
8957         }
8958     }
8959
8960     tlbl = newiTempLabel(NULL);
8961     tlbl1= newiTempLabel(NULL);
8962     size = AOP_SIZE(result);
8963     offset = size - 1;
8964
8965     /* if it is only one byte then */
8966     if (size == 1) {
8967
8968       tlbl = newiTempLabel(NULL);
8969       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8970         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8971         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8972       }
8973
8974       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8975       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8976       pic16_emitpLabel(tlbl->key);
8977       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8978       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8979       emitSKPC;
8980       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8981
8982       goto release ;
8983     }
8984
8985     reAdjustPreg(AOP(result));
8986     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8987     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8988     CLRC;
8989     while (size--) {
8990         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8991         MOVA(l);
8992         pic16_emitcode("rrc","a");         
8993         pic16_aopPut(AOP(result),"a",offset--);
8994     }
8995     reAdjustPreg(AOP(result));
8996
8997     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8998     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8999
9000 release:
9001     pic16_freeAsmop(left,NULL,ic,TRUE);
9002     pic16_freeAsmop (right,NULL,ic,TRUE);
9003     pic16_freeAsmop(result,NULL,ic,TRUE);
9004 }
9005
9006 /*-----------------------------------------------------------------*/
9007 /* genUnpackBits - generates code for unpacking bits               */
9008 /*-----------------------------------------------------------------*/
9009 static void genUnpackBits (operand *result, char *rname, int ptype)
9010 {    
9011     int shCnt ;
9012     int rlen = 0 ;
9013     sym_link *etype;
9014     int offset = 0 ;
9015
9016         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9017         etype = getSpec(operandType(result));
9018
9019         /* read the first byte  */
9020         switch (ptype) {
9021                 case POINTER:
9022                 case IPOINTER:
9023                 case PPOINTER:
9024                 case FPOINTER:
9025                 case GPOINTER:
9026                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9027                         break;
9028                 case CPOINTER:
9029                         pic16_emitcode("clr","a");
9030                         pic16_emitcode("movc","a","@a+dptr");
9031                         break;
9032         }
9033         
9034
9035         /* if we have bitdisplacement then it fits   */
9036         /* into this byte completely or if length is */
9037         /* less than a byte                          */
9038         if ((shCnt = SPEC_BSTR(etype)) || 
9039                 (SPEC_BLEN(etype) <= 8))  {
9040
9041                 /* shift right acc */
9042                 AccRsh(shCnt, 0);
9043
9044                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9045                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9046
9047 /* VR -- normally I would use the following, but since we use the hack,
9048  * to avoid the masking from AccRsh, why not mask it right now? */
9049
9050 /*
9051                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9052 */
9053
9054                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9055           return ;
9056         }
9057
9058
9059
9060         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9061         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9062         exit(-1);
9063
9064     /* bit field did not fit in a byte  */
9065     rlen = SPEC_BLEN(etype) - 8;
9066     pic16_aopPut(AOP(result),"a",offset++);
9067
9068     while (1)  {
9069
9070         switch (ptype) {
9071         case POINTER:
9072         case IPOINTER:
9073             pic16_emitcode("inc","%s",rname);
9074             pic16_emitcode("mov","a,@%s",rname);
9075             break;
9076             
9077         case PPOINTER:
9078             pic16_emitcode("inc","%s",rname);
9079             pic16_emitcode("movx","a,@%s",rname);
9080             break;
9081
9082         case FPOINTER:
9083             pic16_emitcode("inc","dptr");
9084             pic16_emitcode("movx","a,@dptr");
9085             break;
9086             
9087         case CPOINTER:
9088             pic16_emitcode("clr","a");
9089             pic16_emitcode("inc","dptr");
9090             pic16_emitcode("movc","a","@a+dptr");
9091             break;
9092             
9093         case GPOINTER:
9094             pic16_emitcode("inc","dptr");
9095             pic16_emitcode("lcall","__gptrget");
9096             break;
9097         }
9098
9099         rlen -= 8;            
9100         /* if we are done */
9101         if ( rlen <= 0 )
9102             break ;
9103         
9104         pic16_aopPut(AOP(result),"a",offset++);
9105                               
9106     }
9107     
9108     if (rlen) {
9109         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9110         pic16_aopPut(AOP(result),"a",offset);          
9111     }
9112     
9113     return ;
9114 }
9115
9116
9117 static void genDataPointerGet(operand *left,
9118                               operand *result,
9119                               iCode *ic)
9120 {
9121   int size, offset = 0, leoffset=0 ;
9122
9123         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9124         pic16_aopOp(result, ic, FALSE);
9125
9126         size = AOP_SIZE(result);
9127 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9128
9129
9130 #if 0
9131         /* The following tests may save a redudant movff instruction when
9132          * accessing unions */
9133          
9134         /* if they are the same */
9135         if (operandsEqu (left, result)) {
9136                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9137                 goto release;
9138         }
9139 #endif
9140
9141 #if 0
9142         /* if they are the same registers */
9143         if (pic16_sameRegs(AOP(left),AOP(result))) {
9144                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9145                 goto release;
9146         }
9147 #endif
9148
9149 #if 1
9150         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9151                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9152                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9153                 goto release;
9154         }
9155 #endif
9156
9157
9158 #if 0
9159         if ( AOP_TYPE(left) == AOP_PCODE) {
9160                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9161                                 AOP(left)->aopu.pcop->name,
9162                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9163                                 PCOR(AOP(left)->aopu.pcop)->instance:
9164                                 PCOI(AOP(left)->aopu.pcop)->offset);
9165         }
9166 #endif
9167
9168         if(AOP(left)->aopu.pcop->type == PO_DIR)
9169                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9170
9171         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9172
9173         while (size--) {
9174                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9175                 
9176                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9177                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9178                         mov2w(AOP(left), offset); // patch 8
9179                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9180                 } else {
9181                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9182                                 pic16_popGet(AOP(left), offset), //patch 8
9183                                 pic16_popGet(AOP(result), offset)));
9184                 }
9185
9186                 offset++;
9187                 leoffset++;
9188         }
9189
9190 release:
9191     pic16_freeAsmop(result,NULL,ic,TRUE);
9192 }
9193
9194 void pic16_loadFSR0(operand *op)
9195 {
9196         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9197 }
9198
9199
9200 /*-----------------------------------------------------------------*/
9201 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9202 /*-----------------------------------------------------------------*/
9203 static void genNearPointerGet (operand *left, 
9204                                operand *result, 
9205                                iCode *ic)
9206 {
9207     asmop *aop = NULL;
9208     //regs *preg = NULL ;
9209     sym_link *rtype, *retype;
9210     sym_link *ltype = operandType(left);    
9211
9212         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9213         rtype = operandType(result);
9214         retype= getSpec(rtype);
9215     
9216         pic16_aopOp(left,ic,FALSE);
9217
9218 //      pic16_DumpOp("(left)",left);
9219 //      pic16_DumpOp("(result)",result);
9220
9221         /* if left is rematerialisable and
9222          * result is not bit variable type and
9223          * the left is pointer to data space i.e
9224          * lower 128 bytes of space */
9225         if (AOP_TYPE(left) == AOP_PCODE
9226                 && !IS_BITFIELD(retype)
9227                 && DCL_TYPE(ltype) == POINTER) {
9228
9229                 genDataPointerGet (left,result,ic);
9230                 pic16_freeAsmop(left, NULL, ic, TRUE);
9231           return ;
9232         }
9233     
9234         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9235
9236         /* if the value is already in a pointer register
9237          * then don't need anything more */
9238         if (!AOP_INPREG(AOP(left))) {
9239                 /* otherwise get a free pointer register */
9240                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9241                 
9242                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9243                 if( (AOP_TYPE(left) == AOP_PCODE) 
9244                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9245                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9246                 {
9247                         pic16_loadFSR0( left );  // patch 10
9248                 } else {
9249                         // set up FSR0 with address from left
9250                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9251                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9252                 }
9253         }
9254 //       else
9255 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9256     
9257         pic16_aopOp (result,ic,FALSE);
9258     
9259       /* if bitfield then unpack the bits */
9260     if (IS_BITFIELD(retype)) 
9261         genUnpackBits (result, NULL, POINTER);
9262     else {
9263         /* we have can just get the values */
9264       int size = AOP_SIZE(result);
9265       int offset = 0;   
9266         
9267       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9268
9269
9270         /* fsr0 is loaded already -- VR */
9271 //      pic16_loadFSR0( left );
9272
9273 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9274 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9275       while(size--) {
9276
9277         if(size) {
9278                 pic16_emitpcode(POC_MOVFF,
9279                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9280                                 pic16_popGet(AOP(result), offset++)));
9281         } else {
9282                 pic16_emitpcode(POC_MOVFF,
9283                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9284                                 pic16_popGet(AOP(result), offset++)));
9285         }
9286       }
9287 #if 0
9288 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9289 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9290         if(size)
9291           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9292 #endif
9293 /*
9294         while (size--) {
9295             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9296
9297                 pic16_emitcode("mov","a,@%s",rname);
9298                 pic16_aopPut(AOP(result),"a",offset);
9299             } else {
9300                 sprintf(buffer,"@%s",rname);
9301                 pic16_aopPut(AOP(result),buffer,offset);
9302             }
9303             offset++ ;
9304             if (size)
9305                 pic16_emitcode("inc","%s",rname);
9306         }
9307 */
9308     }
9309
9310     /* now some housekeeping stuff */
9311     if (aop) {
9312         /* we had to allocate for this iCode */
9313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9314         pic16_freeAsmop(NULL,aop,ic,TRUE);
9315     } else { 
9316         /* we did not allocate which means left
9317            already in a pointer register, then
9318            if size > 0 && this could be used again
9319            we have to point it back to where it 
9320            belongs */
9321     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9322         if (AOP_SIZE(result) > 1 &&
9323             !OP_SYMBOL(left)->remat &&
9324             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9325               ic->depth )) {
9326 //          int size = AOP_SIZE(result) - 1;
9327 //          while (size--)
9328 //              pic16_emitcode("dec","%s",rname);
9329         }
9330     }
9331
9332     /* done */
9333     pic16_freeAsmop(left,NULL,ic,TRUE);
9334     pic16_freeAsmop(result,NULL,ic,TRUE);
9335      
9336 }
9337
9338 /*-----------------------------------------------------------------*/
9339 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9340 /*-----------------------------------------------------------------*/
9341 static void genPagedPointerGet (operand *left, 
9342                                operand *result, 
9343                                iCode *ic)
9344 {
9345     asmop *aop = NULL;
9346     regs *preg = NULL ;
9347     char *rname ;
9348     sym_link *rtype, *retype;    
9349
9350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9351
9352     rtype = operandType(result);
9353     retype= getSpec(rtype);
9354     
9355     pic16_aopOp(left,ic,FALSE);
9356
9357   /* if the value is already in a pointer register
9358        then don't need anything more */
9359     if (!AOP_INPREG(AOP(left))) {
9360         /* otherwise get a free pointer register */
9361         aop = newAsmop(0);
9362         preg = getFreePtr(ic,&aop,FALSE);
9363         pic16_emitcode("mov","%s,%s",
9364                 preg->name,
9365                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9366         rname = preg->name ;
9367     } else
9368         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9369     
9370     pic16_freeAsmop(left,NULL,ic,TRUE);
9371     pic16_aopOp (result,ic,FALSE);
9372
9373     /* if bitfield then unpack the bits */
9374     if (IS_BITFIELD(retype)) 
9375         genUnpackBits (result,rname,PPOINTER);
9376     else {
9377         /* we have can just get the values */
9378         int size = AOP_SIZE(result);
9379         int offset = 0 ;        
9380         
9381         while (size--) {
9382             
9383             pic16_emitcode("movx","a,@%s",rname);
9384             pic16_aopPut(AOP(result),"a",offset);
9385             
9386             offset++ ;
9387             
9388             if (size)
9389                 pic16_emitcode("inc","%s",rname);
9390         }
9391     }
9392
9393     /* now some housekeeping stuff */
9394     if (aop) {
9395         /* we had to allocate for this iCode */
9396         pic16_freeAsmop(NULL,aop,ic,TRUE);
9397     } else { 
9398         /* we did not allocate which means left
9399            already in a pointer register, then
9400            if size > 0 && this could be used again
9401            we have to point it back to where it 
9402            belongs */
9403         if (AOP_SIZE(result) > 1 &&
9404             !OP_SYMBOL(left)->remat &&
9405             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9406               ic->depth )) {
9407             int size = AOP_SIZE(result) - 1;
9408             while (size--)
9409                 pic16_emitcode("dec","%s",rname);
9410         }
9411     }
9412
9413     /* done */
9414     pic16_freeAsmop(result,NULL,ic,TRUE);
9415     
9416         
9417 }
9418
9419 /*-----------------------------------------------------------------*/
9420 /* genFarPointerGet - gget value from far space                    */
9421 /*-----------------------------------------------------------------*/
9422 static void genFarPointerGet (operand *left,
9423                               operand *result, iCode *ic)
9424 {
9425     int size, offset ;
9426     sym_link *retype = getSpec(operandType(result));
9427
9428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9429
9430     pic16_aopOp(left,ic,FALSE);
9431
9432     /* if the operand is already in dptr 
9433     then we do nothing else we move the value to dptr */
9434     if (AOP_TYPE(left) != AOP_STR) {
9435         /* if this is remateriazable */
9436         if (AOP_TYPE(left) == AOP_IMMD)
9437             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9438         else { /* we need to get it byte by byte */
9439             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9440             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9441             if (options.model == MODEL_FLAT24)
9442             {
9443                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9444             }
9445         }
9446     }
9447     /* so dptr know contains the address */
9448     pic16_freeAsmop(left,NULL,ic,TRUE);
9449     pic16_aopOp(result,ic,FALSE);
9450
9451     /* if bit then unpack */
9452     if (IS_BITFIELD(retype)) 
9453         genUnpackBits(result,"dptr",FPOINTER);
9454     else {
9455         size = AOP_SIZE(result);
9456         offset = 0 ;
9457
9458         while (size--) {
9459             pic16_emitcode("movx","a,@dptr");
9460             pic16_aopPut(AOP(result),"a",offset++);
9461             if (size)
9462                 pic16_emitcode("inc","dptr");
9463         }
9464     }
9465
9466     pic16_freeAsmop(result,NULL,ic,TRUE);
9467 }
9468 #if 0
9469 /*-----------------------------------------------------------------*/
9470 /* genCodePointerGet - get value from code space                  */
9471 /*-----------------------------------------------------------------*/
9472 static void genCodePointerGet (operand *left,
9473                                 operand *result, iCode *ic)
9474 {
9475     int size, offset ;
9476     sym_link *retype = getSpec(operandType(result));
9477
9478     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9479
9480     pic16_aopOp(left,ic,FALSE);
9481
9482     /* if the operand is already in dptr 
9483     then we do nothing else we move the value to dptr */
9484     if (AOP_TYPE(left) != AOP_STR) {
9485         /* if this is remateriazable */
9486         if (AOP_TYPE(left) == AOP_IMMD)
9487             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9488         else { /* we need to get it byte by byte */
9489             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9490             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9491             if (options.model == MODEL_FLAT24)
9492             {
9493                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9494             }
9495         }
9496     }
9497     /* so dptr know contains the address */
9498     pic16_freeAsmop(left,NULL,ic,TRUE);
9499     pic16_aopOp(result,ic,FALSE);
9500
9501     /* if bit then unpack */
9502     if (IS_BITFIELD(retype)) 
9503         genUnpackBits(result,"dptr",CPOINTER);
9504     else {
9505         size = AOP_SIZE(result);
9506         offset = 0 ;
9507
9508         while (size--) {
9509             pic16_emitcode("clr","a");
9510             pic16_emitcode("movc","a,@a+dptr");
9511             pic16_aopPut(AOP(result),"a",offset++);
9512             if (size)
9513                 pic16_emitcode("inc","dptr");
9514         }
9515     }
9516
9517     pic16_freeAsmop(result,NULL,ic,TRUE);
9518 }
9519 #endif
9520 /*-----------------------------------------------------------------*/
9521 /* genGenPointerGet - gget value from generic pointer space        */
9522 /*-----------------------------------------------------------------*/
9523 static void genGenPointerGet (operand *left,
9524                               operand *result, iCode *ic)
9525 {
9526   int size, offset, lit;
9527   sym_link *retype = getSpec(operandType(result));
9528
9529         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9530         pic16_aopOp(left,ic,FALSE);
9531         pic16_aopOp(result,ic,FALSE);
9532         size = AOP_SIZE(result);
9533
9534         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9535
9536         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9537
9538                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9539                 // load FSR0 from immediate
9540                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9541
9542 //              pic16_loadFSR0( left );
9543
9544                 offset = 0;
9545                 while(size--) {
9546                         if(size) {
9547                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9548                         } else {
9549                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9550                         }
9551                         offset++;
9552                 }
9553                 goto release;
9554
9555         }
9556         else { /* we need to get it byte by byte */
9557                 // set up FSR0 with address from left
9558                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9559                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9560
9561                 offset = 0 ;
9562
9563                 while(size--) {
9564                         if(size) {
9565                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9566                         } else {
9567                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9568                         }
9569                         offset++;
9570                 }
9571                 goto release;
9572         }
9573
9574   /* if bit then unpack */
9575         if (IS_BITFIELD(retype)) 
9576                 genUnpackBits(result,"BAD",GPOINTER);
9577
9578         release:
9579         pic16_freeAsmop(left,NULL,ic,TRUE);
9580         pic16_freeAsmop(result,NULL,ic,TRUE);
9581
9582 }
9583
9584 /*-----------------------------------------------------------------*/
9585 /* genConstPointerGet - get value from const generic pointer space */
9586 /*-----------------------------------------------------------------*/
9587 static void genConstPointerGet (operand *left,
9588                                 operand *result, iCode *ic)
9589 {
9590   //sym_link *retype = getSpec(operandType(result));
9591   // symbol *albl = newiTempLabel(NULL);        // patch 15
9592   // symbol *blbl = newiTempLabel(NULL);        //
9593   // PIC_OPCODE poc;                            // patch 15
9594   int size;
9595   int offset = 0;
9596
9597   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9598   pic16_aopOp(left,ic,FALSE);
9599   pic16_aopOp(result,ic,TRUE);
9600   size = AOP_SIZE(result);
9601
9602   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9603
9604   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9605 #if 0                                                                   // patch 15
9606   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9607   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9608   pic16_emitpLabel(albl->key);
9609
9610   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9611     
9612   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9613   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9614   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9615   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9616   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9617
9618   pic16_emitpLabel(blbl->key);
9619
9620   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9621 #endif                                                                  // patch 15
9622
9623
9624   // set up table pointer
9625   if( (AOP_TYPE(left) == AOP_PCODE) 
9626       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9627           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9628     {
9629       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9630       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9631       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9632       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9633       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9634       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9635     }
9636   else
9637     {
9638       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9639       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9640       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9641     }
9642
9643
9644   while(size--)
9645     {
9646       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9647       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9648       offset++;
9649     }
9650     
9651   pic16_freeAsmop(left,NULL,ic,TRUE);
9652   pic16_freeAsmop(result,NULL,ic,TRUE);
9653
9654 }
9655
9656
9657 /*-----------------------------------------------------------------*/
9658 /* genPointerGet - generate code for pointer get                   */
9659 /*-----------------------------------------------------------------*/
9660 static void genPointerGet (iCode *ic)
9661 {
9662     operand *left, *result ;
9663     sym_link *type, *etype;
9664     int p_type;
9665
9666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9667
9668     left = IC_LEFT(ic);
9669     result = IC_RESULT(ic) ;
9670
9671     /* depending on the type of pointer we need to
9672     move it to the correct pointer register */
9673     type = operandType(left);
9674     etype = getSpec(type);
9675
9676 #if 0
9677     if (IS_PTR_CONST(type))
9678 #else
9679     if (IS_CODEPTR(type))
9680 #endif
9681       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9682
9683     /* if left is of type of pointer then it is simple */
9684     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9685         p_type = DCL_TYPE(type);
9686     else {
9687         /* we have to go by the storage class */
9688         p_type = PTR_TYPE(SPEC_OCLS(etype));
9689
9690         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9691
9692         if (SPEC_OCLS(etype)->codesp ) {
9693           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9694           //p_type = CPOINTER ; 
9695         }
9696         else
9697             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9698               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9699                /*p_type = FPOINTER ;*/ 
9700             else
9701                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9702                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9703 /*                  p_type = PPOINTER; */
9704                 else
9705                     if (SPEC_OCLS(etype) == idata )
9706                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9707 /*                      p_type = IPOINTER; */
9708                     else
9709                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9710 /*                      p_type = POINTER ; */
9711     }
9712
9713     /* now that we have the pointer type we assign
9714     the pointer values */
9715     switch (p_type) {
9716
9717     case POINTER:       
9718     case IPOINTER:
9719         genNearPointerGet (left,result,ic);
9720         break;
9721
9722     case PPOINTER:
9723         genPagedPointerGet(left,result,ic);
9724         break;
9725
9726     case FPOINTER:
9727         genFarPointerGet (left,result,ic);
9728         break;
9729
9730     case CPOINTER:
9731         genConstPointerGet (left,result,ic);
9732         //pic16_emitcodePointerGet (left,result,ic);
9733         break;
9734
9735     case GPOINTER:
9736 #if 0
9737       if (IS_PTR_CONST(type))
9738         genConstPointerGet (left,result,ic);
9739       else
9740 #endif
9741         genGenPointerGet (left,result,ic);
9742       break;
9743
9744     default:
9745       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9746               "genPointerGet: illegal pointer type");
9747     
9748     }
9749
9750 }
9751
9752 /*-----------------------------------------------------------------*/
9753 /* genPackBits - generates code for packed bit storage             */
9754 /*-----------------------------------------------------------------*/
9755 static void genPackBits (sym_link    *etype ,
9756                          operand *right ,
9757                          char *rname, int p_type)
9758 {
9759   int shCnt = 0 ;
9760   int offset = 0  ;
9761   int rLen = 0 ;
9762   int blen, bstr ;   
9763   char *l ;
9764
9765         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9766         blen = SPEC_BLEN(etype);
9767         bstr = SPEC_BSTR(etype);
9768
9769         if(AOP_TYPE(right) == AOP_LIT) {
9770                 if((blen == 1) && (bstr < 8)) {
9771                   unsigned long lit;
9772                         /* it is a single bit, so use the appropriate bit instructions */
9773
9774                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9775
9776                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9777 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9778                         if(lit) {
9779                                 pic16_emitpcode(POC_BSF,
9780                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9781                         } else {
9782                                 pic16_emitpcode(POC_BCF,
9783                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9784                         }
9785         
9786                   return;
9787                 }
9788
9789                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9790                 offset++;
9791         } else
9792                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9793
9794         /* if the bit lenth is less than or    */
9795         /* it exactly fits a byte then         */
9796         if((shCnt=SPEC_BSTR(etype))
9797                 || SPEC_BLEN(etype) <= 8 )  {
9798
9799                 /* shift left acc */
9800                 AccLsh(shCnt);
9801
9802                 /* using PRODL as a temporary register here */
9803                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9804
9805                 switch (p_type) {
9806                         case FPOINTER:
9807                         case POINTER:
9808                         case GPOINTER:
9809                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9810 //                              pic16_emitcode ("mov","b,a");
9811 //                              pic16_emitcode("mov","a,@%s",rname);
9812                                 break;
9813                 }
9814 #if 1
9815                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9816                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9817                                         (unsigned char)(0xff >> (8-bstr))) ));
9818                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9819                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9820 #endif
9821
9822           return;
9823         }
9824
9825
9826         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9827         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9828         exit(-1);
9829
9830
9831     /* if we r done */
9832     if ( SPEC_BLEN(etype) <= 8 )
9833         return ;
9834
9835     pic16_emitcode("inc","%s",rname);
9836     rLen = SPEC_BLEN(etype) ;     
9837
9838
9839
9840     /* now generate for lengths greater than one byte */
9841     while (1) {
9842
9843         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9844
9845         rLen -= 8 ;
9846         if (rLen <= 0 )
9847             break ;
9848
9849         switch (p_type) {
9850             case POINTER:
9851                 if (*l == '@') {
9852                     MOVA(l);
9853                     pic16_emitcode("mov","@%s,a",rname);
9854                 } else
9855                     pic16_emitcode("mov","@%s,%s",rname,l);
9856                 break;
9857
9858             case FPOINTER:
9859                 MOVA(l);
9860                 pic16_emitcode("movx","@dptr,a");
9861                 break;
9862
9863             case GPOINTER:
9864                 MOVA(l);
9865                 DEBUGpic16_emitcode(";lcall","__gptrput");
9866                 break;  
9867         }   
9868         pic16_emitcode ("inc","%s",rname);
9869     }
9870
9871     MOVA(l);
9872
9873     /* last last was not complete */
9874     if (rLen)   {
9875         /* save the byte & read byte */
9876         switch (p_type) {
9877             case POINTER:
9878                 pic16_emitcode ("mov","b,a");
9879                 pic16_emitcode("mov","a,@%s",rname);
9880                 break;
9881
9882             case FPOINTER:
9883                 pic16_emitcode ("mov","b,a");
9884                 pic16_emitcode("movx","a,@dptr");
9885                 break;
9886
9887             case GPOINTER:
9888                 pic16_emitcode ("push","b");
9889                 pic16_emitcode ("push","acc");
9890                 pic16_emitcode ("lcall","__gptrget");
9891                 pic16_emitcode ("pop","b");
9892                 break;
9893         }
9894
9895         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9896         pic16_emitcode ("orl","a,b");
9897     }
9898
9899     if (p_type == GPOINTER)
9900         pic16_emitcode("pop","b");
9901
9902     switch (p_type) {
9903
9904     case POINTER:
9905         pic16_emitcode("mov","@%s,a",rname);
9906         break;
9907         
9908     case FPOINTER:
9909         pic16_emitcode("movx","@dptr,a");
9910         break;
9911         
9912     case GPOINTER:
9913         DEBUGpic16_emitcode(";lcall","__gptrput");
9914         break;                  
9915     }
9916 }
9917 /*-----------------------------------------------------------------*/
9918 /* genDataPointerSet - remat pointer to data space                 */
9919 /*-----------------------------------------------------------------*/
9920 static void genDataPointerSet(operand *right,
9921                               operand *result,
9922                               iCode *ic)
9923 {
9924     int size, offset = 0, resoffset=0 ;
9925
9926     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9927     pic16_aopOp(right,ic,FALSE);
9928
9929     size = AOP_SIZE(right);
9930
9931 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9932
9933 #if 0
9934     if ( AOP_TYPE(result) == AOP_PCODE) {
9935       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9936               AOP(result)->aopu.pcop->name,
9937                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9938               PCOR(AOP(result)->aopu.pcop)->instance:
9939               PCOI(AOP(result)->aopu.pcop)->offset);
9940     }
9941 #endif
9942
9943         if(AOP(result)->aopu.pcop->type == PO_DIR)
9944                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9945
9946         while (size--) {
9947                 if (AOP_TYPE(right) == AOP_LIT) {
9948                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9949
9950                         lit = lit >> (8*offset);
9951                         if(lit&0xff) {
9952                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9953                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9954                         } else {
9955                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9956                         }
9957                 } else {
9958                         mov2w(AOP(right), offset);
9959                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9960                 }
9961                 offset++;
9962                 resoffset++;
9963         }
9964
9965     pic16_freeAsmop(right,NULL,ic,TRUE);
9966 }
9967
9968
9969
9970 /*-----------------------------------------------------------------*/
9971 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9972 /*-----------------------------------------------------------------*/
9973 static void genNearPointerSet (operand *right,
9974                                operand *result, 
9975                                iCode *ic)
9976 {
9977   asmop *aop = NULL;
9978   char *l;
9979   sym_link *retype;
9980   sym_link *ptype = operandType(result);
9981   sym_link *resetype;
9982     
9983         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9984         retype= getSpec(operandType(right));
9985         resetype = getSpec(operandType(result));
9986   
9987         pic16_aopOp(result,ic,FALSE);
9988     
9989         /* if the result is rematerializable &
9990          * in data space & not a bit variable */
9991         
9992         /* and result is not a bit variable */
9993         if (AOP_TYPE(result) == AOP_PCODE
9994 //              && AOP_TYPE(result) == AOP_IMMD
9995                 && DCL_TYPE(ptype) == POINTER
9996                 && !IS_BITFIELD(retype)
9997                 && !IS_BITFIELD(resetype)) {
9998
9999                 genDataPointerSet (right,result,ic);
10000                 pic16_freeAsmop(result,NULL,ic,TRUE);
10001           return;
10002         }
10003
10004         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10005         pic16_aopOp(right,ic,FALSE);
10006         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10007
10008         /* if the value is already in a pointer register
10009          * then don't need anything more */
10010         if (!AOP_INPREG(AOP(result))) {
10011                 /* otherwise get a free pointer register */
10012                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10013
10014                 if( (AOP_TYPE(result) == AOP_PCODE) 
10015                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10016                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10017                 {
10018                         pic16_loadFSR0( result );  // patch 10
10019                 } else {
10020                         // set up FSR0 with address of result
10021                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10022                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10023                 }
10024
10025         }
10026 //      else
10027 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10028
10029         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10030
10031         /* if bitfield then unpack the bits */
10032         if (IS_BITFIELD(resetype)) {
10033                 genPackBits (resetype, right, NULL, POINTER);
10034         } else {
10035                 /* we have can just get the values */
10036           int size = AOP_SIZE(right);
10037           int offset = 0 ;    
10038
10039                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10040                 while (size--) {
10041                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10042                         if (*l == '@' ) {
10043                                 //MOVA(l);
10044                                 //pic16_emitcode("mov","@%s,a",rname);
10045                                 pic16_emitcode("movf","indf0,w ;1");
10046                         } else {
10047
10048                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10049                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10050                                         if (size) {                                                                     // 
10051                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10052                                         } else {                                                                        // 
10053                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10054                                         }                                                                               // 
10055                                 } else { // no literal                                                                  // 
10056                                         if(size) {                                                                      // 
10057                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10058                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10059                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10060                                         } else {                                                                        // 
10061                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10062                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10063                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10064                                         }                                                                               //
10065                                 }                                                                                       // patch 10
10066                         }
10067                         offset++;
10068                 }
10069         }
10070
10071         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10072         /* now some housekeeping stuff */
10073         if (aop) {
10074                 /* we had to allocate for this iCode */
10075                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10076         } else { 
10077                 /* we did not allocate which means left
10078                  * already in a pointer register, then
10079                  * if size > 0 && this could be used again
10080                  * we have to point it back to where it 
10081                  * belongs */
10082                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10083                 if (AOP_SIZE(right) > 1
10084                         && !OP_SYMBOL(result)->remat
10085                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10086                                 || ic->depth )) {
10087
10088                   int size = AOP_SIZE(right) - 1;
10089
10090                         while (size--)
10091                                 pic16_emitcode("decf","fsr0,f");
10092                         //pic16_emitcode("dec","%s",rname);
10093                 }
10094         }
10095
10096         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10097         /* done */
10098 //release:
10099         pic16_freeAsmop(right,NULL,ic,TRUE);
10100         pic16_freeAsmop(result,NULL,ic,TRUE);
10101 }
10102
10103 /*-----------------------------------------------------------------*/
10104 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10105 /*-----------------------------------------------------------------*/
10106 static void genPagedPointerSet (operand *right,
10107                                operand *result, 
10108                                iCode *ic)
10109 {
10110     asmop *aop = NULL;
10111     regs *preg = NULL ;
10112     char *rname , *l;
10113     sym_link *retype;
10114        
10115     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10116
10117     retype= getSpec(operandType(right));
10118     
10119     pic16_aopOp(result,ic,FALSE);
10120     
10121     /* if the value is already in a pointer register
10122        then don't need anything more */
10123     if (!AOP_INPREG(AOP(result))) {
10124         /* otherwise get a free pointer register */
10125         aop = newAsmop(0);
10126         preg = getFreePtr(ic,&aop,FALSE);
10127         pic16_emitcode("mov","%s,%s",
10128                 preg->name,
10129                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10130         rname = preg->name ;
10131     } else
10132         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10133     
10134     pic16_freeAsmop(result,NULL,ic,TRUE);
10135     pic16_aopOp (right,ic,FALSE);
10136
10137     /* if bitfield then unpack the bits */
10138     if (IS_BITFIELD(retype)) 
10139         genPackBits (retype,right,rname,PPOINTER);
10140     else {
10141         /* we have can just get the values */
10142         int size = AOP_SIZE(right);
10143         int offset = 0 ;        
10144         
10145         while (size--) {
10146             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10147             
10148             MOVA(l);
10149             pic16_emitcode("movx","@%s,a",rname);
10150
10151             if (size)
10152                 pic16_emitcode("inc","%s",rname);
10153
10154             offset++;
10155         }
10156     }
10157     
10158     /* now some housekeeping stuff */
10159     if (aop) {
10160         /* we had to allocate for this iCode */
10161         pic16_freeAsmop(NULL,aop,ic,TRUE);
10162     } else { 
10163         /* we did not allocate which means left
10164            already in a pointer register, then
10165            if size > 0 && this could be used again
10166            we have to point it back to where it 
10167            belongs */
10168         if (AOP_SIZE(right) > 1 &&
10169             !OP_SYMBOL(result)->remat &&
10170             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10171               ic->depth )) {
10172             int size = AOP_SIZE(right) - 1;
10173             while (size--)
10174                 pic16_emitcode("dec","%s",rname);
10175         }
10176     }
10177
10178     /* done */
10179     pic16_freeAsmop(right,NULL,ic,TRUE);
10180     
10181         
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genFarPointerSet - set value from far space                     */
10186 /*-----------------------------------------------------------------*/
10187 static void genFarPointerSet (operand *right,
10188                               operand *result, iCode *ic)
10189 {
10190     int size, offset ;
10191     sym_link *retype = getSpec(operandType(right));
10192
10193     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10194     pic16_aopOp(result,ic,FALSE);
10195
10196     /* if the operand is already in dptr 
10197     then we do nothing else we move the value to dptr */
10198     if (AOP_TYPE(result) != AOP_STR) {
10199         /* if this is remateriazable */
10200         if (AOP_TYPE(result) == AOP_IMMD)
10201             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10202         else { /* we need to get it byte by byte */
10203             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10204             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10205             if (options.model == MODEL_FLAT24)
10206             {
10207                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10208             }
10209         }
10210     }
10211     /* so dptr know contains the address */
10212     pic16_freeAsmop(result,NULL,ic,TRUE);
10213     pic16_aopOp(right,ic,FALSE);
10214
10215     /* if bit then unpack */
10216     if (IS_BITFIELD(retype)) 
10217         genPackBits(retype,right,"dptr",FPOINTER);
10218     else {
10219         size = AOP_SIZE(right);
10220         offset = 0 ;
10221
10222         while (size--) {
10223             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10224             MOVA(l);
10225             pic16_emitcode("movx","@dptr,a");
10226             if (size)
10227                 pic16_emitcode("inc","dptr");
10228         }
10229     }
10230
10231     pic16_freeAsmop(right,NULL,ic,TRUE);
10232 }
10233
10234 /*-----------------------------------------------------------------*/
10235 /* genGenPointerSet - set value from generic pointer space         */
10236 /*-----------------------------------------------------------------*/
10237 static void genGenPointerSet (operand *right,
10238                               operand *result, iCode *ic)
10239 {
10240         int i, size, offset, lit;
10241         sym_link *retype = getSpec(operandType(right));
10242
10243         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10244
10245         pic16_aopOp(result,ic,FALSE);
10246         pic16_aopOp(right,ic,FALSE);
10247         size = AOP_SIZE(right);
10248         offset = 0;
10249
10250         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10251
10252         /* if the operand is already in dptr 
10253                 then we do nothing else we move the value to dptr */
10254         if (AOP_TYPE(result) != AOP_STR) {
10255                 /* if this is remateriazable */
10256                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10257                 // WARNING: anythig until "else" is untested!
10258                 if (AOP_TYPE(result) == AOP_IMMD) {
10259                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10260                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10261                         // load FSR0 from immediate
10262                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10263                         offset = 0;
10264                         while(size--) {
10265                                 if(size) {
10266                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10267                                 } else {
10268                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10269                                 }
10270                                 offset++;
10271                         }
10272                         goto release;
10273                 }
10274                 else { /* we need to get it byte by byte */
10275                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10276                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10277
10278                         // set up FSR0 with address of result
10279                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10280                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10281
10282                         /* hack hack! see if this the FSR. If so don't load W */
10283                         if(AOP_TYPE(right) != AOP_ACC) {
10284
10285                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10286
10287                                 if(AOP_TYPE(right) == AOP_LIT)
10288                                 {
10289                                         // copy literal
10290                                         // note: pic16_popGet handles sign extension
10291                                         for(i=0;i<size;i++) {
10292                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10293                                                 if(i < size-1)
10294                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10295                                                 else
10296                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10297                                         }
10298                                 } else {
10299                                         // copy regs
10300
10301                                         for(i=0;i<size;i++) {
10302                                                 if(i < size-1)
10303                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10304                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10305                                                 else
10306                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10307                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10308                                         }
10309                                 }
10310                                 goto release;
10311                         } 
10312                         // right = ACC
10313                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10314                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10315                         goto release;
10316         } // if (AOP_TYPE(result) != AOP_IMMD)
10317
10318         } // if (AOP_TYPE(result) != AOP_STR)
10319         /* so dptr know contains the address */
10320
10321
10322         /* if bit then unpack */
10323         if (IS_BITFIELD(retype)) 
10324                 genPackBits(retype,right,"dptr",GPOINTER);
10325         else {
10326                 size = AOP_SIZE(right);
10327                 offset = 0 ;
10328
10329                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10330
10331                 // set up FSR0 with address of result
10332                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10333                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10334         
10335                 while (size--) {
10336                         if (AOP_TYPE(right) == AOP_LIT) {
10337                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10338                                 if (size) {
10339                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10340                                 } else {
10341                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10342                                 }
10343                         } else { // no literal
10344                                 if(size) {
10345                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10346                                 } else {
10347                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10348                                 }
10349                         }
10350                         offset++;
10351                 }
10352         }
10353
10354         release:
10355         pic16_freeAsmop(right,NULL,ic,TRUE);
10356         pic16_freeAsmop(result,NULL,ic,TRUE);
10357 }
10358
10359 /*-----------------------------------------------------------------*/
10360 /* genPointerSet - stores the value into a pointer location        */
10361 /*-----------------------------------------------------------------*/
10362 static void genPointerSet (iCode *ic)
10363 {    
10364     operand *right, *result ;
10365     sym_link *type, *etype;
10366     int p_type;
10367
10368     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10369
10370     right = IC_RIGHT(ic);
10371     result = IC_RESULT(ic) ;
10372
10373     /* depending on the type of pointer we need to
10374     move it to the correct pointer register */
10375     type = operandType(result);
10376     etype = getSpec(type);
10377     /* if left is of type of pointer then it is simple */
10378     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10379         p_type = DCL_TYPE(type);
10380     }
10381     else {
10382         /* we have to go by the storage class */
10383         p_type = PTR_TYPE(SPEC_OCLS(etype));
10384
10385 /*      if (SPEC_OCLS(etype)->codesp ) { */
10386 /*          p_type = CPOINTER ;  */
10387 /*      } */
10388 /*      else */
10389 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10390 /*              p_type = FPOINTER ; */
10391 /*          else */
10392 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10393 /*                  p_type = PPOINTER ; */
10394 /*              else */
10395 /*                  if (SPEC_OCLS(etype) == idata ) */
10396 /*                      p_type = IPOINTER ; */
10397 /*                  else */
10398 /*                      p_type = POINTER ; */
10399     }
10400
10401     /* now that we have the pointer type we assign
10402     the pointer values */
10403     switch (p_type) {
10404
10405     case POINTER:
10406     case IPOINTER:
10407         genNearPointerSet (right,result,ic);
10408         break;
10409
10410     case PPOINTER:
10411         genPagedPointerSet (right,result,ic);
10412         break;
10413
10414     case FPOINTER:
10415         genFarPointerSet (right,result,ic);
10416         break;
10417
10418     case GPOINTER:
10419         genGenPointerSet (right,result,ic);
10420         break;
10421
10422     default:
10423       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10424               "genPointerSet: illegal pointer type");
10425     }
10426 }
10427
10428 /*-----------------------------------------------------------------*/
10429 /* genIfx - generate code for Ifx statement                        */
10430 /*-----------------------------------------------------------------*/
10431 static void genIfx (iCode *ic, iCode *popIc)
10432 {
10433   operand *cond = IC_COND(ic);
10434   int isbit =0;
10435
10436   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10437
10438   pic16_aopOp(cond,ic,FALSE);
10439
10440   /* get the value into acc */
10441   if (AOP_TYPE(cond) != AOP_CRY)
10442     pic16_toBoolean(cond);
10443   else
10444     isbit = 1;
10445   /* the result is now in the accumulator */
10446   pic16_freeAsmop(cond,NULL,ic,TRUE);
10447
10448   /* if there was something to be popped then do it */
10449   if (popIc)
10450     genIpop(popIc);
10451
10452   /* if the condition is  a bit variable */
10453   if (isbit && IS_ITEMP(cond) && 
10454       SPIL_LOC(cond)) {
10455     genIfxJump(ic,SPIL_LOC(cond)->rname);
10456     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10457   }
10458   else {
10459     if (isbit && !IS_ITEMP(cond))
10460       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10461     else
10462       genIfxJump(ic,"a");
10463   }
10464   ic->generated = 1;
10465
10466 }
10467
10468 /*-----------------------------------------------------------------*/
10469 /* genAddrOf - generates code for address of                       */
10470 /*-----------------------------------------------------------------*/
10471 static void genAddrOf (iCode *ic)
10472 {
10473   operand *result, *left;
10474   int size;
10475   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10476   pCodeOp *pcop0, *pcop1, *pcop2;
10477
10478         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10479
10480         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10481         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10482
10483         sym = OP_SYMBOL( left );
10484
10485         size = AOP_SIZE(IC_RESULT(ic));
10486
10487 //      if(pic16_debug_verbose) {
10488 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10489 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10490 //      }
10491         
10492         /* Assume that what we want the address of is in data space
10493          * since there is no stack on the PIC, yet! -- VR */
10494         /* low */
10495         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10496
10497         /* high */
10498         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10499         
10500         /* upper */
10501         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10502         
10503
10504         if (size == 3) {
10505                 pic16_emitpcode(POC_MOVLW, pcop0);
10506                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10507                 pic16_emitpcode(POC_MOVLW, pcop1);
10508                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10509                 pic16_emitpcode(POC_MOVLW, pcop2);
10510                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10511         } else
10512         if (size == 2) {
10513                 pic16_emitpcode(POC_MOVLW, pcop0);
10514                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10515                 pic16_emitpcode(POC_MOVLW, pcop1);
10516                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10517         } else {
10518                 pic16_emitpcode(POC_MOVLW, pcop0);
10519                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10520         }
10521
10522         pic16_freeAsmop(result,NULL,ic,TRUE);
10523         pic16_freeAsmop(left, NULL, ic, FALSE);
10524 }
10525
10526
10527 #if 0
10528 /*-----------------------------------------------------------------*/
10529 /* genFarFarAssign - assignment when both are in far space         */
10530 /*-----------------------------------------------------------------*/
10531 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10532 {
10533     int size = AOP_SIZE(right);
10534     int offset = 0;
10535     char *l ;
10536     /* first push the right side on to the stack */
10537     while (size--) {
10538         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10539         MOVA(l);
10540         pic16_emitcode ("push","acc");
10541     }
10542     
10543     pic16_freeAsmop(right,NULL,ic,FALSE);
10544     /* now assign DPTR to result */
10545     pic16_aopOp(result,ic,FALSE);
10546     size = AOP_SIZE(result);
10547     while (size--) {
10548         pic16_emitcode ("pop","acc");
10549         pic16_aopPut(AOP(result),"a",--offset);
10550     }
10551     pic16_freeAsmop(result,NULL,ic,FALSE);
10552         
10553 }
10554 #endif
10555
10556 /*-----------------------------------------------------------------*/
10557 /* genAssign - generate code for assignment                        */
10558 /*-----------------------------------------------------------------*/
10559 static void genAssign (iCode *ic)
10560 {
10561   operand *result, *right;
10562   int size, offset,know_W;
10563   unsigned long lit = 0L;
10564
10565   result = IC_RESULT(ic);
10566   right  = IC_RIGHT(ic) ;
10567
10568   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10569   
10570   /* if they are the same */
10571   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10572     return ;
10573
10574   pic16_aopOp(right,ic,FALSE);
10575   pic16_aopOp(result,ic,TRUE);
10576
10577   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10578
10579   /* if they are the same registers */
10580   if (pic16_sameRegs(AOP(right),AOP(result)))
10581     goto release;
10582
10583   /* if the result is a bit */
10584   if (AOP_TYPE(result) == AOP_CRY) {
10585     /* if the right size is a literal then
10586        we know what the value is */
10587     if (AOP_TYPE(right) == AOP_LIT) {
10588           
10589       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10590                   pic16_popGet(AOP(result),0));
10591
10592       if (((int) operandLitValue(right))) 
10593         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10594                        AOP(result)->aopu.aop_dir,
10595                        AOP(result)->aopu.aop_dir);
10596       else
10597         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10598                        AOP(result)->aopu.aop_dir,
10599                        AOP(result)->aopu.aop_dir);
10600       goto release;
10601     }
10602
10603     /* the right is also a bit variable */
10604     if (AOP_TYPE(right) == AOP_CRY) {
10605       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10606       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10607       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10608
10609       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10610                      AOP(result)->aopu.aop_dir,
10611                      AOP(result)->aopu.aop_dir);
10612       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10613                      AOP(right)->aopu.aop_dir,
10614                      AOP(right)->aopu.aop_dir);
10615       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10616                      AOP(result)->aopu.aop_dir,
10617                      AOP(result)->aopu.aop_dir);
10618       goto release ;
10619     }
10620
10621     /* we need to or */
10622     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10623     pic16_toBoolean(right);
10624     emitSKPZ;
10625     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10626     //pic16_aopPut(AOP(result),"a",0);
10627     goto release ;
10628   }
10629
10630   /* bit variables done */
10631   /* general case */
10632   size = AOP_SIZE(result);
10633   offset = 0 ;
10634
10635   if(AOP_TYPE(right) == AOP_LIT) {
10636         if(!IS_FLOAT(operandType( right )))
10637                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10638         else {
10639            union {
10640               unsigned long lit_int;
10641               float lit_float;
10642             } info;
10643         
10644                 /* take care if literal is a float */
10645                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10646                 lit = info.lit_int;
10647         }
10648   }
10649
10650 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10651 //                      sizeof(unsigned long int), sizeof(float));
10652
10653   if(AOP_TYPE(right) != AOP_LIT
10654         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10655         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10656
10657         // set up table pointer
10658         if( (AOP_TYPE(right) == AOP_PCODE)
10659                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10660                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10661         {
10662                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10663                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10664                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10665                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10666                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10667                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10668         } else {
10669                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10670                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10671                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10672                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10673                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10674                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10675         }
10676
10677         size = min(AOP_SIZE(right), AOP_SIZE(result));
10678         while(size--) {
10679                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10680                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10681                         pic16_popGet(AOP(result),offset)));
10682                 offset++;
10683         }
10684
10685         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10686                 size = AOP_SIZE(result) - AOP_SIZE(right);
10687                 while(size--) {
10688                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10689                         offset++;
10690                 }
10691         }
10692         goto release;
10693   }
10694
10695
10696
10697 /* VR - What is this?! */
10698   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10699   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10700     if(aopIdx(AOP(result),0) == 4) {
10701   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10702         assert(0);
10703       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10704       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10705       goto release;
10706     } else
10707 //      assert(0);
10708       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10709   }
10710
10711   know_W=-1;
10712   while (size--) {
10713   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10714     if(AOP_TYPE(right) == AOP_LIT) {
10715       if(lit&0xff) {
10716         if(know_W != (lit&0xff))
10717           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10718         know_W = lit&0xff;
10719         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10720       } else
10721         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10722
10723       lit >>= 8;
10724
10725     } else if (AOP_TYPE(right) == AOP_CRY) {
10726       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10727       if(offset == 0) {
10728         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10729         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10730       }
10731     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10732         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10733         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10734     } else {
10735   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10736
10737 #if 1
10738         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10739            normally should work, but mind that the W register live range
10740            is not checked, so if the code generator assumes that the W
10741            is already loaded after such a pair, wrong code will be generated.
10742            
10743            Checking the live range is the next step.
10744            This is experimental code yet and has not been fully tested yet.
10745            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10746            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10747            
10748         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10749 #else   
10750         /* This is the old code, which is assumed(?!) that works fine(!?) */
10751
10752         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10753         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10754 #endif
10755     }
10756             
10757     offset++;
10758   }
10759
10760     
10761  release:
10762   pic16_freeAsmop (right,NULL,ic,FALSE);
10763   pic16_freeAsmop (result,NULL,ic,TRUE);
10764 }   
10765
10766 /*-----------------------------------------------------------------*/
10767 /* genJumpTab - generates code for jump table                       */
10768 /*-----------------------------------------------------------------*/
10769 static void genJumpTab (iCode *ic)
10770 {
10771     symbol *jtab;
10772     char *l;
10773
10774     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10775
10776     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10777     /* get the condition into accumulator */
10778     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10779     MOVA(l);
10780     /* multiply by three */
10781     pic16_emitcode("add","a,acc");
10782     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10783
10784     jtab = newiTempLabel(NULL);
10785     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10786     pic16_emitcode("jmp","@a+dptr");
10787     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10788
10789     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10790     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10791     emitSKPNC;
10792     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10793     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10794     pic16_emitpLabel(jtab->key);
10795
10796     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10797
10798     /* now generate the jump labels */
10799     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10800          jtab = setNextItem(IC_JTLABELS(ic))) {
10801         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10802         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10803         
10804     }
10805
10806 }
10807
10808 /*-----------------------------------------------------------------*/
10809 /* genMixedOperation - gen code for operators between mixed types  */
10810 /*-----------------------------------------------------------------*/
10811 /*
10812   TSD - Written for the PIC port - but this unfortunately is buggy.
10813   This routine is good in that it is able to efficiently promote 
10814   types to different (larger) sizes. Unfortunately, the temporary
10815   variables that are optimized out by this routine are sometimes
10816   used in other places. So until I know how to really parse the 
10817   iCode tree, I'm going to not be using this routine :(.
10818 */
10819 static int genMixedOperation (iCode *ic)
10820 {
10821 #if 0
10822   operand *result = IC_RESULT(ic);
10823   sym_link *ctype = operandType(IC_LEFT(ic));
10824   operand *right = IC_RIGHT(ic);
10825   int ret = 0;
10826   int big,small;
10827   int offset;
10828
10829   iCode *nextic;
10830   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10831
10832   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10833
10834   nextic = ic->next;
10835   if(!nextic)
10836     return 0;
10837
10838   nextright = IC_RIGHT(nextic);
10839   nextleft  = IC_LEFT(nextic);
10840   nextresult = IC_RESULT(nextic);
10841
10842   pic16_aopOp(right,ic,FALSE);
10843   pic16_aopOp(result,ic,FALSE);
10844   pic16_aopOp(nextright,  nextic, FALSE);
10845   pic16_aopOp(nextleft,   nextic, FALSE);
10846   pic16_aopOp(nextresult, nextic, FALSE);
10847
10848   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10849
10850     operand *t = right;
10851     right = nextright;
10852     nextright = t; 
10853
10854     pic16_emitcode(";remove right +","");
10855
10856   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10857 /*
10858     operand *t = right;
10859     right = nextleft;
10860     nextleft = t; 
10861 */
10862     pic16_emitcode(";remove left +","");
10863   } else
10864     return 0;
10865
10866   big = AOP_SIZE(nextleft);
10867   small = AOP_SIZE(nextright);
10868
10869   switch(nextic->op) {
10870
10871   case '+':
10872     pic16_emitcode(";optimize a +","");
10873     /* if unsigned or not an integral type */
10874     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10875       pic16_emitcode(";add a bit to something","");
10876     } else {
10877
10878       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10879
10880       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10881         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10882         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10883       } else
10884         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10885
10886       offset = 0;
10887       while(--big) {
10888
10889         offset++;
10890
10891         if(--small) {
10892           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10893             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10894             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10895           }
10896
10897           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10898           emitSKPNC;
10899           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10900                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10901                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10902           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10903           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10904
10905         } else {
10906           pic16_emitcode("rlf","known_zero,w");
10907
10908           /*
10909             if right is signed
10910               btfsc  right,7
10911                addlw ff
10912           */
10913           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10914             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10915             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10916           } else {
10917             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10918           }
10919         }
10920       }
10921       ret = 1;
10922     }
10923   }
10924   ret = 1;
10925
10926 release:
10927   pic16_freeAsmop(right,NULL,ic,TRUE);
10928   pic16_freeAsmop(result,NULL,ic,TRUE);
10929   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10930   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10931   if(ret)
10932     nextic->generated = 1;
10933
10934   return ret;
10935 #else
10936   return 0;
10937 #endif
10938 }
10939 /*-----------------------------------------------------------------*/
10940 /* genCast - gen code for casting                                  */
10941 /*-----------------------------------------------------------------*/
10942 static void genCast (iCode *ic)
10943 {
10944   operand *result = IC_RESULT(ic);
10945   sym_link *ctype = operandType(IC_LEFT(ic));
10946   sym_link *rtype = operandType(IC_RIGHT(ic));
10947   operand *right = IC_RIGHT(ic);
10948   int size, offset ;
10949
10950         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10951         /* if they are equivalent then do nothing */
10952         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10953                 return ;
10954
10955         pic16_aopOp(right,ic,FALSE) ;
10956         pic16_aopOp(result,ic,FALSE);
10957
10958         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10959
10960         /* if the result is a bit */
10961         if (AOP_TYPE(result) == AOP_CRY) {
10962         
10963                 /* if the right size is a literal then
10964                  * we know what the value is */
10965                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10966
10967                 if (AOP_TYPE(right) == AOP_LIT) {
10968                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10969                                 pic16_popGet(AOP(result),0));
10970
10971                         if (((int) operandLitValue(right))) 
10972                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10973                                         AOP(result)->aopu.aop_dir,
10974                                         AOP(result)->aopu.aop_dir);
10975                         else
10976                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10977                                         AOP(result)->aopu.aop_dir,
10978                                         AOP(result)->aopu.aop_dir);
10979                         goto release;
10980                 }
10981
10982                 /* the right is also a bit variable */
10983                 if (AOP_TYPE(right) == AOP_CRY) {
10984                         emitCLRC;
10985                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10986
10987                         pic16_emitcode("clrc","");
10988                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10989                                 AOP(right)->aopu.aop_dir,
10990                                 AOP(right)->aopu.aop_dir);
10991                         pic16_aopPut(AOP(result),"c",0);
10992                         goto release ;
10993                 }
10994
10995                 /* we need to or */
10996                 if (AOP_TYPE(right) == AOP_REG) {
10997                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10998                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10999                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11000                 }
11001                 pic16_toBoolean(right);
11002                 pic16_aopPut(AOP(result),"a",0);
11003                 goto release ;
11004         }
11005
11006         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11007           int offset = 1;
11008
11009                 size = AOP_SIZE(result);
11010
11011                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11012
11013                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11014                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11015                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11016
11017                 while (size--)
11018                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11019
11020                 goto release;
11021         }
11022
11023         /* if they are the same size : or less */
11024         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11025
11026                 /* if they are in the same place */
11027                 if (pic16_sameRegs(AOP(right),AOP(result)))
11028                         goto release;
11029
11030                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11031 #if 0
11032                 if (IS_PTR_CONST(rtype))
11033 #else
11034                 if (IS_CODEPTR(rtype))
11035 #endif
11036                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11037
11038 #if 0
11039                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11040 #else
11041                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11042 #endif
11043                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11044
11045 #if 0
11046                 if(AOP_TYPE(right) == AOP_IMMD) {
11047                   pCodeOp *pcop0, *pcop1, *pcop2;
11048                   symbol *sym = OP_SYMBOL( right );
11049
11050                         size = AOP_SIZE(result);
11051                         /* low */
11052                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11053                         /* high */
11054                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11055                         /* upper */
11056                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11057         
11058                         if (size == 3) {
11059                                 pic16_emitpcode(POC_MOVLW, pcop0);
11060                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11061                                 pic16_emitpcode(POC_MOVLW, pcop1);
11062                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11063                                 pic16_emitpcode(POC_MOVLW, pcop2);
11064                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11065                         } else
11066                         if (size == 2) {
11067                                 pic16_emitpcode(POC_MOVLW, pcop0);
11068                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11069                                 pic16_emitpcode(POC_MOVLW, pcop1);
11070                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11071                         } else {
11072                                 pic16_emitpcode(POC_MOVLW, pcop0);
11073                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11074                         }
11075                 } else
11076 #endif
11077                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11078                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11079                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11080                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11081                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11082                         if(AOP_SIZE(result) <2)
11083                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11084                 } else {
11085                         /* if they in different places then copy */
11086                         size = AOP_SIZE(result);
11087                         offset = 0 ;
11088                         while (size--) {
11089                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11090                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11091                                 offset++;
11092                         }
11093                 }
11094                 goto release;
11095         }
11096
11097         /* if the result is of type pointer */
11098         if (IS_PTR(ctype)) {
11099           int p_type;
11100           sym_link *type = operandType(right);
11101           sym_link *etype = getSpec(type);
11102
11103                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11104
11105                 /* pointer to generic pointer */
11106                 if (IS_GENPTR(ctype)) {
11107                   char *l = zero;
11108             
11109                         if (IS_PTR(type)) 
11110                                 p_type = DCL_TYPE(type);
11111                         else {
11112                 /* we have to go by the storage class */
11113                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11114
11115 /*              if (SPEC_OCLS(etype)->codesp )  */
11116 /*                  p_type = CPOINTER ;  */
11117 /*              else */
11118 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11119 /*                      p_type = FPOINTER ; */
11120 /*                  else */
11121 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11122 /*                          p_type = PPOINTER; */
11123 /*                      else */
11124 /*                          if (SPEC_OCLS(etype) == idata ) */
11125 /*                              p_type = IPOINTER ; */
11126 /*                          else */
11127 /*                              p_type = POINTER ; */
11128             }
11129                 
11130             /* the first two bytes are known */
11131       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11132             size = GPTRSIZE - 1; 
11133             offset = 0 ;
11134             while (size--) {
11135               if(offset < AOP_SIZE(right)) {
11136       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11137                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11138                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11139                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11140                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11141                 } else { 
11142                   pic16_aopPut(AOP(result),
11143                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11144                          offset);
11145                 }
11146               } else 
11147                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11148               offset++;
11149             }
11150             /* the last byte depending on type */
11151             switch (p_type) {
11152             case IPOINTER:
11153             case POINTER:
11154                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11155                 break;
11156             case FPOINTER:
11157               pic16_emitcode(";BUG!? ","%d",__LINE__);
11158                 l = one;
11159                 break;
11160             case CPOINTER:
11161               pic16_emitcode(";BUG!? ","%d",__LINE__);
11162                 l = "#0x02";
11163                 break;                          
11164             case PPOINTER:
11165               pic16_emitcode(";BUG!? ","%d",__LINE__);
11166                 l = "#0x03";
11167                 break;
11168                 
11169             default:
11170                 /* this should never happen */
11171                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11172                        "got unknown pointer type");
11173                 exit(1);
11174             }
11175             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11176             goto release ;
11177         }
11178         
11179         /* just copy the pointers */
11180         size = AOP_SIZE(result);
11181         offset = 0 ;
11182         while (size--) {
11183             pic16_aopPut(AOP(result),
11184                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11185                    offset);
11186             offset++;
11187         }
11188         goto release ;
11189     }
11190     
11191
11192
11193     /* so we now know that the size of destination is greater
11194     than the size of the source.
11195     Now, if the next iCode is an operator then we might be
11196     able to optimize the operation without performing a cast.
11197     */
11198     if(genMixedOperation(ic))
11199       goto release;
11200
11201     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11202     
11203     /* we move to result for the size of source */
11204     size = AOP_SIZE(right);
11205     offset = 0 ;
11206     while (size--) {
11207       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11208       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11209       offset++;
11210     }
11211
11212     /* now depending on the sign of the destination */
11213     size = AOP_SIZE(result) - AOP_SIZE(right);
11214     /* if unsigned or not an integral type */
11215     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11216       while (size--)
11217         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11218     } else {
11219       /* we need to extend the sign :( */
11220
11221       if(size == 1) {
11222         /* Save one instruction of casting char to int */
11223         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11224         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11225         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11226       } else {
11227         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11228
11229         if(offset)
11230           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11231         else
11232           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11233         
11234         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11235
11236         while (size--)
11237           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11238       }
11239     }
11240
11241 release:
11242     pic16_freeAsmop(right,NULL,ic,TRUE);
11243     pic16_freeAsmop(result,NULL,ic,TRUE);
11244
11245 }
11246
11247 /*-----------------------------------------------------------------*/
11248 /* genDjnz - generate decrement & jump if not zero instrucion      */
11249 /*-----------------------------------------------------------------*/
11250 static int genDjnz (iCode *ic, iCode *ifx)
11251 {
11252     symbol *lbl, *lbl1;
11253     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11254
11255     if (!ifx)
11256         return 0;
11257     
11258     /* if the if condition has a false label
11259        then we cannot save */
11260     if (IC_FALSE(ifx))
11261         return 0;
11262
11263     /* if the minus is not of the form 
11264        a = a - 1 */
11265     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11266         !IS_OP_LITERAL(IC_RIGHT(ic)))
11267         return 0;
11268
11269     if (operandLitValue(IC_RIGHT(ic)) != 1)
11270         return 0;
11271
11272     /* if the size of this greater than one then no
11273        saving */
11274     if (getSize(operandType(IC_RESULT(ic))) > 1)
11275         return 0;
11276
11277     /* otherwise we can save BIG */
11278     lbl = newiTempLabel(NULL);
11279     lbl1= newiTempLabel(NULL);
11280
11281     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11282     
11283     if (IS_AOP_PREG(IC_RESULT(ic))) {
11284         pic16_emitcode("dec","%s",
11285                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11286         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11287         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11288     } else {    
11289
11290
11291       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11292       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11293
11294       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11295       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11296
11297     }
11298 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11299 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11300 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11301 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11302
11303     
11304     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11305     ifx->generated = 1;
11306     return 1;
11307 }
11308
11309 /*-----------------------------------------------------------------*/
11310 /* genReceive - generate code for a receive iCode                  */
11311 /*-----------------------------------------------------------------*/
11312 static void genReceive (iCode *ic)
11313 {    
11314         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11315
11316         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11317                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11318                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11319
11320           int size = getSize(operandType(IC_RESULT(ic)));
11321           int offset =  pic16_fReturnSizePic - size;
11322
11323                 while (size--) {
11324                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11325                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11326                         offset++;
11327                 }
11328
11329                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11330
11331                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11332                 size = AOP_SIZE(IC_RESULT(ic));
11333                 offset = 0;
11334                 while (size--) {
11335                         pic16_emitcode ("pop","acc");
11336                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11337                 }
11338         } else {
11339                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11340
11341                 _G.accInUse++;
11342                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11343                 _G.accInUse--;
11344                 assignResultValue(IC_RESULT(ic), 0);
11345         }
11346
11347         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11348 }
11349
11350 /*-----------------------------------------------------------------*/
11351 /* genDummyRead - generate code for dummy read of volatiles        */
11352 /*-----------------------------------------------------------------*/
11353 static void
11354 genDummyRead (iCode * ic)
11355 {
11356   pic16_emitcode ("; genDummyRead","");
11357   pic16_emitcode ("; not implemented","");
11358
11359   ic = ic;
11360 }
11361
11362 /*-----------------------------------------------------------------*/
11363 /* genpic16Code - generate code for pic16 based controllers        */
11364 /*-----------------------------------------------------------------*/
11365 /*
11366  * At this point, ralloc.c has gone through the iCode and attempted
11367  * to optimize in a way suitable for a PIC. Now we've got to generate
11368  * PIC instructions that correspond to the iCode.
11369  *
11370  * Once the instructions are generated, we'll pass through both the
11371  * peep hole optimizer and the pCode optimizer.
11372  *-----------------------------------------------------------------*/
11373
11374 void genpic16Code (iCode *lic)
11375 {
11376     iCode *ic;
11377     int cln = 0;
11378
11379     lineHead = lineCurr = NULL;
11380
11381     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11382     pic16_addpBlock(pb);
11383
11384 #if 0
11385     /* if debug information required */
11386     if (options.debug && currFunc) {
11387       if (currFunc) {
11388         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11389       }
11390     }
11391 #endif
11392
11393     for (ic = lic ; ic ; ic = ic->next ) {
11394
11395       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11396         if ( cln != ic->lineno ) {
11397             if ( options.debug ) {
11398               debugFile->writeCLine (ic);
11399             }
11400             
11401             if(!options.noCcodeInAsm) {
11402                 pic16_addpCode2pBlock(pb,
11403                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11404                                 printCLine(ic->filename, ic->lineno)));
11405             }
11406
11407             cln = ic->lineno ;
11408         }
11409         
11410         if(options.iCodeInAsm) {
11411                 char *l;
11412                 /* insert here code to print iCode as comment */
11413                 l = Safe_strdup(printILine(ic));
11414                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11415         }
11416         
11417         /* if the result is marked as
11418            spilt and rematerializable or code for
11419            this has already been generated then
11420            do nothing */
11421         if (resultRemat(ic) || ic->generated ) 
11422             continue ;
11423         
11424         /* depending on the operation */
11425         switch (ic->op) {
11426         case '!' :
11427             pic16_genNot(ic);
11428             break;
11429             
11430         case '~' :
11431             pic16_genCpl(ic);
11432             break;
11433             
11434         case UNARYMINUS:
11435             genUminus (ic);
11436             break;
11437             
11438         case IPUSH:
11439             genIpush (ic);
11440             break;
11441             
11442         case IPOP:
11443             /* IPOP happens only when trying to restore a 
11444                spilt live range, if there is an ifx statement
11445                following this pop then the if statement might
11446                be using some of the registers being popped which
11447                would destroy the contents of the register so
11448                we need to check for this condition and handle it */
11449             if (ic->next            && 
11450                 ic->next->op == IFX &&
11451                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11452                 genIfx (ic->next,ic);
11453             else
11454                 genIpop (ic);
11455             break; 
11456             
11457         case CALL:
11458             genCall (ic);
11459             break;
11460             
11461         case PCALL:
11462             genPcall (ic);
11463             break;
11464             
11465         case FUNCTION:
11466             genFunction (ic);
11467             break;
11468             
11469         case ENDFUNCTION:
11470             genEndFunction (ic);
11471             break;
11472             
11473         case RETURN:
11474             genRet (ic);
11475             break;
11476             
11477         case LABEL:
11478             genLabel (ic);
11479             break;
11480             
11481         case GOTO:
11482             genGoto (ic);
11483             break;
11484             
11485         case '+' :
11486             pic16_genPlus (ic) ;
11487             break;
11488             
11489         case '-' :
11490             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11491                 pic16_genMinus (ic);
11492             break;
11493             
11494         case '*' :
11495             genMult (ic);
11496             break;
11497             
11498         case '/' :
11499             genDiv (ic) ;
11500             break;
11501             
11502         case '%' :
11503             genMod (ic);
11504             break;
11505             
11506         case '>' :
11507             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11508             break;
11509             
11510         case '<' :
11511             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11512             break;
11513             
11514         case LE_OP:
11515         case GE_OP:
11516         case NE_OP:
11517             
11518             /* note these two are xlated by algebraic equivalence
11519                during parsing SDCC.y */
11520             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11521                    "got '>=' or '<=' shouldn't have come here");
11522             break;      
11523             
11524         case EQ_OP:
11525             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11526             break;          
11527             
11528         case AND_OP:
11529             genAndOp (ic);
11530             break;
11531             
11532         case OR_OP:
11533             genOrOp (ic);
11534             break;
11535             
11536         case '^' :
11537             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11538             break;
11539             
11540         case '|' :
11541                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11542             break;
11543             
11544         case BITWISEAND:
11545             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11546             break;
11547             
11548         case INLINEASM:
11549             genInline (ic);
11550             break;
11551             
11552         case RRC:
11553             genRRC (ic);
11554             break;
11555             
11556         case RLC:
11557             genRLC (ic);
11558             break;
11559             
11560         case GETHBIT:
11561             genGetHbit (ic);
11562             break;
11563             
11564         case LEFT_OP:
11565             genLeftShift (ic);
11566             break;
11567             
11568         case RIGHT_OP:
11569             genRightShift (ic);
11570             break;
11571             
11572         case GET_VALUE_AT_ADDRESS:
11573             genPointerGet(ic);
11574             break;
11575             
11576         case '=' :
11577             if (POINTER_SET(ic))
11578                 genPointerSet(ic);
11579             else
11580                 genAssign(ic);
11581             break;
11582             
11583         case IFX:
11584             genIfx (ic,NULL);
11585             break;
11586             
11587         case ADDRESS_OF:
11588             genAddrOf (ic);
11589             break;
11590             
11591         case JUMPTABLE:
11592             genJumpTab (ic);
11593             break;
11594             
11595         case CAST:
11596             genCast (ic);
11597             break;
11598             
11599         case RECEIVE:
11600             genReceive(ic);
11601             break;
11602             
11603         case SEND:
11604             addSet(&_G.sendSet,ic);
11605             break;
11606
11607         case DUMMY_READ_VOLATILE:
11608           genDummyRead (ic);
11609           break;
11610
11611         default :
11612             ic = ic;
11613         }
11614     }
11615
11616
11617     /* now we are ready to call the
11618        peep hole optimizer */
11619     if (!options.nopeep) {
11620       peepHole (&lineHead);
11621     }
11622     /* now do the actual printing */
11623     printLine (lineHead,codeOutFile);
11624
11625 #ifdef PCODE_DEBUG
11626     DFPRINTF((stderr,"printing pBlock\n\n"));
11627     pic16_printpBlock(stdout,pb);
11628 #endif
11629
11630     return;
11631 }
11632